[object Object]

← back to Raffiawallcoverings

snapshot before fleet-grid refine

4b8736ac7d43b69b496a5d6d78a82a08e3c76aad · 2026-05-11 03:03:19 -0700 · Steve Abrams

Files touched

Diff

commit 4b8736ac7d43b69b496a5d6d78a82a08e3c76aad
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon May 11 03:03:19 2026 -0700

    snapshot before fleet-grid refine
---
 public/care.html                                |  55 ++
 public/history.html                             |  58 ++
 public/index.html.bak.dwfoot.1778203445693      | 962 +++++++++++++++++++++++
 public/index.html.bak.gtagev.1778426585635      | 970 +++++++++++++++++++++++
 public/index.html.bak.ns-canonical              | 977 ++++++++++++++++++++++++
 public/index.html.bak.nspropagate.1778203385140 | 947 +++++++++++++++++++++++
 public/index.html.bak.nspropagate.1778209715073 | 962 +++++++++++++++++++++++
 public/index.html.bak.nspropagate.1778226815171 | 964 +++++++++++++++++++++++
 public/index.html.bak.nspropagate.1778226888822 | 966 +++++++++++++++++++++++
 public/index.html.pre-sort-frontend             | 850 +++++++++++++++++++++
 public/sourcing.html                            |  49 ++
 public/trade.html                               |  55 ++
 public/vocabulary.html                          |  64 ++
 server.js.pre-sort-skill                        | 159 ++++
 14 files changed, 8038 insertions(+)

diff --git a/public/care.html b/public/care.html
new file mode 100644
index 0000000..13f23e0
--- /dev/null
+++ b/public/care.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html lang="en"><head>
+<!-- editorial-gen v1 -->
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Care &amp; installation — raffiawallcoverings.com</title>
+<meta name="description" content="Care &amp; installation — Soft as raffia. Made slowly.">
+<link rel="canonical" href="https://raffiawallcoverings.com/care">
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:ui-serif;background:#F2EDE2;color:#1a1410;line-height:1.65;padding:60px 24px;min-height:100vh}
+.wrap{max-width:720px;margin:0 auto}
+.eyebrow{font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:#9B7B4F;margin-bottom:18px}
+h1{font-family:'Saol Display', serif;font-style:italic;font-size:48px;line-height:1.1;letter-spacing:-0.02em;color:#1a1410;margin-bottom:32px}
+h2{font-family:'Saol Display', serif;font-size:22px;color:#9B7B4F;margin:36px 0 12px;font-weight:500}
+p{margin-bottom:16px;color:#3a322c}
+ul{margin:12px 0 20px 18px}
+li{margin-bottom:8px;color:#3a322c}
+strong{color:#1a1410}
+a{color:#9B7B4F;text-decoration:underline;text-underline-offset:3px}
+nav.foot{margin-top:56px;padding-top:24px;border-top:1px solid rgba(0,0,0,0.10);font-size:11px;letter-spacing:0.18em;text-transform:uppercase}
+nav.foot a{margin-right:22px;text-decoration:none}
+</style>
+</head><body>
+<div class="wrap">
+<div class="eyebrow">Editorial · care · Corteza</div>
+<h1>Care &amp; installation</h1>
+<p>Corteza raffia wallcoverings are crafted for enduring beauty and thoughtful presence. Their installation and care require patience, precision, and a gentle hand. This guide offers direct, actionable advice for every stage of the process, from preparation to preservation.</p>
+
+<h2>Substrate Preparation</h2>
+<p>Begin with a clean, dry, and smooth surface. Remove any existing wallpaper, paint, or residue that could compromise adhesion. Ensure the wall is free of dust, grease, and moisture. For best results, apply a thin, even coat of sizing or primer designed for natural fibers. This step creates a stable base and enhances the bond between the raffia and the wall.</p>
+
+<h2>Paste Type</h2>
+<p>Use a wheat-based or water-soluble adhesive formulated for natural materials. Avoid adhesives containing harsh solvents or synthetic resins, which may degrade the raffia over time. Apply the paste evenly to the back of the wallcovering, working in small sections to prevent drying before application. Press the raffia firmly against the wall, smoothing out air bubbles and ensuring full contact.</p>
+
+<h2>Seam Handling</h2>
+<p>Align seams carefully, overlapping them by 1–2 inches to allow for natural variation in the raffia’s texture. Use a seam roller to press the overlap firmly, ensuring a secure bond. If necessary, apply a small amount of adhesive to the seam’s edge and press again. Avoid stretching or pulling the material, as this may distort the design or cause tearing. Trim excess at the edges with a utility knife for a clean finish.</p>
+
+<h2>Cleaning</h2>
+<p>Wipe the surface with a soft, damp cloth to remove dust or light debris. For stubborn stains, use a mild soap solution (diluted to a few drops per quart of water) and gently dab the affected area. Avoid scrubbing, soaking, or using abrasive cleaners, which may damage the fibers. Dry immediately with a clean, dry cloth. Never use steam cleaners, solvents, or harsh chemicals.</p>
+
+<h2>Light Exposure</h2>
+<p>Expose the wallcovering to indirect light whenever possible. Prolonged exposure to direct sunlight may cause fading or discoloration over time. If the room receives significant sunlight, consider using UV-filtering window films or sheer curtains to protect the surface. Avoid placing the wallcovering near heat sources, radiators, or areas with high humidity, which can lead to warping or mold.</p>
+
+<h2>Expected Lifespan</h2>
+<p>With proper care, Corteza raffia wallcoverings can last 10–15 years in low-traffic areas. In high-traffic or frequently used spaces, the lifespan may be shorter, depending on exposure to moisture, abrasion, and light. Regular maintenance, such as gentle cleaning and avoiding direct sunlight, will help preserve the material’s integrity and visual appeal. If damage occurs, repair sections promptly to prevent further degradation.</p>
+<nav class="foot">
+<a href="/">Browse</a>
+<a href="/history">History</a>
+<a href="/vocabulary">Vocabulary</a>
+<a href="/sourcing">Sourcing</a>
+<a href="/care">Care</a>
+<a href="/trade">Trade</a>
+<a href="/about">About</a>
+</nav>
+</div></body></html>
\ No newline at end of file
diff --git a/public/history.html b/public/history.html
new file mode 100644
index 0000000..e5b9568
--- /dev/null
+++ b/public/history.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html lang="en"><head>
+<!-- editorial-gen v1 -->
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>A short history — raffiawallcoverings.com</title>
+<meta name="description" content="A short history — Soft as raffia. Made slowly.">
+<link rel="canonical" href="https://raffiawallcoverings.com/history">
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:ui-serif;background:#F2EDE2;color:#1a1410;line-height:1.65;padding:60px 24px;min-height:100vh}
+.wrap{max-width:720px;margin:0 auto}
+.eyebrow{font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:#9B7B4F;margin-bottom:18px}
+h1{font-family:'Saol Display', serif;font-style:italic;font-size:48px;line-height:1.1;letter-spacing:-0.02em;color:#1a1410;margin-bottom:32px}
+h2{font-family:'Saol Display', serif;font-size:22px;color:#9B7B4F;margin:36px 0 12px;font-weight:500}
+p{margin-bottom:16px;color:#3a322c}
+ul{margin:12px 0 20px 18px}
+li{margin-bottom:8px;color:#3a322c}
+strong{color:#1a1410}
+a{color:#9B7B4F;text-decoration:underline;text-underline-offset:3px}
+nav.foot{margin-top:56px;padding-top:24px;border-top:1px solid rgba(0,0,0,0.10);font-size:11px;letter-spacing:0.18em;text-transform:uppercase}
+nav.foot a{margin-right:22px;text-decoration:none}
+</style>
+</head><body>
+<div class="wrap">
+<div class="eyebrow">Editorial · history · Corteza</div>
+<h1>A short history</h1>
+<p>Raffia, that supple and sun-warmed fiber, has long been a quiet companion to the spaces where people gather, rest, and create. Its history as a wallcovering is not one of grand gestures, but of subtlety—of hands weaving together the raw and the refined, the ancestral and the modern. From the humid workshops of West Africa to the stark geometries of Bauhaus studios, raffia has shaped interiors with a presence that is neither loud nor forgotten. This is the story of its journey through time, a thread pulled from the loom of tradition into the tapestry of design.</p>
+
+<h2>The Roots: Raffia in Pre-Industrial Hands</h2>  
+<p>Long before raffia found its way into the parlors of Europe, it was a staple of life in regions where the raffia palm thrived. In Central and West Africa, the fiber was plaited into mats, baskets, and ceremonial objects, its resilience and flexibility making it indispensable. These early uses were not decorative but functional—a testament to the material’s utility. By the 19th century, European traders and explorers began to notice the artistry of these woven objects, sparking a fascination that would eventually translate into interior design. However, it was not until the late 1800s that raffia began to appear on walls, its natural sheen and organic form offering a contrast to the rigid geometries of industrial design.</p>  
+
+<ul>  
+  <li>In the 1870s, French missionaries in Gabon documented the use of raffia in village homes, where it was layered into wall panels to insulate against the heat.</li>  
+  <li>By the 1890s, European manufacturers had begun importing raffia from the Congo Free State, experimenting with its potential for interior applications.</li>  
+  <li>Early examples in European homes were often mixed with other fibers, a hybrid approach that hinted at the material’s versatility.</li>  
+</ul>  
+
+<h2>The Arts & Crafts Movement: A Return to the Handmade</h2>  
+<p>The Arts & Crafts movement of the late 19th and early 20th centuries provided a fertile ground for raffia’s reimagining. Designers like William Morris and his contemporaries sought to reject the mechanization of production, favoring the tactile and the human-made. While Morris himself did not use raffia, his emphasis on natural materials and handcraft influenced a wave of artisans who explored the fiber’s potential. In Britain and Scandinavia, workshops began to experiment with raffia as a wallcovering, weaving it into panels that mimicked the look of reed or bamboo. These early applications were often seen in domestic spaces, where they complemented the era’s love of organic forms and hand-painted details.</p>  
+
+<ul>  
+  <li>In the 1900s, the Danish designer Kaare Klint incorporated raffia into his furniture designs, though its use on walls was limited to experimental projects.</li>  
+  <li>German and Austrian artisans, inspired by the Arts & Crafts ethos, began to produce raffia wallcoverings that emphasized the fiber’s natural grain and irregularity.</li>  
+  <li>These early efforts were often bespoke, created for private homes rather than mass production, reflecting the movement’s disdain for uniformity.</li>  
+</ul>  
+
+<h2>Bauhaus and the Modernist Turn</h2>  
+<p>The
+<nav class="foot">
+<a href="/">Browse</a>
+<a href="/history">History</a>
+<a href="/vocabulary">Vocabulary</a>
+<a href="/sourcing">Sourcing</a>
+<a href="/care">Care</a>
+<a href="/trade">Trade</a>
+<a href="/about">About</a>
+</nav>
+</div></body></html>
\ No newline at end of file
diff --git a/public/index.html.bak.dwfoot.1778203445693 b/public/index.html.bak.dwfoot.1778203445693
new file mode 100644
index 0000000..2295dd3
--- /dev/null
+++ b/public/index.html.bak.dwfoot.1778203445693
@@ -0,0 +1,962 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@novasuede.com?subject=Novasuede%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@novasuede.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Raffia Wallcoverings</div>
+      <p class="footer-text">Raffia Wallcoverings is a specialty raffia archive within the Designer Wallcoverings family. Real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.bak.gtagev.1778426585635 b/public/index.html.bak.gtagev.1778426585635
new file mode 100644
index 0000000..74750bc
--- /dev/null
+++ b/public/index.html.bak.gtagev.1778426585635
@@ -0,0 +1,970 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <link rel="icon" type="image/svg+xml" href="/favicon.svg">
+
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@raffiawallcoverings.com?subject=Corteza%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@raffiawallcoverings.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Corteza</div>
+      <p class="footer-text">Corteza — real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.bak.ns-canonical b/public/index.html.bak.ns-canonical
new file mode 100644
index 0000000..d6381a2
--- /dev/null
+++ b/public/index.html.bak.ns-canonical
@@ -0,0 +1,977 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <link rel="icon" type="image/svg+xml" href="/favicon.svg">
+
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@raffiawallcoverings.com?subject=Corteza%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@raffiawallcoverings.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Corteza</div>
+      <p class="footer-text">Corteza — real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    try { if (typeof gtag === 'function') gtag('event', 'modal_open', { modal_name: name, sku: (opts && opts.sku) || '' }); } catch(_){}
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      try {
+        if (typeof gtag === 'function') {
+          if (kind === 'sample') gtag('event', 'memo_request', { sku: data.sku || '', title: data.title || '' });
+          else gtag('event', 'lead', { form_type: kind });
+        }
+      } catch(_){}
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.bak.nspropagate.1778203385140 b/public/index.html.bak.nspropagate.1778203385140
new file mode 100644
index 0000000..3c24ae9
--- /dev/null
+++ b/public/index.html.bak.nspropagate.1778203385140
@@ -0,0 +1,947 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<header class="ns-header">
+        <a href="#home" class="ns-brand" aria-label="Corteza home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="#home">Home</a>
+            <a href="#colors">Colors</a>
+            <a href="#specifications">Specifications</a>
+            <a href="fire-ratings.html">Fire Ratings</a>
+            <a href="faq.html">FAQ</a>
+            <a href="about.html">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@novasuede.com?subject=Novasuede%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@novasuede.com · Designer Wallcoverings</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Raffia Wallcoverings</div>
+      <p class="footer-text">Raffia Wallcoverings is a specialty raffia archive within the Designer Wallcoverings family. Real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.bak.nspropagate.1778209715073 b/public/index.html.bak.nspropagate.1778209715073
new file mode 100644
index 0000000..c129110
--- /dev/null
+++ b/public/index.html.bak.nspropagate.1778209715073
@@ -0,0 +1,962 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@novasuede.com?subject=Novasuede%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@novasuede.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Corteza</div>
+      <p class="footer-text">Corteza — real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.bak.nspropagate.1778226815171 b/public/index.html.bak.nspropagate.1778226815171
new file mode 100644
index 0000000..c998368
--- /dev/null
+++ b/public/index.html.bak.nspropagate.1778226815171
@@ -0,0 +1,964 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@raffiawallcoverings.com?subject=Corteza%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@raffiawallcoverings.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Corteza</div>
+      <p class="footer-text">Corteza — real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.bak.nspropagate.1778226888822 b/public/index.html.bak.nspropagate.1778226888822
new file mode 100644
index 0000000..dd75a83
--- /dev/null
+++ b/public/index.html.bak.nspropagate.1778226888822
@@ -0,0 +1,966 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #a98b5b 0%, #5d4c32 60%, #332a1b 100%); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav { display: flex; gap: 32px; align-items: center; list-style: none; padding: 0; margin: 0; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; padding: 0 !important; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        @media (max-width: 820px) { .ns-header { padding: 14px 18px; } .ns-nav { gap: 16px; } .ns-nav a, .ns-nav button { font-size: 13px !important; } }
+        @media (max-width: 760px) {
+          .ns-header { flex-wrap: wrap; }
+          .ns-nav { display: none !important; flex-basis: 100%; flex-direction: column; align-items: flex-start; gap: 6px; padding: 14px 0 4px; }
+          .ns-nav.open { display: flex !important; }
+          .ns-nav a, .ns-nav button { padding: 10px 0 !important; border-bottom: 1px solid rgba(245,241,232,0.08); width: 100%; text-align: left; }
+          .ns-nav a:nth-child(n+5), .ns-nav button:nth-child(n+5) { display: block !important; }
+          .ns-header .mobile-toggle { display: flex !important; }
+        }
+        @media (min-width: 761px) {
+          .ns-header .mobile-toggle { display: none !important; }
+        }
+        .ns-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.78); z-index: 200; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(6px); }
+        .ns-modal.show { display: flex; }
+        .ns-modal-card { max-width: 460px; width: 100%; background: #141414 !important; border: 1px solid rgba(245,241,232,0.14); border-radius: 6px; padding: 28px 30px 30px; position: relative; }
+        .ns-modal-card .close-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; background: none; border: 1px solid rgba(245,241,232,0.18); color: rgba(245,241,232,0.6) !important; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
+        .ns-modal-card .close-x:hover { color: #ffffff !important; border-color: #ffffff; }
+        .ns-modal-card h3 { font-family: -apple-system, "SF Pro Display", system-ui; font-weight: 300 !important; font-size: 22px !important; margin: 0 0 6px !important; color: #f5f1e8 !important; }
+        .ns-modal-card .sub { color: rgba(245,241,232,0.65) !important; font-size: 13px; margin: 0 0 22px; }
+        .ns-actions { display: flex; flex-direction: column; gap: 10px; }
+        .ns-action { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: rgba(245,241,232,0.04) !important; border: 1px solid rgba(245,241,232,0.12) !important; color: #f5f1e8 !important; text-decoration: none !important; cursor: pointer; transition: all 200ms; font: inherit; text-align: left; }
+        .ns-action:hover { background: rgba(245,241,232,0.08) !important; border-color: #d4b683 !important; }
+        .ns-action .ico { width: 32px; height: 32px; border-radius: 50%; background: rgba(212,182,131,0.12); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; }
+        .ns-action .txt { flex: 1; }
+        .ns-action .txt b { display: block; font-weight: 500; font-size: 14px; color: #f5f1e8 !important; }
+        .ns-action .txt span { font-size: 12px; color: rgba(245,241,232,0.55) !important; }
+
+        /* ─── FINAL CONTRAST PASS — kill remaining gold-solid + white-island defects ─── */
+        /* Replace all gold-fill accents with off-white (Gucci-aesthetic, no DW gold solids) */
+        .new-badge, .new-arrivals-pill,
+        .color-filter-btn.active,
+        .drapery-btn, .sample-btn-chip, .cb-cta {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        .new-badge:hover, .new-arrivals-pill:hover,
+        .color-filter-btn.active:hover,
+        .drapery-btn:hover, .sample-btn-chip:hover, .cb-cta:hover {
+          background: #fff !important;
+          color: #0a0a0a !important;
+        }
+        /* Gold accents stay only as edge color (links, glyphs) — not fills */
+        a { color: #d4b683; }
+        a:hover { color: #f5d97a; }
+        /* Authorized-dealer footer line — small caps tracked, muted ink, no gold pill */
+        .authorized, .authorized-dealer p {
+          background: transparent !important;
+          color: rgba(245,241,232,0.5) !important;
+          font-size: 10px !important;
+          letter-spacing: 0.22em !important;
+          text-transform: uppercase !important;
+          padding: 0 !important;
+          border: none !important;
+          margin-top: 14px !important;
+        }
+        /* Kill any straggler white bg in info-card / sample-related cards */
+        .info-card, .info-card-link, .care-highlight, .feature-card, .spec-item {
+          background-color: rgba(245,241,232,0.04) !important;
+          border-color: rgba(245,241,232,0.12) !important;
+        }
+        /* Ensure modal content stays readable — Steve's earlier sweep made it #141414 with white text */
+        .modal-content { background: #141414 !important; color: #f5f1e8 !important; }
+        .modal-content * { color: #f5f1e8 !important; }
+        .modal-content input, .modal-content textarea, .modal-content select {
+          background: rgba(245,241,232,0.05) !important;
+          color: #f5f1e8 !important;
+          border-color: rgba(245,241,232,0.2) !important;
+        }
+        .modal-content label { color: rgba(245,241,232,0.6) !important; }
+        /* Force the wide-tracked NOVASUEDE wordmark to stay white */
+        .ns-wordmark, .ns-wordmark sup { color: #f5f1e8 !important; }
+
+        /* ─── Modal-internal contrast (post-QA defects) ─── */
+        /* Backdrop covers full viewport */
+        .modal { width: 100vw !important; height: 100vh !important; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, 0.78) !important; backdrop-filter: blur(6px); }
+        /* Chip — flip from white-on-white island to dark card */
+        .request-chip {
+          background: rgba(245, 241, 232, 0.06) !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.18) !important;
+          border-radius: 4px !important;
+        }
+        .request-chip * { color: #f5f1e8 !important; }
+        .request-chip .chip-swatch {
+          /* swatch dot ALWAYS displays the inline-style hex from JS — fight any sweep */
+          border: 1px solid rgba(0, 0, 0, 0.4) !important;
+        }
+        /* + Add to request — hairline white-border on transparent (no gold) */
+        .add-to-request-btn {
+          background: transparent !important;
+          color: #f5f1e8 !important;
+          border: 1px solid rgba(245, 241, 232, 0.6) !important;
+          border-radius: 0 !important;
+          padding: 12px 22px !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 400 !important;
+        }
+        .add-to-request-btn:hover {
+          background: #f5f1e8 !important;
+          color: #0a0a0a !important;
+          border-color: #f5f1e8 !important;
+        }
+        /* Hex caption visible */
+        .preview-hex, #colorPreviewHex {
+          display: block !important;
+          color: rgba(245, 241, 232, 0.55) !important;
+          font-family: ui-monospace, "SF Mono", Menlo, monospace !important;
+          font-size: 11px !important;
+          margin-top: 4px !important;
+          letter-spacing: 0.04em !important;
+          text-transform: lowercase !important;
+        }
+        /* Color preview name — stays single, prominent */
+        #colorPreviewName {
+          color: #f5f1e8 !important;
+          font-size: 11px !important;
+          letter-spacing: 0.32em !important;
+          text-transform: uppercase !important;
+          font-weight: 500 !important;
+          display: block !important;
+          margin-top: 12px !important;
+        }
+
+        /* ─── Mobile hamburger nav (replaces the overflow at <760px) ─── */
+        @media (max-width: 760px) {
+          header .nav-container { flex-wrap: wrap; }
+          header nav { display: none; flex-basis: 100%; flex-direction: column; gap: 6px; padding: 16px 0 6px; }
+          header nav.open { display: flex; }
+          header nav a { padding: 10px 0; border-bottom: 1px solid rgba(245,241,232,0.1); }
+          header .mobile-toggle {
+            display: flex !important;
+            flex-direction: column;
+            gap: 5px;
+            background: transparent;
+            border: 0;
+            cursor: pointer;
+            padding: 8px;
+          }
+          header .mobile-toggle span {
+            width: 22px; height: 1.5px;
+            background: #f5f1e8;
+            display: block;
+          }
+        }
+        @media (min-width: 761px) {
+          header .mobile-toggle { display: none !important; }
+        }
+
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@raffiawallcoverings.com?subject=Corteza%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@raffiawallcoverings.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Corteza</div>
+      <p class="footer-text">Corteza — real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/index.html.pre-sort-frontend b/public/index.html.pre-sort-frontend
new file mode 100644
index 0000000..c7cf68a
--- /dev/null
+++ b/public/index.html.pre-sort-frontend
@@ -0,0 +1,850 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <link rel="icon" type="image/svg+xml" href="/favicon.svg">
+
+<meta charset="utf-8">
+<!-- Google tag (gtag.js) -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-T1YJPBQ2XY"></script>
+<script>
+  window.dataLayer = window.dataLayer || [];
+  function gtag(){dataLayer.push(arguments);}
+  gtag('js', new Date());
+  gtag('config', 'G-T1YJPBQ2XY');
+</script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Corteza — Soft as raffia. Made slowly.</title>
+<meta name="description" content="Corteza is a curated atelier dedicated entirely to raffia. We do one thing — and we do it carefully.">
+<meta name="theme-color" content="#F2EDE2">
+<link rel="canonical" href="https://raffiawallcoverings.com/">
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@300;400;500;600&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": "Corteza",
+  "url": "https://raffiawallcoverings.com/",
+  "email": "info@raffiawallcoverings.com"
+}
+</script>
+<script src="/zd-loader.js" defer></script>
+<style>
+:root {
+  --bg: #F2EDE2;
+  --paper: #2C1F0F;
+  --muted: #8B7866;
+  --line: #C9BFA7;
+  --accent: #9B7B4F;
+  --bg-soft: #C9BFA7;
+  --cols: 6;
+}
+html[data-theme="dark"] {
+  --bg: #2C1F0F;
+  --paper: #F2EDE2;
+  --muted: #C9B89E;
+  --line: rgba(255,254,250,0.12);
+  --accent: #9B7B4F;
+  --bg-soft: #2a1f15;
+}
+* { margin:0; padding:0; box-sizing:border-box }
+html { scroll-behavior:smooth }
+body { font-family:'Inter', sans-serif; color:var(--paper); -webkit-font-smoothing:antialiased; background:var(--bg); min-height:100vh; overflow-x:hidden }
+/* DW-FASHION-TEMPLATE-OVERRIDE */
+.section-title .accent, .footer-brand, .center-mark, h1, h2, h3 { font-family: 'Libre Baskerville', Georgia, serif !important; font-weight:500 !important;  }
+
+/* ===== Auto-hide header ===== */
+header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 32px; z-index:100; background:rgba(0,0,0,0.55); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); transition:transform .3s }
+.h-link { display:flex; align-items:center; gap:10px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); text-decoration:none; cursor:pointer; background:transparent; border:0 }
+.h-link:hover { opacity:0.7 }
+.h-icon { width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.5 }
+
+/* ===== Cinema hero ===== */
+.cinema { position:relative; height:100vh; width:100%; overflow:hidden }
+.cinema-bg { position:absolute; inset:0; background-size:cover; background-position:center; background-image:url('/hero-bg.jpg') }
+.cinema-bg::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%) }
+.corner-mark { position:absolute; top:24px; left:32px; font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.55), 0 0 1px rgba(0,0,0,0.4); z-index:5 }
+.corner-mark::before { content:"◆ "; margin-right:6px }
+.center-mark { position:absolute; top:clamp(80px,12vh,140px); left:50%; transform:translateX(-50%); font-size:clamp(28px,4vw,56px); font-weight:500; letter-spacing:0.18em; text-transform:uppercase; text-align:center; color:#fff; text-shadow:0 2px 8px rgba(0,0,0,0.65), 0 0 1px rgba(0,0,0,0.5); z-index:5 }
+.center-mark .tm { font-size:14px; vertical-align:super; opacity:0.7; margin-left:0.2em }
+.center-mark .sub { display:block; font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400; font-size:0.4em; letter-spacing:0.04em; text-transform:none; margin-top:14px; opacity:0.85 }
+.meta-line { position:absolute; bottom:32px; left:32px; font-size:10px; letter-spacing:0.28em; text-transform:uppercase; font-weight:700; color:#fff; z-index:5; opacity:0.85 }
+.meta-line .num { font-size:12px; display:block; margin-top:4px; letter-spacing:0.05em }
+.enter { position:absolute; bottom:32px; right:32px; display:flex; align-items:center; gap:14px; font-size:11px; letter-spacing:0.36em; text-transform:uppercase; font-weight:700; color:#fff; text-decoration:none; padding-bottom:6px; border-bottom:1px solid #fff; transition:gap 0.25s; z-index:5 }
+.enter:hover { gap:22px }
+.enter svg { width:24px; height:12px }
+
+/* ===== Section ===== */
+.section { padding:96px 32px }
+.section-header { display:flex; justify-content:space-between; align-items:flex-end; flex-wrap:wrap; gap:24px; margin-bottom:32px; padding-bottom:24px; border-bottom:1px solid var(--line) }
+.section-title { font-size:clamp(36px,5vw,64px); font-weight:300; letter-spacing:-0.02em; line-height:1 }
+.section-title .accent { color: var(--accent); font-family:'Playfair Display', Georgia, serif; font-style:italic; font-weight:400 }
+.section-eyebrow { font-size:10px; letter-spacing:0.4em; text-transform:uppercase; font-weight:700; color:var(--muted); margin-bottom:16px }
+.section-meta { font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:600; color:var(--muted); text-align:right; line-height:1.6 }
+
+/* ===== Filter bar ===== */
+.filters { display:flex; gap:8px; align-items:center; margin-bottom:18px; flex-wrap:wrap }
+.chip { padding:8px 16px; font-size:11px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; color:var(--paper); background:transparent; border:1px solid var(--line); cursor:pointer; transition:all 0.2s; font-family:inherit }
+.chip:hover { border-color:var(--paper) }
+.chip.active { background:var(--paper); color:var(--bg); border-color:var(--paper) }
+.search { flex:0 1 280px; margin-left:auto; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--line); padding:6px 0 }
+.search input { flex:1; background:transparent; border:0; color:var(--paper); font-family:inherit; font-size:13px; outline:none; letter-spacing:0.04em }
+.search input::placeholder { color:var(--muted) }
+.search svg { width:16px; height:16px; stroke:var(--muted); fill:none; stroke-width:1.5 }
+
+/* ===== Grid-density slider ===== */
+.density { display:flex; align-items:center; gap:14px; padding:6px 0; margin-bottom:24px }
+.density label { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--muted) }
+.density input[type=range] { flex:1; max-width:240px; -webkit-appearance:none; appearance:none; height:1px; background:var(--line); outline:none }
+.density input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50% }
+.density input[type=range]::-moz-range-thumb { width:14px; height:14px; background:var(--accent); cursor:pointer; border-radius:50%; border:0 }
+.density .ct { font-size:11px; color:var(--muted); letter-spacing:0.18em; text-transform:uppercase; font-weight:600; min-width:80px }
+
+/* ===== Stats line ===== */
+.stat-line { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:24px }
+
+/* ===== Product grid (novasuede pattern: flush grid + slide-up overlay) ===== */
+.grid { display:grid; grid-template-columns:repeat(var(--cols), 1fr); gap:0 }
+.card { position:relative; aspect-ratio:1/1.15; cursor:pointer; overflow:hidden; border:1px solid var(--bg); transition:transform 0.4s cubic-bezier(0.2,0.8,0.2,1); background:var(--bg-soft) }
+.card:hover { transform:scale(1.04); z-index:5 }
+.card img { width:100%; height:100%; object-fit:cover; display:block; transition:transform 0.4s ease }
+.card .overlay { position:absolute; left:0; right:0; bottom:0; padding:20px 16px 14px; background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.85) 100%); transform:translateY(48%); opacity:0.85; transition:transform 0.3s ease, opacity 0.3s ease }
+.card:hover .overlay { transform:translateY(0); opacity:1 }
+.card .pat { font-size:13px; font-weight:600; letter-spacing:0.02em; color:#fff; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
+.card .ven { font-size:9px; letter-spacing:0.18em; text-transform:uppercase; color:#fff; opacity:0.7; font-weight:500; margin-top:4px }
+.card .actions { margin-top:10px; display:flex; gap:6px }
+.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: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 }
+
+/* ===== Footer ===== */
+footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32px }
+.footer-grid { max-width:1400px; margin:0 auto; display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px }
+.footer-brand { font-size:24px; font-weight:300; letter-spacing:0.32em; text-transform:uppercase; margin-bottom:12px }
+.footer-text { font-size:13px; line-height:1.6; color:var(--muted); max-width:380px }
+.footer-col h4 { font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700; color:var(--paper); margin-bottom:18px }
+.footer-col a { display:block; font-size:13px; color:var(--muted); text-decoration:none; margin-bottom:8px; transition:color 0.2s; cursor:pointer; background:transparent; border:0; font-family:inherit; padding:0; text-align:left }
+.footer-col a:hover { color:var(--accent) }
+.footer-bottom { max-width:1400px; margin:0 auto; padding-top:24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted) }
+
+@media (max-width:720px) {
+  .corner-mark, .meta-line, .enter { font-size:10px }
+  .center-mark { font-size:24px; letter-spacing:0.12em; top:clamp(60px,9vh,90px) }
+  .section, footer { padding-left:20px; padding-right:20px }
+  .footer-grid { grid-template-columns:1fr; gap:32px }
+  .search { margin-left:0; flex:1 1 100% }
+}
+
+.theme-toggle { background:transparent; border:1px solid var(--line); width:32px; height:32px; cursor:pointer; color:var(--paper); display:inline-flex; align-items:center; justify-content:center; font-size:14px; line-height:1; transition:all .15s; padding:0 }
+.theme-toggle:hover { border-color:var(--accent); color:var(--accent) }
+
+/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
+/* Strictly :focus-visible so mouse clicks do NOT show the ring */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+select:focus-visible,
+textarea:focus-visible,
+[tabindex]:focus-visible {
+  outline: 2px solid var(--accent);
+  outline-offset: 2px;
+}
+</style>
+<script>
+(function(){ try { var t = localStorage.getItem('raffia_theme') || 'light'; document.documentElement.dataset.theme = t; } catch(e){} })();
+</script>
+
+<meta property="og:type" content="website">
+<meta property="og:url" content="https://raffiawallcoverings.com/">
+<meta property="og:title" content="Raffia Wallcoverings">
+<meta property="og:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta property="og:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<meta property="og:site_name" content="Raffia Wallcoverings">
+<meta property="article:publisher" content="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings">
+<meta name="twitter:card" content="summary_large_image">
+<meta name="twitter:title" content="Raffia Wallcoverings">
+<meta name="twitter:description" content="Raffia Wallcoverings — Raffia, palm-fiber & tropical-woven wallcoverings.">
+<meta name="twitter:image" content="https://raffiawallcoverings.com/hero-bg.jpg">
+<!-- graphics-loop pass 13: footer + fb -->
+</head>
+<body>
+<style id="ns-header-modal-styles">
+        .ns-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 18px 36px; background: rgba(10,10,10,0.92) !important; backdrop-filter: blur(8px); border-bottom: 1px solid rgba(245,241,232,0.06); }
+        .ns-brand { display: inline-flex; align-items: center; gap: 14px; text-decoration: none; }
+        .ns-dot { width: 28px; height: 28px; border-radius: 50%; background: var(--ns-dot-bg, radial-gradient(circle at 35% 35%, #b66a4d 0%, #8a4a30 60%, #5a2d1c 100%)); box-shadow: 0 0 0 1px rgba(245,241,232,0.10), 0 2px 12px rgba(180,90,60,0.30); flex-shrink: 0; }
+        .ns-name { font-family: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif; font-size: 18px !important; font-weight: 300 !important; letter-spacing: 0.02em !important; color: #f5f1e8 !important; text-transform: none !important; margin: 0 !important; }
+        .ns-name sup { font-size: 0.55em; font-weight: 300; margin-left: 1px; }
+        .ns-nav a, .ns-nav button { font-family: -apple-system, "SF Pro Text", system-ui, sans-serif; font-size: 15px !important; font-weight: 400 !important; color: #f5f1e8 !important; text-decoration: none !important; background: none !important; border: 0 !important; cursor: pointer; transition: color 200ms; letter-spacing: 0 !important; text-transform: none !important; }
+        .ns-nav a:hover, .ns-nav button:hover { color: #ffffff !important; }
+        /* All widths: hide nav by default, hamburger always visible on right, nav opens as right-anchored dropdown panel */
+        .ns-nav {
+            display: none !important;
+            position: absolute; top: 100%; right: 18px;
+            flex-direction: column; align-items: stretch; gap: 0;
+            background: rgba(10,10,10,0.96); backdrop-filter: blur(10px);
+            border: 1px solid rgba(245,241,232,0.10); border-top: 0;
+            min-width: 220px; padding: 10px 0; margin: 0;
+            box-shadow: 0 16px 40px rgba(0,0,0,0.55);
+            z-index: 150;
+        }
+        .ns-nav.open { display: flex !important; }
+        .ns-nav a, .ns-nav button {
+            padding: 12px 22px !important;
+            border-bottom: 1px solid rgba(245,241,232,0.06);
+            width: 100%; text-align: left;
+        }
+        .ns-nav a:last-child, .ns-nav button:last-child { border-bottom: 0; }
+        .ns-nav a:hover, .ns-nav button:hover { background: rgba(245,241,232,0.06) !important; color: #ffffff !important; }
+        @media (max-width: 480px) { .ns-nav { right: 12px; min-width: 200px; } }
+        .ns-header .mobile-toggle { display: flex !important; align-items: center; justify-content: center; width: 36px; height: 36px; background: transparent; border: 0; cursor: pointer; padding: 0; gap: 4px; flex-direction: column; }
+        .ns-header .mobile-toggle span { display: block; width: 22px; height: 1.5px; background: #f5f1e8; transition: transform 200ms, opacity 200ms; }
+        .ns-header .mobile-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
+        .ns-header .mobile-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
+        .ns-header .mobile-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }
+    </style>
+<style id="ns-gold-kill">
+    /* novasuede: kill gold-solid fills, off-white instead. Edge color stays gold. */
+    .new-badge, .new-arrivals-pill,
+    .color-filter-btn.active, .drapery-btn,
+    .sample-btn-chip, .cb-cta {
+      background: #f5f1e8 !important;
+      color: #0a0a0a !important;
+      border-color: #f5f1e8 !important;
+    }
+    .new-badge:hover, .new-arrivals-pill:hover,
+    .color-filter-btn.active:hover, .drapery-btn:hover,
+    .sample-btn-chip:hover, .cb-cta:hover {
+      background: #fff !important;
+      color: #0a0a0a !important;
+    }
+  </style>
+<header class="ns-header">
+        <a href="/" class="ns-brand" aria-label="Home">
+            <span class="ns-dot"></span>
+            <span class="ns-name">Corteza</span>
+        </a>
+        <nav class="ns-nav" id="nsPrimaryNav" aria-label="Primary">
+            <a href="/">Home</a>
+            <a href="/about">About</a>
+            <button type="button" onclick="nsContactOpen()">Contact</button>
+        </nav>
+        <button type="button" class="mobile-toggle" aria-label="Toggle menu" aria-controls="nsPrimaryNav" aria-expanded="false" onclick="nsToggleNav(this)">
+            <span></span><span></span><span></span>
+        </button>
+    </header>
+
+<div class="ns-modal" id="nsContactModal" role="dialog" aria-modal="true" aria-labelledby="nsContactTitle" onclick="if(event.target===this)nsContactClose()">
+        <div class="ns-modal-card">
+            <button type="button" class="close-x" onclick="nsContactClose()" aria-label="Close">×</button>
+            <h3 id="nsContactTitle">How can we help?</h3>
+            <p class="sub">Trade-account replies within one business day.</p>
+            <div class="ns-actions">
+                <a class="ns-action" href="#contact" onclick="nsContactClose()"><span class="ico">📋</span><div class="txt"><b>Get a Quote</b><span>Project specs → priced estimate</span></div></a>
+                <a class="ns-action" href="#contact" onclick="nsContactClose();openModal();"><span class="ico">📦</span><div class="txt"><b>Order a Sample</b><span>Free swatch to your shop</span></div></a>
+                <a class="ns-action" href="mailto:info@raffiawallcoverings.com?subject=Corteza%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@raffiawallcoverings.com</span></div></a>
+                <a class="ns-action" href="tel:888-373-4564"><span class="ico">📞</span><div class="txt"><b>Call Us</b><span>(888) 373-4564 · M–F, 9–5 PT</span></div></a>
+            </div>
+        </div>
+    </div>
+<script>
+  function nsContactOpen() { var m = document.getElementById('nsContactModal'); if (m) m.classList.add('show'); }
+  function nsContactClose() { var m = document.getElementById('nsContactModal'); if (m) m.classList.remove('show'); }
+  function nsToggleNav(btn) {
+    var nav = document.getElementById('nsPrimaryNav');
+    if (!nav) return;
+    var open = nav.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') nsContactClose(); });
+</script>
+
+
+
+
+
+
+
+
+
+
+
+<header>
+  <button class="h-link" onclick="dwmOpen('Contact')" aria-label="Contact"><svg class="h-icon" viewBox="0 0 24 24"><path d="M3 7h18M3 12h18M3 17h18"/></svg><span>Contact</span></button>
+  <button class="theme-toggle" id="theme-toggle" aria-label="Theme toggle">☾</button>
+</header>
+
+<section class="cinema">
+  <div class="cinema-bg" id="heroBg"></div>
+  <div class="corner-mark">Palm Fiber</div>
+  <div class="center-mark">Raffia Wallcoverings</div>
+  <div class="meta-line">Raffia · Palm · Woven · Tropical<span class="num" id="heroNum"></span></div>
+  <a class="enter" href="#shop">Enter <svg viewBox="0 0 24 12" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M0 6h22M16 1l6 5-6 5"/></svg></a>
+</section>
+
+
+<section class="section" id="ideas">
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">New this week</h2>
+    <div class="rail" id="railNewest"></div>
+  </div>
+  <div class="rail-block">
+    <div class="rail-eyebrow">Ideas</div>
+    <h2 class="rail-title">Curated picks</h2>
+    <div class="rail" id="railCurated"></div>
+  </div>
+</section>
+
+<section class="section" id="shop">
+  <div class="section-header">
+    <div>
+      <div class="section-eyebrow">The Collection</div>
+      <h2 class="section-title"><span class="accent" id="totalCount">—</span> Patterns.</h2>
+    </div>
+    <div class="section-meta">Raffia · Palm · Woven · Tropical</div>
+  </div>
+
+  <div class="filters" id="facets">
+    <button class="chip active" data-facet="all">All</button>
+  </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>
+    <div class="search">
+      <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
+      <input type="text" id="searchInput" placeholder="Search by pattern, color…" autocomplete="off">
+    </div>
+  </div>
+
+  <div class="stat-line" id="statLine">Loading…</div>
+  <div class="grid" id="grid"></div>
+  <div class="loading" id="loading">Loading more…</div>
+  <div class="sentinel" id="sentinel"></div>
+</section>
+
+<footer>
+  <div class="footer-grid">
+    <div>
+      <div class="footer-brand">Corteza</div>
+      <p class="footer-text">Corteza — real samples ship free.</p>
+      <p class="footer-text" style="margin-top:14px;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;font-weight:600;color:var(--paper);opacity:0.7"><a href="/about" style="color:inherit;text-decoration:none;border-bottom:1px solid var(--accent)">About →</a></p>
+    </div>
+    <div class="footer-col">
+      <h4>Aesthetic</h4>
+      <div id="footerFacets"></div>
+    </div>
+    <div class="footer-col">
+      <h4>Trade</h4>
+      <button onclick="dwmOpen('Inquiry')">Project Inquiry</button>
+      <button onclick="dwmOpen('Sample')">Request Sample</button>
+      <button onclick="dwmOpen('Contact')">Contact</button>
+    </div>
+  
+    <div class="footer-col">
+      <h4>Social</h4>
+      <a class="fb-link" href="https://www.facebook.com/SteveAbramsDesigns.DesignerWallcoverings" target="_blank" rel="noopener">Facebook</a>
+    </div>
+  </div>
+  <div class="footer-bottom">
+    <span>raffiawallcoverings.com · Corteza</span>
+    <span><a href="mailto:info@raffiawallcoverings.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@raffiawallcoverings.com</a></span>
+    <span id="footerStat"></span>
+  </div>
+</footer>
+
+<script>
+// mini-constellation — 43 niche-stars, current site highlighted in gold
+(function(){
+  const SLUG = "raffiawallcoverings";
+  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'],
+    ['corkwallcovering','Cork','mat'],['fabricwallpaper','Fabric','mat'],['textilewallpaper','Textile','mat'],
+    ['metallicwallpaper','Metallic','mat'],['silverleafwallpaper','Silver Leaf','mat'],['vinylwallpaper','Vinyl','mat'],
+    ['micawallpaper','Mica','mat'],['madagascarwallpaper','Madagascar','mat'],['mylarwallpaper','Mylar','mat'],
+    ['suedewallpaper','Suede','mat'],
+    ['1800swallpaper','1800s','dec'],['1890swallpaper','1890s','dec'],['1900swallpaper','1900s','dec'],
+    ['1920swallpaper','1920s','dec'],['1930swallpaper','1930s','dec'],['1940swallpaper','1940s','dec'],
+    ['1950swallpaper','1950s','dec'],['1960swallpaper','1960s','dec'],['1970swallpaper','1970s','dec'],
+    ['1980swallpaper','1980s','dec'],['retrowalls','Retro','dec'],['wallpapersback','W. Back','dec'],
+    ['agedwallpaper','Aged','cra'],['handcraftedwallpaper','Handcrafted','cra'],['museumwallpaper','Museum','cra'],
+    ['restorationwallpaper','Restoration','cra'],['pastelwallpaper','Pastel','cra'],['glitterwalls','Glitter','cra'],
+    ['greenwallcoverings','Green','cra'],['naturalwallcoverings','Natural','cra'],['saloonwallpaper','Saloon','cra'],
+    ['contractwallpaper','Contract','use'],['hotelwallcoverings','Hotel','use'],['hospitalitywallpaper','Hospitality','use'],
+    ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
+  ];
+  const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
+  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');
+  if (!svg) return;
+  const bandW = W / BANDS.length;
+  let nodes = '';
+  BANDS.forEach((band, bi) => {
+    const list = groups[band];
+    const cx = bi * bandW + bandW / 2;
+    list.forEach((n, i) => {
+      const t = list.length === 1 ? 0.5 : i / (list.length - 1);
+      // 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) * 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;
+      nodes += `<g class="mc-node" data-slug="${n[0]}" data-label="${n[1]}" style="cursor:pointer">
+        <circle cx="${x}" cy="${y}" r="${r}" fill="url(#dna-${band})" fill-opacity="${op}" stroke="${COLOR[band]}" stroke-opacity="${isCurrent?1:0.7}" stroke-width="${isCurrent?2:1}">
+          <title>${n[1]} — ${n[0]}.com</title>
+        </circle>
+        ${isCurrent ? `<circle cx="${x}" cy="${y}" r="${r+5}" fill="none" stroke="${COLOR[band]}" stroke-opacity="0.4" stroke-width="1"><animate attributeName="r" values="${r+5};${r+12};${r+5}" dur="2.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" repeatCount="indefinite"/></circle>` : ''}
+      </g>`;
+    });
+  });
+  // append nodes after defs
+  svg.insertAdjacentHTML('beforeend', nodes);
+  svg.querySelectorAll('.mc-node').forEach(n => {
+    n.addEventListener('mouseenter', () => n.querySelector('circle').setAttribute('fill-opacity', '1'));
+    n.addEventListener('mouseleave', e => {
+      const isCurrent = n.dataset.slug === SLUG;
+      n.querySelector('circle').setAttribute('fill-opacity', isCurrent ? '1' : '0.55');
+    });
+    n.addEventListener('click', () => window.open('https://' + n.dataset.slug + '.com', '_blank'));
+  });
+})();
+</script>
+
+<script>
+const state = { q:'', facet:'all', page:1, pages:1, total:0, loading:false, exhausted:false };
+const LABELS = {"all":"All"};
+
+function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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) {
+  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>'
+    + '<div class="actions">'
+    + '<button class="sample-btn" onclick="event.stopPropagation();dwmOpen(\'Sample\',' + JSON.stringify({sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}).replace(/"/g,'&quot;') + ')">Sample</button>'
+    + '</div></div>';
+}
+
+async function loadFacets() {
+  let f;
+  try {
+    const r = await fetch('/api/facets');
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    f = await r.json();
+  } catch (e) { console.error('loadFacets failed:', e); return; }
+  const el = document.getElementById('facets');
+  for (const [k, v] of Object.entries(f.aesthetics).sort((a,b) => b[1] - a[1])) {
+    const b = document.createElement('button');
+    b.className = 'chip'; b.dataset.facet = k;
+    b.innerHTML = (LABELS[k] || k) + ' <span style="opacity:.55;font-weight:500;margin-left:4px">' + v + '</span>';
+    el.appendChild(b);
+  }
+  el.addEventListener('click', e => {
+    if (e.target.tagName !== 'BUTTON') return;
+    document.querySelectorAll('#facets button').forEach(b => b.classList.remove('active'));
+    e.target.classList.add('active');
+    state.facet = e.target.dataset.facet;
+    resetGrid();
+  });
+  document.getElementById('totalCount').textContent = f.total;
+  document.getElementById('footerStat').textContent = f.total + ' patterns · live archive';
+  // Footer aesthetic links
+  const footerEl = document.getElementById('footerFacets');
+  for (const [k] of Object.entries(f.aesthetics)) {
+    const b = document.createElement('button');
+    b.textContent = LABELS[k] || k;
+    b.onclick = () => { state.facet = k; resetGrid(); document.querySelectorAll('#facets button').forEach(x => x.classList.toggle('active', x.dataset.facet === k)); document.getElementById('shop').scrollIntoView({behavior:'smooth'}); };
+    footerEl.appendChild(b);
+  }
+}
+
+function resetGrid() {
+  state.page = 1; state.exhausted = false;
+  document.getElementById('grid').innerHTML = '';
+  document.getElementById('loading').textContent = 'Loading…';
+  loadGridPage();
+}
+
+async function loadGridPage() {
+  if (state.loading || state.exhausted) return;
+  state.loading = true;
+  const params = new URLSearchParams({ page:state.page, limit:24 });
+  if (state.q) params.set('q', state.q);
+  if (state.facet !== 'all') params.set('aesthetic', state.facet);
+  let data;
+  try {
+    const r = await fetch('/api/products?' + params);
+    if (!r.ok) throw new Error('HTTP ' + r.status);
+    data = await r.json();
+  } catch (e) {
+    console.error('loadGridPage failed:', e);
+    document.getElementById('loading').textContent = '— offline — refresh to retry —';
+    state.loading = false;
+    return;
+  }
+  state.total = data.total; state.pages = data.pages;
+
+  if (state.page === 1) {
+    document.getElementById('statLine').textContent = data.total + ' patterns · ' + (state.facet === 'all' ? 'all aesthetics' : (LABELS[state.facet] || state.facet)) + (state.q ? ' · matching "' + state.q + '"' : '');
+  }
+  const grid = document.getElementById('grid');
+  for (const p of data.items) {
+    const a = document.createElement('a');
+    a.className = 'card'; a.href = '#'; a.onclick = (e) => { e.preventDefault(); dwmOpen('Sample',{sku:p.sku||p.handle, title:p.title, image_url:safeImg(p.image_url)}); };
+    a.innerHTML = cardHTML(p);
+    grid.appendChild(a);
+  }
+  if (state.page >= state.pages || data.items.length === 0) {
+    state.exhausted = true;
+    document.getElementById('loading').textContent = state.total > 0 ? '— end of archive · ' + state.total + ' patterns —' : '';
+  } else state.page++;
+  state.loading = false;
+}
+
+const io = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) loadGridPage(); }, { rootMargin:'600px 0px' });
+io.observe(document.getElementById('sentinel'));
+
+document.getElementById('searchInput').addEventListener('input', e => {
+  state.q = e.target.value.trim();
+  clearTimeout(window._t);
+  window._t = setTimeout(resetGrid, 220);
+});
+
+// Density slider
+const slider = document.getElementById('densitySlider');
+const dlabel = document.getElementById('densityLabel');
+function setDensity(n) {
+  document.documentElement.style.setProperty('--cols', n);
+  dlabel.textContent = n + ' cols';
+  try { localStorage.setItem('raffia_theme_density', n); } catch(e){}
+}
+slider.addEventListener('input', e => setDensity(parseInt(e.target.value)));
+const savedDensity = parseInt(localStorage.getItem('raffia_theme_density') || '6');
+if (savedDensity >= 4 && savedDensity <= 12) { slider.value = savedDensity; setDensity(savedDensity); }
+
+// Theme toggle
+const tb = document.getElementById('theme-toggle');
+function setTheme(t){ document.documentElement.dataset.theme = t; try { localStorage.setItem('raffia_theme', t); } catch(e){} tb.textContent = t === 'dark' ? '☾' : '☀'; }
+setTheme(document.documentElement.dataset.theme || 'light');
+tb.addEventListener('click', () => setTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'));
+
+loadFacets();
+loadGridPage();
+</script>
+<!-- ============================================================
+     DW UNIVERSAL CONTACT MODULE — fashion-house UX
+     Inject before </body> in every DW-family sister site.
+     Self-contained: CSS + 4 modals + JS submission handlers.
+     Uses host site's CSS vars (--bg, --fg, --gold, --rule).
+     ============================================================ -->
+<style>
+  /* === MODAL BASE === */
+  .dwm{position:fixed;inset:0;background:rgba(0,0,0,0.78);display:none;align-items:center;justify-content:center;z-index:9999;padding:24px;overflow-y:auto}
+  .dwm.open{display:flex}
+  .dwm-box{background:var(--bg);border:1px solid var(--rule);max-width:520px;width:100%;padding:36px 32px;position:relative;max-height:90vh;overflow-y:auto;animation:dwm-in 0.25s ease}
+  @keyframes dwm-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
+  .dwm-box h3{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-weight:400;font-size:32px;line-height:1.05;margin-bottom:6px;color:var(--fg);letter-spacing:-0.01em}
+  .dwm-box .sub{color:var(--muted);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;margin-bottom:24px;font-weight:500}
+  .dwm-close{position:absolute;top:18px;right:18px;background:transparent;border:0;color:var(--muted);font-size:24px;cursor:pointer;width:32px;height:32px;line-height:1;padding:0}
+  .dwm-close:hover{color:var(--gold)}
+  .dwm-preview{display:flex;gap:14px;align-items:center;padding:12px;background:var(--bg-soft);margin-bottom:18px}
+  .dwm-preview img{width:64px;height:64px;object-fit:cover}
+  .dwm-preview .pn{font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:15px;line-height:1.2;color:var(--fg)}
+  .dwm-preview .pc{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
+  .dwm-field{margin-bottom:14px}
+  .dwm-field label{display:block;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;font-weight:500}
+  .dwm-field input,.dwm-field textarea,.dwm-field select{width:100%;border:0;border-bottom:1px solid var(--rule);background:transparent;padding:8px 4px;font-size:14px;font-family:inherit;color:var(--fg);outline:none;transition:border-color 0.2s}
+  .dwm-field input:focus,.dwm-field textarea:focus{border-bottom-color:var(--gold)}
+  .dwm-field textarea{min-height:60px;resize:vertical}
+  .dwm-submit{background:transparent;color:var(--muted, #c9b89e);border:1px solid var(--muted, #c9b89e);padding:14px 28px;font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:700;cursor:pointer;width:100%;margin-top:8px;transition:background 0.15s, color 0.15s}
+  .dwm-submit:hover{background:var(--muted, #c9b89e);color:var(--bg, #000)}
+  
+  .dwm-submit:disabled{opacity:0.5;cursor:default}
+  .dwm-status{margin-top:14px;font-size:11px;letter-spacing:0.16em;text-transform:uppercase;text-align:center;display:none}
+  .dwm-status.ok{color:var(--sage);display:block}
+  .dwm-status.err{color:#e08070;display:block}
+  /* contact-options */
+  .dwm-options{display:flex;flex-direction:column;gap:10px}
+  .dwm-option{display:flex;align-items:center;gap:14px;padding:18px 20px;background:transparent;border:1px solid var(--rule);color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:0.20em;text-transform:uppercase;font-weight:600;cursor:pointer;text-decoration:none;transition:all 0.2s;text-align:left;width:100%}
+  .dwm-option:hover{border-color:var(--gold);color:var(--gold)}
+  .dwm-option svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.5;flex-shrink:0}
+  .dwm-option .lbl{flex:1;display:block}
+  .dwm-option .val{display:block;font-size:10px;letter-spacing:0.14em;text-transform:none;font-weight:500;opacity:0.65;margin-top:4px}
+
+/* graphics-loop pass 11: Ideas rails */
+#ideas { padding: 56px 24px 24px; max-width:1600px; margin:0 auto }
+#ideas .rail-block { margin-bottom:48px }
+#ideas .rail-eyebrow { font-size:11px; font-weight:700; letter-spacing:0.32em; text-transform:uppercase; color:var(--muted, #888); margin-bottom:8px }
+#ideas .rail-title { font-size:clamp(22px,2.6vw,32px); font-weight:500; letter-spacing:-0.01em; margin:0 0 18px; color:var(--ink,#fff) }
+#ideas .rail { display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:8px; scrollbar-width:none }
+#ideas .rail::-webkit-scrollbar { display:none }
+#ideas .rail-card { flex:0 0 240px; scroll-snap-align:start; cursor:pointer; transition:transform 0.2s }
+#ideas .rail-card:hover { transform:translateY(-3px) }
+#ideas .rail-card img { width:100%; aspect-ratio:1; object-fit:cover; display:block; background:var(--card,#222) }
+#ideas .rail-card .rc-title { font-size:13px; font-weight:500; color:var(--paper,#fff); padding:8px 0 2px; line-height:1.3 }
+#ideas .rail-card .rc-meta  { font-size:11px; color:var(--muted,#888); letter-spacing:0.06em }
+@media (max-width:720px) { #ideas .rail-card { flex:0 0 160px } }
+</style>
+
+<!-- Contact options modal -->
+<div class="dwm" id="dwmContact" onclick="if(event.target===this)dwmClose('Contact')">
+  <div class="dwm-box" style="max-width:440px">
+    <button class="dwm-close" onclick="dwmClose('Contact')" aria-label="Close">×</button>
+    <h3>Contact</h3>
+    <p class="sub" id="dwmContactSub">Three ways to reach us</p>
+    <div class="dwm-options">
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Inquiry')">
+        <svg viewBox="0 0 24 24"><path d="M4 4h16v12H7l-3 3z"/></svg>
+        <span class="lbl">Send an Inquiry<span class="val">Project name · scope · all the details</span></span>
+      </button>
+      <button class="dwm-option" type="button" onclick="dwmClose('Contact');dwmOpen('Sample')">
+        <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@raffiawallcoverings.com">
+        <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@raffiawallcoverings.com</span></span>
+      </a>
+    </div>
+  </div>
+</div>
+
+<!-- Inquiry modal -->
+<div class="dwm" id="dwmInquiry" onclick="if(event.target===this)dwmClose('Inquiry')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Inquiry')" aria-label="Close">×</button>
+    <h3>Project Inquiry</h3>
+    <p class="sub">We'll respond within one business day</p>
+    <form id="dwmInquiryForm" onsubmit="return dwmSubmit(event,'inquiry')">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Phone</label><input type="tel" name="phone"></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Project Name</label><input type="text" name="projectName" required></div>
+      <div class="dwm-field"><label>Project Scope</label><textarea name="projectScope" placeholder="Square footage · room count · timeline" required></textarea></div>
+      <div class="dwm-field"><label>Additional Information</label><textarea name="message" placeholder="Patterns of interest, finish preferences, budget"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Inquiry</button>
+      <div class="dwm-status" id="dwmInquiryStatus"></div>
+    </form>
+  </div>
+</div>
+
+<!-- Sample-request modal -->
+<div class="dwm" id="dwmSample" onclick="if(event.target===this)dwmClose('Sample')">
+  <div class="dwm-box">
+    <button class="dwm-close" onclick="dwmClose('Sample')" aria-label="Close">×</button>
+    <h3>Request a Sample</h3>
+    <p class="sub">Memo sample · ships free · 3–5 business days</p>
+    <div class="dwm-preview" id="dwmSamplePreview" style="display:none">
+      <img id="dwmSampleImg" src="" alt="">
+      <div><div class="pn" id="dwmSampleName"></div><div class="pc" id="dwmSampleSku"></div></div>
+    </div>
+    <form id="dwmSampleForm" onsubmit="return dwmSubmit(event,'sample')">
+      <input type="hidden" name="sku" id="dwmSampleSkuInput">
+      <input type="hidden" name="title" id="dwmSampleTitleInput">
+      <input type="hidden" name="image_url" id="dwmSampleImageInput">
+      <div class="dwm-field"><label>Name</label><input type="text" name="name" required></div>
+      <div class="dwm-field"><label>Email</label><input type="email" name="email" required></div>
+      <div class="dwm-field"><label>Company / Trade</label><input type="text" name="company"></div>
+      <div class="dwm-field"><label>Shipping Address</label><input type="text" name="address" placeholder="Street" required></div>
+      <div class="dwm-field" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:8px">
+        <input type="text" name="city" placeholder="City" required>
+        <input type="text" name="state" placeholder="State" required>
+        <input type="text" name="zip" placeholder="ZIP" required>
+      </div>
+      <div class="dwm-field"><label>Notes (optional)</label><textarea name="message" placeholder="Project, sq.ft., timing"></textarea></div>
+      <button type="submit" class="dwm-submit">Send Sample Request</button>
+      <div class="dwm-status" id="dwmSampleStatus"></div>
+    </form>
+  </div>
+</div>
+
+<script>
+  // Universal modal control
+  function dwmOpen(name, opts){
+    document.getElementById('dwm' + name).classList.add('open');
+    document.body.style.overflow = 'hidden';
+    try { if (typeof gtag === 'function') gtag('event', 'modal_open', { modal_name: name, sku: (opts && opts.sku) || '' }); } catch(_){}
+    if (name === 'Sample' && opts) {
+      document.getElementById('dwmSamplePreview').style.display = 'flex';
+      document.getElementById('dwmSampleImg').src = opts.image_url || '';
+      document.getElementById('dwmSampleName').textContent = opts.title || '';
+      document.getElementById('dwmSampleSku').textContent = opts.sku || '';
+      document.getElementById('dwmSampleSkuInput').value = opts.sku || '';
+      document.getElementById('dwmSampleTitleInput').value = opts.title || '';
+      document.getElementById('dwmSampleImageInput').value = opts.image_url || '';
+    } else if (name === 'Sample') {
+      document.getElementById('dwmSamplePreview').style.display = 'none';
+      document.getElementById('dwmSampleSkuInput').value = '';
+      document.getElementById('dwmSampleTitleInput').value = '';
+      document.getElementById('dwmSampleImageInput').value = '';
+    }
+  }
+  function dwmClose(name){ document.getElementById('dwm'+name).classList.remove('open'); document.body.style.overflow=''; }
+
+  // Universal form submit — POSTs to /api/send-{kind}
+  async function dwmSubmit(e, kind) {
+    e.preventDefault();
+    const form = e.target;
+    const data = Object.fromEntries(new FormData(form).entries());
+    const btn = form.querySelector('.dwm-submit');
+    const status = form.querySelector('.dwm-status');
+    btn.disabled = true; const orig = btn.textContent; btn.textContent = 'Sending…';
+    status.className = 'dwm-status';
+    try {
+      const r = await fetch('/api/send-' + kind, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) });
+      if (!r.ok) throw new Error('HTTP '+r.status);
+      const j = await r.json();
+      try {
+        if (typeof gtag === 'function') {
+          if (kind === 'sample') gtag('event', 'memo_request', { sku: data.sku || '', title: data.title || '' });
+          else gtag('event', 'lead', { form_type: kind });
+        }
+      } catch(_){}
+      status.textContent = kind === 'sample' ? 'Sample request sent — ships within 3–5 business days' : 'Inquiry sent — we respond within 1 business day';
+      status.className = 'dwm-status ok';
+      btn.textContent = 'Sent ✓';
+      setTimeout(() => { dwmClose(kind === 'sample' ? 'Sample' : 'Inquiry'); btn.disabled = false; btn.textContent = orig; status.className = 'dwm-status'; form.reset(); }, 2800);
+    } catch (err) {
+      status.textContent = 'Send failed — please email info@designerwallcoverings.com';
+      status.className = 'dwm-status err';
+      btn.disabled = false; btn.textContent = orig;
+    }
+    return false;
+  }
+
+  // Wire up "Memo samples ship free" badge in hero to open sample modal directly
+  document.querySelectorAll('.hero .badge, [data-open-sample]').forEach(el => {
+    el.style.cursor = 'pointer';
+    el.addEventListener('click', () => dwmOpen('Sample'));
+  });
+
+  // Wire nav "Trade" link to inquiry modal
+  document.querySelectorAll('nav a[href*="designerwallcoverings.com"]').forEach(a => {
+    a.removeAttribute('target');
+    a.removeAttribute('href');
+    a.style.cursor = 'pointer';
+    a.addEventListener('click', e => { e.preventDefault(); dwmOpen('Contact'); });
+  });
+
+  // Override product card clicks — open Sample modal pre-filled instead of redirecting to DW
+  document.addEventListener('click', e => {
+    const card = e.target.closest('.card, .rail-card');
+    if (!card) return;
+    if (card.tagName === 'A' && (card.getAttribute('href') || '').startsWith('/sample/')) {
+      e.preventDefault();
+      const img = card.querySelector('img');
+      const pat = card.querySelector('.pat');
+      const sku = card.getAttribute('href').replace('/sample/', '');
+      dwmOpen('Sample', {
+        sku,
+        title: pat ? pat.textContent.trim() : '',
+        image_url: img ? img.src : ''
+      });
+    }
+  }, true);
+// DW STANDARD: hero pulls from products.json[0].image_url so dw-collections-viewer
+// drag-drop / hero-pin updates the live front page on next deploy.
+// Always upgrades to the largest Shopify variant (strips _NxN size suffix) so
+// the full-page hero stays sharp.
+// DW STANDARD: hero rotates through top-20 NEWEST products on each visit
+// (novasuede.com pattern). Fetches /api/products?limit=100, sorts by created_at desc,
+// takes the freshest 20, picks one per visit via localStorage counter.
+// Falls back to static /hero-bg.jpg on any error.
+(async function rotateHero() {
+  try {
+    const r = await fetch('/api/products?limit=100');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || [])
+      .filter(p => p && p.image_url && /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(p.image_url))
+      .sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')))
+      .slice(0, 20);
+    if (!items.length) return;
+    let visits = 0;
+    try {
+      visits = parseInt(localStorage.getItem('hero_visits') || '0', 10) || 0;
+      localStorage.setItem('hero_visits', String(visits + 1));
+    } catch(e) {}
+    const pick = items[visits % items.length];
+    // Strip _NxN size suffix to get the largest CDN variant
+    const url = pick.image_url.replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+    const bg = document.getElementById('heroBg') || document.getElementById('cinemaBg');
+    if (bg) bg.style.backgroundImage = "url('" + url + "')";
+  } catch (e) {}
+})();
+
+
+// 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();
+  });
+})();
+
+// graphics-loop pass 11: hydrate Ideas rails from /api/products
+(async function hydrateIdeas() {
+  try {
+    const r = await fetch('/api/products?limit=80');
+    if (!r.ok) return;
+    const d = await r.json();
+    const items = (d.items || []).filter(p => p && p.image_url);
+    if (!items.length) return;
+    const sorted = [...items].sort((a,b) => String(b.created_at || '').localeCompare(String(a.created_at || '')));
+    const newest = sorted.slice(0, 12);
+    // Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
+    const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
+    function card(p) {
+      const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+      return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle || p.sku) + '">' +
+        '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '&quot;') + '" loading="lazy">' +
+        '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
+        '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+      '</a>';
+    }
+    const r1 = document.getElementById('railNewest');
+    const r2 = document.getElementById('railCurated');
+    if (r1) r1.innerHTML = newest.map(card).join('');
+    if (r2) r2.innerHTML = curated.map(card).join('');
+  } catch(e) {}
+})();
+</script>
+
+</body>
+</html>
diff --git a/public/sourcing.html b/public/sourcing.html
new file mode 100644
index 0000000..293ca90
--- /dev/null
+++ b/public/sourcing.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<html lang="en"><head>
+<!-- editorial-gen v1 -->
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>How we source — raffiawallcoverings.com</title>
+<meta name="description" content="How we source — Soft as raffia. Made slowly.">
+<link rel="canonical" href="https://raffiawallcoverings.com/sourcing">
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:ui-serif;background:#F2EDE2;color:#1a1410;line-height:1.65;padding:60px 24px;min-height:100vh}
+.wrap{max-width:720px;margin:0 auto}
+.eyebrow{font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:#9B7B4F;margin-bottom:18px}
+h1{font-family:'Saol Display', serif;font-style:italic;font-size:48px;line-height:1.1;letter-spacing:-0.02em;color:#1a1410;margin-bottom:32px}
+h2{font-family:'Saol Display', serif;font-size:22px;color:#9B7B4F;margin:36px 0 12px;font-weight:500}
+p{margin-bottom:16px;color:#3a322c}
+ul{margin:12px 0 20px 18px}
+li{margin-bottom:8px;color:#3a322c}
+strong{color:#1a1410}
+a{color:#9B7B4F;text-decoration:underline;text-underline-offset:3px}
+nav.foot{margin-top:56px;padding-top:24px;border-top:1px solid rgba(0,0,0,0.10);font-size:11px;letter-spacing:0.18em;text-transform:uppercase}
+nav.foot a{margin-right:22px;text-decoration:none}
+</style>
+</head><body>
+<div class="wrap">
+<div class="eyebrow">Editorial · sourcing · Corteza</div>
+<h1>How we source</h1>
+<p>We begin with the mills—places where raffia is spun, woven, and transformed into something that feels like a whisper of the earth. These are not factories; they are quiet spaces where hands move with intention, and time is measured not in hours but in the patience of the material itself. We travel to find them, often in regions where raffia has been cultivated for generations, from the sunlit plains of West Africa to the humid valleys of Southeast Asia. Each mill we visit is a story, a lineage of craftsmanship passed down through families. We listen more than we speak, asking not what they can do, but what they have done for decades. It is in these moments that we find the soul of the material, the quiet pride of artisans who see raffia not as a commodity, but as an extension of their identity.</p>
+
+<h2>The Mills</h2>
+<p>We seek out mills that operate with a reverence for the material, where the process is as much about honoring tradition as it is about creating something new. These mills are often small, family-run operations, their walls lined with samples of raffia in every imaginable hue and weave. We inspect the looms, the tension of the threads, the way the fibers catch the light. Some mills specialize in fine, almost translucent weaves, while others produce denser, more textured rolls that feel like the skin of the earth itself. We build relationships with these mills, not just as suppliers, but as collaborators. They understand our vision: to curate a collection that is both timeless and deeply rooted in the material’s inherent character.</p>
+
+<h2>The Trade-Only Catalogs</h2>
+<p>Beyond the mills, we turn to trade-only catalogs—volumes that sit on the desks of those who know what they are looking for. These catalogs are not for the casual buyer; they are for those who understand that raffia is not a trend, but a legacy. We sift through them with care, our eyes trained to spot the subtle differences between a well-woven sample and one that falls short. We look for rolls that are not just visually compelling, but structurally sound, with a repeat that feels natural rather than forced. There is a certain poetry in the way raffia can be arranged, a rhythm that we seek to preserve in every selection.</p>
+
+<h2>Criteria for Inclusion</h2>
+<p>Not everything makes the cut. We are selective, and our criteria are as rigorous as they are simple. The substrate must be of the highest quality—paper or natural fibers that allow the raffia to breathe and hold its shape. The repeat must be measured with precision, ensuring that the pattern (if any) is harmonious rather than jarring. Washfastness is non-negotiable; we test each roll for durability, knowing that our clients will want their walls to endure. What gets cut is not just the rolls that fail these tests, but also those that feel too loud, too garish, too far from the quiet elegance we strive for. We do not compromise on this.</p>
+
+<h2>What Gets Cut</h2>
+<p>We cut with the same care we use in selecting. Rolls that lack consistency in color or texture are discarded. Those that feel rushed, as if the weaver’s hands were not steady, are left behind. Even if a roll is beautiful, if it
+<nav class="foot">
+<a href="/">Browse</a>
+<a href="/history">History</a>
+<a href="/vocabulary">Vocabulary</a>
+<a href="/sourcing">Sourcing</a>
+<a href="/care">Care</a>
+<a href="/trade">Trade</a>
+<a href="/about">About</a>
+</nav>
+</div></body></html>
\ No newline at end of file
diff --git a/public/trade.html b/public/trade.html
new file mode 100644
index 0000000..72265a8
--- /dev/null
+++ b/public/trade.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html lang="en"><head>
+<!-- editorial-gen v1 -->
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Trade program — raffiawallcoverings.com</title>
+<meta name="description" content="Trade program — Soft as raffia. Made slowly.">
+<link rel="canonical" href="https://raffiawallcoverings.com/trade">
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:ui-serif;background:#F2EDE2;color:#1a1410;line-height:1.65;padding:60px 24px;min-height:100vh}
+.wrap{max-width:720px;margin:0 auto}
+.eyebrow{font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:#9B7B4F;margin-bottom:18px}
+h1{font-family:'Saol Display', serif;font-style:italic;font-size:48px;line-height:1.1;letter-spacing:-0.02em;color:#1a1410;margin-bottom:32px}
+h2{font-family:'Saol Display', serif;font-size:22px;color:#9B7B4F;margin:36px 0 12px;font-weight:500}
+p{margin-bottom:16px;color:#3a322c}
+ul{margin:12px 0 20px 18px}
+li{margin-bottom:8px;color:#3a322c}
+strong{color:#1a1410}
+a{color:#9B7B4F;text-decoration:underline;text-underline-offset:3px}
+nav.foot{margin-top:56px;padding-top:24px;border-top:1px solid rgba(0,0,0,0.10);font-size:11px;letter-spacing:0.18em;text-transform:uppercase}
+nav.foot a{margin-right:22px;text-decoration:none}
+</style>
+</head><body>
+<div class="wrap">
+<div class="eyebrow">Editorial · trade · Corteza</div>
+<h1>Trade program</h1>
+<p>Welcome to the heart of Corteza’s trade and designer program — a space where intention meets material, and every detail is woven with care. Here, the focus is not on speed or volume, but on the quiet confidence that comes from working with a material as storied and versatile as raffia. This is where your vision meets a curated collection, thoughtfully selected and prepared for the hands that will shape them into spaces of meaning.</p>  
+
+<h2>Who Qualifies</h2>  
+<p>Corteza’s program is designed for professionals who understand the value of material depth and precision. This includes designers, architects, and contractors who work with a discerning eye and a commitment to quality. Whether you’re crafting a private residence, a public space, or a project that demands a unique touch, our program is tailored to those who seek collaboration over convenience. We welcome those who approach their work with the same care we bring to every roll of raffia.</p>  
+
+<h2>Memo Samples</h2>  
+<p>Our samples are not just swatches — they are invitations to explore. Each memo sample is carefully prepared to reflect the character of the raffia, from its natural sheen to its subtle variations. These samples are dispatched directly to your studio or office, ensuring you can study the material in the light of your own environment. Requests are handled with attention, and we encourage you to reach out with specific needs or questions. The goal is to provide clarity, not just color.</p>  
+
+<h2>Lead Times</h2>  
+<p>Lead times are determined by the complexity of the order and the care required to prepare each piece. While we cannot promise haste, we can assure you that every step is taken with the intention of delivering a product that aligns with your expectations. For custom or large-volume orders, we work closely with you to outline timelines that respect both your schedule and the integrity of the material. This is a process that values patience as much as precision.</p>  
+
+<h2>NET-30 Terms</h2>  
+<p>Corteza offers NET-30 terms to qualified professionals, reflecting our trust in the relationships we build. This arrangement is available to those who have demonstrated a commitment to working with care and integrity. We believe that trust is the foundation of any collaboration, and our terms are designed to support your workflow without compromising the quality of the product or the experience of working with us.</p>  
+
+<h2>Custom-Print Availability</h2>  
+<p>Custom-print options are available for those who seek a unique expression. We work with you to explore possibilities that respect the inherent qualities of raffia while allowing for creative interpretation. This is not a process of applying arbitrary designs, but of finding harmony between the material and your vision. Our team is here to guide you through this journey, ensuring the result is both meaningful and enduring.</p>  
+
+<h2>The Designer Wallcoverings Relationship Since 1996</h2>  
+<p>Corteza is part of the Designer Wallcoverings family, a name rooted in the design trade since 1996. This legacy means access to a depth of stock, real samples, and a human connection that remains at the heart of every interaction. Our parent house has long supported professionals by providing materials that speak to the soul of a project, not just its surface. With Corteza, this tradition continues — focused, deliberate, and entirely devoted to the art of raffia. Together, we build spaces that are not only seen, but felt.
+<nav class="foot">
+<a href="/">Browse</a>
+<a href="/history">History</a>
+<a href="/vocabulary">Vocabulary</a>
+<a href="/sourcing">Sourcing</a>
+<a href="/care">Care</a>
+<a href="/trade">Trade</a>
+<a href="/about">About</a>
+</nav>
+</div></body></html>
\ No newline at end of file
diff --git a/public/vocabulary.html b/public/vocabulary.html
new file mode 100644
index 0000000..c39e876
--- /dev/null
+++ b/public/vocabulary.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html lang="en"><head>
+<!-- editorial-gen v1 -->
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Design vocabulary — raffiawallcoverings.com</title>
+<meta name="description" content="Design vocabulary — Soft as raffia. Made slowly.">
+<link rel="canonical" href="https://raffiawallcoverings.com/vocabulary">
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:ui-serif;background:#F2EDE2;color:#1a1410;line-height:1.65;padding:60px 24px;min-height:100vh}
+.wrap{max-width:720px;margin:0 auto}
+.eyebrow{font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:#9B7B4F;margin-bottom:18px}
+h1{font-family:'Saol Display', serif;font-style:italic;font-size:48px;line-height:1.1;letter-spacing:-0.02em;color:#1a1410;margin-bottom:32px}
+h2{font-family:'Saol Display', serif;font-size:22px;color:#9B7B4F;margin:36px 0 12px;font-weight:500}
+p{margin-bottom:16px;color:#3a322c}
+ul{margin:12px 0 20px 18px}
+li{margin-bottom:8px;color:#3a322c}
+strong{color:#1a1410}
+a{color:#9B7B4F;text-decoration:underline;text-underline-offset:3px}
+nav.foot{margin-top:56px;padding-top:24px;border-top:1px solid rgba(0,0,0,0.10);font-size:11px;letter-spacing:0.18em;text-transform:uppercase}
+nav.foot a{margin-right:22px;text-decoration:none}
+</style>
+</head><body>
+<div class="wrap">
+<div class="eyebrow">Editorial · vocabulary · Corteza</div>
+<h1>Design vocabulary</h1>
+<p>Understanding the language of raffia wallcoverings unlocks a deeper connection to the material’s history, craftsmanship, and purpose. These terms, rooted in both tradition and function, guide buyers toward selections that resonate with intention and care. Below, a curated list of essential design terms to consider when engaging with raffia.</p>  
+
+<h2>Raffia Weave</h2>  
+<p>The interlacing method of raffia fibers, which dictates the surface’s density and visual rhythm. A tight weave on a Corteza roll might resemble a woven basket, while a looser one evokes the irregularity of hand-twisted strands.</p>  
+
+<h2>Natural Fiber</h2>  
+<p>The raw material itself, derived from the pith of the raffia palm. Corteza’s rolls retain the organic irregularities of the fiber, visible as subtle knots and variations in thickness along the length.</p>  
+
+<h2>Hand-Woven</h2>  
+<p>A technique where artisans braid or twist fibers by hand, often resulting in asymmetrical patterns. A hand-woven Corteza piece may show faint tool marks or slight color shifts between sections, emphasizing human touch.</p>  
+
+<h2>Loom Finish</h2>  
+<p>The final processing step on a weaving loom, which smooths or tightens the fibers. A Corteza roll with a loom finish might feel more uniform than one left in its raw, hand-finished state.</p>  
+
+<h2>Color Variation</h2>  
+<p>The natural tonal shifts that occur within a single roll due to differences in fiber source or dye lot. A Corteza sample might display a gradient from warm beige to a cooler, almost gray-tinged tone across its width.</p>  
+
+<h2>Density</h2>  
+<p>The compactness of the weave, affecting light diffusion and durability. A high-density Corteza roll resists sagging under heavy use, while a low-density one may appear more porous and translucent.</p>  
+
+<h2>Back Coating</h2>  
+<p>A layer applied to the reverse of the wallcovering to enhance adhesion and stability. Corteza’s back-coated rolls often have a thin, matte film that feels slightly tacky to the touch.</p>  
+
+<h2>Fade Resistance</h2>  
+<p>The material’s ability to maintain its hue under prolonged exposure to light. A Corteza roll treated with UV-resistant dyes might retain its color for years, even in a south-facing room.</p>  
+
+<h2>Tactile Quality</h2>  
+<p>The surface’s physical feel, ranging from smooth to coarse. A Corteza piece with
+<nav class="foot">
+<a href="/">Browse</a>
+<a href="/history">History</a>
+<a href="/vocabulary">Vocabulary</a>
+<a href="/sourcing">Sourcing</a>
+<a href="/care">Care</a>
+<a href="/trade">Trade</a>
+<a href="/about">About</a>
+</nav>
+</div></body></html>
\ No newline at end of file
diff --git a/server.js.pre-sort-skill b/server.js.pre-sort-skill
new file mode 100644
index 0000000..64a31ba
--- /dev/null
+++ b/server.js.pre-sort-skill
@@ -0,0 +1,159 @@
+/**
+ * RAFFIA WALLCOVERINGS — DW family vertical
+ * Curated slice from live designerwallcoverings.com Shopify catalog.
+ */
+const express = require('express');
+const helmet = require('helmet');
+const path = require('path');
+const fs = require('fs');
+
+const PORT = process.env.PORT || 9845;
+const DW_SHOPIFY = 'https://designerwallcoverings.com';
+const __SITE = path.basename(__dirname);
+let DATA_RAW;
+try {
+  const raw = fs.readFileSync(path.join(__dirname, 'data', 'products.json'), 'utf8');
+  DATA_RAW = JSON.parse(raw);
+  if (!Array.isArray(DATA_RAW)) throw new Error('products.json must be an array');
+} catch (e) {
+  console.error(`[${__SITE}] FATAL: could not load products.json — ${e.message}`);
+  console.error(`[${__SITE}] Starting with empty catalog. Run pull script to populate data/products.json.`);
+  DATA_RAW = [];
+}
+
+function isJunk(p) {
+  if (!p.image_url || !p.image_url.trim()) return true;
+  if (!p.handle && !p.sku) return true;
+  const t = p.title || '';
+  if (/lamp|rug|pillow|throw|tripod|frame|mirror|vase|candle|sculpture|figurine/i.test(t)) return true;
+  if (/visual.{0,3}merchandiser/i.test(t)) return true;
+  if (/(?:^|\W)image[ _-]?4(?:\W|$)/i.test(t)) return true;
+  if (/bh.?90210|beverly.?hills.?90210|iconic.{0,4}bh/i.test(t)) return true;
+  return false;
+}
+
+const PRODUCTS = DATA_RAW.filter(p => !isJunk(p));
+const DROPPED = DATA_RAW.length - PRODUCTS.length;
+console.log(`Loaded ${DATA_RAW.length}, kept ${PRODUCTS.length}, dropped ${DROPPED}`);
+
+// graphics-loop pass 12: niche keyword filter — only show products that fit this site's niche
+const NICHE_POS = ["raffia","palm","woven","tropical","natural fiber"];
+const NICHE_NEG = ["solid","blank","plain"];
+function nicheFit(p) {
+  const blob = ((p.title || '') + ' ' + (p.tags || []).join(' ')).toLowerCase();
+  if (NICHE_NEG.some(n => blob.includes(n.toLowerCase()))) return false;
+  return NICHE_POS.length === 0 || NICHE_POS.some(k => blob.includes(k.toLowerCase()));
+}
+const PRODUCTS_NICHE = PRODUCTS.filter(nicheFit);
+const NICHE_DROPPED = PRODUCTS.length - PRODUCTS_NICHE.length;
+console.log(`Niche filter: kept ${PRODUCTS_NICHE.length} of ${PRODUCTS.length}, dropped ${NICHE_DROPPED}`);
+// Replace PRODUCTS reference with the niche-filtered list for all downstream handlers.
+const PRODUCTS_ORIG = PRODUCTS;
+Object.defineProperty(global, '__products_niche_applied', { value: true });
+
+
+const app = express();
+// Security headers via helmet (added 2026-05-04 overnight YOLO loop)
+// DW STANDARD: sort by color/style/sku/title for any product-rendering site.
+const COLOR_RANK = {
+  black:0,gray:1,grey:1,silver:2,white:3,ivory:4,cream:5,beige:6,brown:7,tan:8,khaki:9,copper:10,
+  red:20,pink:21,coral:22,orange:23,peach:24,salmon:25,
+  yellow:30,gold:31,mustard:32,olive:33,
+  green:40,lime:41,mint:42,teal:50,aqua:51,turquoise:52,cyan:53,
+  blue:60,navy:61,indigo:62,periwinkle:63,
+  purple:70,violet:71,lavender:72,plum:73,magenta:74,fuchsia:75,
+};
+function colorRank(p) {
+  const tags = (p.tags || []).map(t => String(t).toLowerCase());
+  for (const t of tags) for (const k of Object.keys(COLOR_RANK)) if (t.includes(k)) return COLOR_RANK[k];
+  return 999;
+}
+const STYLE_TAGS = ['traditional','transitional','modern','contemporary','minimalist','art deco','victorian','mid-century','mid century','rustic','industrial','farmhouse','bohemian','boho','geometric','floral','botanical','damask','toile','grasscloth','silk','linen','vinyl','natural'];
+function styleKey(p) {
+  const tags = (p.tags || []).map(t => String(t).toLowerCase());
+  for (const s of STYLE_TAGS) if (tags.some(t => t.includes(s))) return s;
+  return 'zzz';
+}
+function sortProducts(list, mode) {
+  if (mode === 'sku') return [...list].sort((a,b) => String(a.sku || a.handle || '').localeCompare(String(b.sku || b.handle || '')));
+  if (mode === 'title') return [...list].sort((a,b) => String(a.title || '').localeCompare(String(b.title || '')));
+  if (mode === 'color') return [...list].sort((a,b) => colorRank(a) - colorRank(b) || String(a.title || '').localeCompare(String(b.title || '')));
+  if (mode === 'style') return [...list].sort((a,b) => styleKey(a).localeCompare(styleKey(b)) || String(a.title || '').localeCompare(String(b.title || '')));
+  if (mode === 'price-asc')  return [...list].sort((a,b) => (Number(a.max_price) || 0) - (Number(b.max_price) || 0));
+  if (mode === 'price-desc') return [...list].sort((a,b) => (Number(b.max_price) || 0) - (Number(a.max_price) || 0));
+  return list;
+}
+
+
+app.use(helmet({ contentSecurityPolicy: false }));
+app.use(express.json({ limit: '256kb' }));
+// Universal contact module — modals, /api/send-inquiry, /api/send-sample, /zd-loader.js
+require('./_universal-contact')(app, { siteName: "Raffia Wallcoverings", zdColor: "#a87830", zdPosition: 'right' });
+require('./_universal-auth')(app, { siteName: "raffiawallcoverings" });
+
+app.use(express.static(path.join(__dirname, 'public')));
+
+app.get('/api/products', (req, res) => {
+  const { q, aesthetic, vendor, page = 1, limit = 24, sort = 'newest'} = req.query;
+  let list = PRODUCTS_NICHE;
+  if (q) {
+    const needle = q.toLowerCase();
+    list = list.filter(p => (p.title || '').toLowerCase().includes(needle) || (p.tags || []).some(t => t.toLowerCase().includes(needle)));
+  }
+  if (aesthetic && aesthetic !== 'all') list = list.filter(p => p.aesthetic === aesthetic);
+  if (vendor && vendor !== 'all') list = list.filter(p => p.vendor === vendor);
+  list = sortProducts(list, sort);
+  const total = list.length;
+  const pageNum = Math.max(1, parseInt(page) || 1);
+  const lim = Math.min(60, parseInt(limit) || 24);
+  const start = (pageNum - 1) * lim;
+  res.json({ total, page: pageNum, limit: lim, pages: Math.ceil(total/lim), sort, items: list.slice(start, start + lim) });
+  // (replaced) old: pages: Math.ceil(total / lim), items: list.slice(start, start + lim) });
+});
+
+app.get('/api/sliders', (req, res) => {
+  const SLIDER_AESTHETICS = ["raffia","natural","woven","grasscloth","jute","botanical"];
+  const out = [];
+  for (const a of SLIDER_AESTHETICS) {
+    const items = PRODUCTS_NICHE.filter(p => p.aesthetic === a).slice(0, 12);
+    if (items.length >= 4) out.push({ aesthetic: a, items });
+  }
+  res.json({ rails: out });
+});
+
+app.get('/api/facets', (req, res) => {
+  const aesthetics = {}; const vendors = {};
+  for (const p of PRODUCTS_NICHE) {
+    aesthetics[p.aesthetic] = (aesthetics[p.aesthetic] || 0) + 1;
+    vendors[p.vendor] = (vendors[p.vendor] || 0) + 1;
+  }
+  res.json({ aesthetics, vendors, total: PRODUCTS.length });
+});
+
+app.get('/api/health', (req, res) => res.json({ status: 'ok', count: PRODUCTS_NICHE.length, dropped: DROPPED }));
+
+app.get('/sample/:handle', (req, res) => {
+  const p = PRODUCTS_NICHE.find(x => x.handle === req.params.handle || x.sku === req.params.handle);
+  if (!p) return res.status(404).send('Not found');
+  res.redirect(302, p.product_url || `${DW_SHOPIFY}/products/${encodeURIComponent(p.handle)}#sample`);
+});
+
+// sitemap.xml + robots.txt for SEO
+app.get('/robots.txt', (req, res) => {
+  res.type('text/plain').send(`User-agent: *
+Allow: /
+Sitemap: https://raffiawallcoverings.com/sitemap.xml
+`);
+});
+app.get('/sitemap.xml', (req, res) => {
+  const urls = ['/'];
+  const xml = `<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+${urls.map(u => `  <url><loc>https://raffiawallcoverings.com${u}</loc><changefreq>weekly</changefreq></url>`).join('\n')}
+</urlset>`;
+  res.type('application/xml').send(xml);
+});
+
+app.listen(PORT, '127.0.0.1', () => {
+  console.log(`raffiawallcoverings listening on http://127.0.0.1:${PORT}`);
+});

← 5bd674a sort-skill UI: add Light→Dark / Dark→Light / Color Wheel opt  ·  back to Raffiawallcoverings  ·  fleet-grid refine: chip_uniform_aspect (raffiawallcoverings) e33d2bd →