← back to Flockedwallpaper
index.html
501 lines
<!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-RH5FHVMMX2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-RH5FHVMMX2');
</script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>flockedwallpaper — flocked. The romance of texture.</title>
<meta name="description" content="Luxury flocked wallpaper with velvet-textured patterns — damasks, art deco, botanicals and more. Order free memo samples.">
<link rel="canonical" href="https://flockedwallpaper.com/">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Flocked Wallpaper">
<meta property="og:title" content="Flocked Wallpaper — the romance of texture">
<meta property="og:description" content="Luxury flocked wallpaper with velvet-textured patterns — damasks, art deco, botanicals and more. Order free memo samples.">
<meta property="og:url" content="https://flockedwallpaper.com/">
<meta property="og:image" content="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/VV241_art_deco_fans_BLACKGOLD_install_913x_04f5f81c-8fff-4df7-85da-40c679e15e00.webp?v=1734414891">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Flocked Wallpaper — the romance of texture">
<meta name="twitter:image" content="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/VV241_art_deco_fans_BLACKGOLD_install_913x_04f5f81c-8fff-4df7-85da-40c679e15e00.webp?v=1734414891">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700;900&family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
:root{--black:#1A1614;--cream:#F5F0EB;--gold:#C4995C;--espresso:#2C2421;--gray:#8A7D74;--green:#4ADE80}
body{font-family:'Inter',sans-serif;background:var(--cream);color:var(--black);overflow-x:hidden;-webkit-font-smoothing:antialiased}
.header{position:sticky;top:0;z-index:100;display:flex;align-items:center;justify-content:space-between;padding:14px 20px;background:var(--black)}
.header-center{display:flex;flex-direction:column;align-items:center}
.header-logo{font-family:'Playfair Display',serif;font-weight:700;font-size:15px;color:#fff}
.header-sub{font-family:'Inter',sans-serif;font-weight:400;font-size:9px;color:var(--gold);letter-spacing:.15em;text-transform:uppercase}
.icon-btn{width:44px;height:44px;display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer}
.icon-btn svg{width:22px;height:22px}
.hero{position:relative;width:100%;height:520px;overflow:hidden}
.hero img{width:100%;height:100%;object-fit:cover}
.hero-overlay{position:absolute;inset:0;background:linear-gradient(180deg,rgba(26,22,20,.15),rgba(26,22,20,.85));display:flex;flex-direction:column;justify-content:flex-end;padding:32px 24px}
.hero-label{font-weight:500;font-size:11px;color:var(--gold);letter-spacing:.2em;text-transform:uppercase}
.hero-title{font-family:'Playfair Display',serif;font-weight:900;font-size:38px;color:#fff;line-height:44px;margin-top:8px}
.hero-desc{font-weight:300;font-size:14px;color:rgba(255,255,255,.8);line-height:22px;margin-top:12px}
.hero-btns{display:flex;gap:12px;margin-top:24px}
.btn-gold{display:flex;align-items:center;justify-content:center;padding:14px 28px;background:var(--gold);border-radius:2px;border:none;cursor:pointer}
.btn-gold span{font-weight:600;font-size:13px;color:var(--black);letter-spacing:.05em}
.btn-outline{display:flex;align-items:center;justify-content:center;padding:14px 20px;border:1px solid rgba(255,255,255,.4);border-radius:2px;cursor:pointer}
.btn-outline span{font-weight:400;font-size:13px;color:#fff}
.section-header{display:flex;align-items:center;justify-content:space-between;padding:32px 24px 16px}
.section-title{font-family:'Playfair Display',serif;font-weight:700;font-size:22px;color:var(--black)}
.section-sub{font-size:12px;color:var(--gray);margin-top:4px}
.section-link{font-weight:500;font-size:12px;color:var(--gold)}
.featured-scroll{display:flex;gap:12px;padding:0 24px;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;scroll-padding-left:24px}
.featured-scroll::-webkit-scrollbar{display:none}
.featured-scroll::after{content:'';flex-shrink:0;width:12px}
.featured-card{flex-shrink:0;width:150px;scroll-snap-align:start;cursor:pointer}
.featured-card img{width:150px;height:180px;object-fit:cover;border-radius:8px;background:#F0EAE2}
.featured-card .name{font-weight:600;font-size:12px;color:var(--black);margin-top:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.featured-card .color{font-size:11px;color:var(--gray);margin-top:2px}
.featured-card .price{font-weight:600;font-size:12px;color:var(--gold);margin-top:4px}
.color-filters{padding:0 24px;display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.color-chip{display:flex;align-items:center;gap:6px;padding:10px 16px;border-radius:20px;background:rgba(26,22,20,.06);cursor:pointer;border:none;font-family:'Inter',sans-serif}
.color-chip.active{background:var(--black)}
.color-chip.active .chip-label{color:#fff}
.chip-dot{width:12px;height:12px;border-radius:6px;flex-shrink:0}
.chip-label{font-weight:500;font-size:12px;color:var(--black)}
.product-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px;padding:20px 24px}
.product-card{cursor:pointer}
.product-card img{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:6px;background:#F0EAE2}
.product-card .name{font-weight:600;font-size:12px;color:var(--black);margin-top:8px}
.product-card .color{font-size:11px;color:var(--gray);margin-top:2px}
.product-card .shop-link{font-weight:600;font-size:11px;color:var(--gold);margin-top:2px;display:flex;align-items:center;gap:4px}
.load-more{display:flex;align-items:center;justify-content:center;padding:16px;margin:0 24px 24px;background:var(--black);border-radius:4px;cursor:pointer;border:none}
.load-more span{font-weight:500;font-size:13px;color:#fff}
footer{background:var(--cream);padding:32px 24px 24px;border-top:1px solid rgba(26,22,20,.1)}
footer .footer-logo{font-family:'Playfair Display',serif;font-weight:700;font-size:18px;color:var(--black)}
footer .footer-desc{font-weight:300;font-size:12px;color:var(--gray);line-height:18px;margin-top:6px}
.footer-cols{display:flex;gap:40px;margin-top:24px}
.footer-col-title{font-weight:600;font-size:11px;color:var(--gold);letter-spacing:.1em;text-transform:uppercase}
.footer-col a{display:block;font-size:13px;color:var(--gray);text-decoration:none;margin-top:10px}
.footer-cta{display:flex;align-items:center;justify-content:center;padding:14px;background:var(--gold);border-radius:4px;margin-top:24px;cursor:pointer;border:none;width:100%}
.footer-cta span{font-weight:600;font-size:13px;color:var(--black)}
.footer-bottom{display:flex;align-items:center;justify-content:space-between;margin-top:24px;padding-top:24px;border-top:1px solid rgba(26,22,20,.1)}
.footer-copy{font-size:10px;color:var(--gray)}
.chat-badge{display:flex;align-items:center;gap:6px;padding:6px 12px;background:rgba(26,22,20,.06);border-radius:12px;cursor:pointer;border:none}
.chat-dot{width:8px;height:8px;border-radius:4px;background:var(--green)}
.chat-label{font-weight:500;font-size:10px;color:var(--gray)}
.share-btn{position:fixed;bottom:80px;right:20px;width:48px;height:48px;border-radius:24px;background:var(--gold);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px rgba(0,0,0,.2);cursor:pointer;border:none;z-index:90}
.share-btn svg{width:20px;height:20px}
</style>
<style id="rebrand-tokens-flockedwallpaper">
:root { --primary: #D70000; --paper: #FFF; --ink: #000; --accent: #D70000; --line: #000; --muted: #D70000; }
.sample-btn, .cta, .submit-btn { background: transparent !important; color: var(--muted, var(--accent)) !important; border: 1px solid var(--muted, var(--accent)) !important; transition: background 0.15s, color 0.15s; }
.sample-btn:hover, .cta:hover, .submit-btn:hover { background: var(--muted, var(--accent)) !important; color: var(--paper, #fff) !important; }
</style>
<style id="ns-modal-fix">.ns-modal{display:none}.ns-modal.show{display:flex;align-items:center;justify-content:center;position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:1000}.ns-modal-card{background:#faf6ef;color:#1a1714;padding:32px;border-radius:12px;max-width:480px;width:90%;position:relative;box-shadow:0 20px 60px rgba(0,0,0,0.3)}.ns-modal .close-x{position:absolute;top:12px;right:16px;background:transparent;border:0;font-size:24px;cursor:pointer;color:#1a1714}.ns-modal h3{margin:0 0 8px;font-size:22px;font-weight:400}.ns-modal .sub{color:rgba(0,0,0,0.5);margin:0 0 20px;font-size:14px}.ns-actions{display:grid;gap:10px}.ns-action{display:flex;gap:14px;align-items:center;color:inherit;text-decoration:none;padding:14px 16px;border:1px solid rgba(0,0,0,0.12);border-radius:8px}.ns-action:hover{background:rgba(0,0,0,0.04)}.ns-action .ico{font-size:20px}.ns-action .txt{display:flex;flex-direction:column}.ns-action .txt b{font-weight:600}.ns-action .txt span{font-size:12px;color:rgba(0,0,0,0.5)}</style> <script src="/corner-nav.js" defer></script>
<!-- Meta Pixel — INERT until set-fb-pixel.sh is run (does NOT load fbevents.js or hit Meta until flipped) -->
<script>
(function(){
var PIXEL_ID = '{{FACEBOOK_PIXEL_ID}}';
// Inert until flipped — the brace check prevents BOTH the loader IIFE
// AND the init call from running, so fbevents.js is never fetched.
if (PIXEL_ID.indexOf('{{') !== -1) return;
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', PIXEL_ID);
fbq('track', 'PageView');
})();
</script>
<!-- noscript fallback is added by set-fb-pixel.sh on flip (omitted here to avoid unflipped img phone-home) -->
<!-- End Meta Pixel -->
</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">flockedwallpaper</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@flockedwallpaper.com?subject=Casa%20Cremisi%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@flockedwallpaper.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 -->
<header class="header">
<button class="icon-btn" onclick="document.getElementById('nav-menu').style.display='flex'">
<svg viewBox="0 0 20 20" fill="none"><rect x="2" y="4" width="16" height="2" rx="1" fill="#C4995C"/><rect x="2" y="9" width="16" height="2" rx="1" fill="#C4995C"/><rect x="2" y="14" width="16" height="2" rx="1" fill="#C4995C"/></svg>
</button>
<div class="header-center">
<span class="header-logo">FlockedWallpaper</span>
<span class="header-sub">Luxury Velvet Wallcoverings</span>
</div>
<button class="icon-btn" onclick="document.getElementById('search-bar').style.display=document.getElementById('search-bar').style.display==='flex'?'none':'flex'">
<svg viewBox="0 0 20 20" fill="none"><circle cx="8.5" cy="8.5" r="5.5" stroke="#C4995C" stroke-width="1.5"/><line x1="12.5" y1="12.5" x2="17" y2="17" stroke="#C4995C" stroke-width="1.5" stroke-linecap="round"/></svg>
</button>
</header>
<!-- Search Bar (hidden) -->
<div id="search-bar" style="display:none;padding:12px 20px;background:var(--black)">
<input type="text" id="searchInput" placeholder="Search flocked wallpapers..." oninput="filterProducts()" style="width:100%;padding:12px 16px;border:1px solid rgba(255,255,255,.15);border-radius:4px;background:rgba(255,255,255,.06);color:#fff;font-family:'Inter',sans-serif;font-size:14px;outline:none">
</div>
<!-- Nav Menu Overlay -->
<div id="nav-menu" style="display:none;position:fixed;inset:0;z-index:200;background:var(--black);flex-direction:column;padding:20px">
<div style="display:flex;justify-content:flex-end"><button class="icon-btn" onclick="this.parentElement.parentElement.style.display='none'"><svg viewBox="0 0 20 20" fill="none"><line x1="4" y1="4" x2="16" y2="16" stroke="#C4995C" stroke-width="1.5" stroke-linecap="round"/><line x1="16" y1="4" x2="4" y2="16" stroke="#C4995C" stroke-width="1.5" stroke-linecap="round"/></svg></button></div>
<nav style="display:flex;flex-direction:column;gap:24px;padding:40px 24px">
<a href="/" style="font-family:'Playfair Display',serif;font-size:28px;color:#fff;text-decoration:none">Browse Collection</a>
<a href="https://flockedwallpaper.com/about-flock-wallpaper.html" style="font-family:'Playfair Display',serif;font-size:28px;color:#fff;text-decoration:none">About Flock</a>
<a href="https://flockedwallpaper.com/custom-flock.html" style="font-family:'Playfair Display',serif;font-size:28px;color:#fff;text-decoration:none">Custom Services</a>
<a href="https://www.designerwallcoverings.com/pages/contact-us" style="font-family:'Playfair Display',serif;font-size:28px;color:#fff;text-decoration:none">Contact Us</a>
<a href="https://designer-laboratory-sandbox.myshopify.com/account/login" style="font-family:'Playfair Display',serif;font-size:28px;color:var(--gold);text-decoration:none">Sign In</a>
</nav>
</div>
<!-- Hero -->
<section class="hero" id="heroSection">
<img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/VV241_art_deco_fans_BLACKGOLD_install_913x_04f5f81c-8fff-4df7-85da-40c679e15e00.webp?v=1734414891" alt="Art Deco Fans Flocked Velvet">
<div class="hero-overlay">
<span class="hero-label">Curated Collection</span>
<h1 class="hero-title">Touch the<br>Extraordinary</h1>
<p class="hero-desc" id="heroCount">Loading collection...</p>
<div class="hero-btns">
<button class="btn-gold" onclick="document.getElementById('products').scrollIntoView({behavior:'smooth'})"><span>Browse Collection</span></button>
<a href="https://www.designerwallcoverings.com/pages/samples" class="btn-outline" style="text-decoration:none"><span>Free Samples</span></a>
</div>
</div>
</section>
<!-- Featured -->
<div class="section-header">
<div>
<div class="section-title">Featured</div>
<div class="section-sub">Editor's picks from our velvet collection</div>
</div>
<span class="section-link">See All</span>
</div>
<div class="featured-scroll" id="featuredScroll"></div>
<!-- Shop by Color -->
<div class="section-header" style="padding-bottom:0">
<div><div class="section-title">Shop by Color</div></div>
</div>
<div class="color-filters" id="colorFilters"></div>
<!-- Product Grid -->
<div id="products">
<div class="controls-bar" style="display:flex;gap:18px;align-items:center;justify-content:flex-end;padding:12px 24px;flex-wrap:wrap">
<input type="search" id="grid-search" placeholder="Search…" aria-label="Search products" style="background:transparent;border:1px solid var(--line,#333);color:var(--ink,#f5f1e8);padding:7px 12px;font:inherit;font-size:13px;outline:none;min-width:200px">
<label style="font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted,#A98B5B)">Sort</label>
<select id="sort" aria-label="Sort products" style="background:transparent;border:1px solid var(--line,#333);color:var(--ink,#f5f1e8);padding:7px 12px;font:inherit;font-size:12px;cursor:pointer;outline:none">
<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>
</select>
<label style="font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted,#A98B5B);margin-left:14px">Density</label>
<input id="density" type="range" min="180" max="380" step="10" value="240" style="accent-color:var(--accent,#A98B5B);width:140px;cursor:pointer">
</div>
<script>
// Controls wiring — deferred to DOMContentLoaded so #productGrid (declared after
// this block) exists; otherwise getElementById returns null and the density slider
// + live sort listener never bind (controls render but stay inert).
(function(){
function wire(){
const grid = document.getElementById('productGrid') || document.getElementById('productsGrid');
const dens = document.getElementById('density');
const sortSel = document.getElementById('sort');
const search = document.getElementById('grid-search');
if (!grid) return;
const STORE = 'flockedwallpaper_grid';
const saved = (() => { try { return JSON.parse(localStorage.getItem(STORE) || '{}'); } catch { return {}; } })();
function applyDensity(v){ grid.style.gridTemplateColumns = 'repeat(auto-fill,minmax(' + v + 'px,1fr))'; }
if (dens) {
dens.value = saved.density || 240;
applyDensity(dens.value);
dens.addEventListener('input', () => { applyDensity(dens.value); saved.density = dens.value; localStorage.setItem(STORE, JSON.stringify(saved)); });
}
if (sortSel) {
sortSel.value = saved.sort || 'newest';
sortSel.addEventListener('change', () => {
saved.sort = sortSel.value;
localStorage.setItem(STORE, JSON.stringify(saved));
if (typeof window.applySort === 'function') window.applySort(sortSel.value);
});
}
if (search) {
search.addEventListener('input', () => {
const q = search.value.toLowerCase().trim();
Array.from(grid.children).forEach(card => {
const t = (card.textContent || '').toLowerCase();
card.style.display = !q || t.includes(q) ? '' : 'none';
});
});
}
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', wire);
else wire();
})();
</script>
<div class="product-grid" id="productGrid"></div>
<button class="load-more" id="loadMore" onclick="displayBatch()" style="display:none"><span>Load More</span></button>
</div>
<!-- Footer -->
<footer>
<div class="footer-logo">FlockedWallpaper.com</div>
<div class="footer-desc">flockedwallpaper — flocked. The romance of texture. Premium flocked & velvet wallcoverings curated for designers and homeowners.</div>
<div class="footer-cols">
<div>
<div class="footer-col-title">Explore</div>
<a href="/">Browse Collection</a>
<a href="https://flockedwallpaper.com/about-flock-wallpaper.html">About Flock</a>
<a href="https://flockedwallpaper.com/custom-flock.html">Custom Services</a>
</div>
<div>
<div class="footer-col-title">Support</div>
<a href="https://www.designerwallcoverings.com/pages/contact-us">Contact Us</a>
<a href="https://designerwallcoverings.com/pages/installation">Installation Guide</a>
<a href="https://designerwallcoverings.com/pages/samples">Order Samples</a>
</div>
</div>
<button class="footer-cta" onclick="window.open('https://designerwallcoverings.com','_blank')"><span>Shop on DesignerWallcoverings.com →</span></button>
<div class="footer-bottom">
<span class="footer-copy">© 2026 FlockedWallpaper.com</span>
<button class="chat-badge" onclick="if(window.zE)zE('messenger','open')"><span class="chat-dot"></span><span class="chat-label">Live Chat</span></button>
</div>
</footer>
<!-- Share FAB -->
<button class="share-btn" onclick="shareProduct()">
<svg viewBox="0 0 20 20" fill="none"><path d="M15 7a2 2 0 100-4 2 2 0 000 4zM5 12a2 2 0 100-4 2 2 0 000 4zM15 17a2 2 0 100-4 2 2 0 000 4zM7 11l6 3M13 6L7 9" stroke="#1A1614" stroke-width="1.5" stroke-linecap="round"/></svg>
</button>
<script>
let allProducts=[], filteredProducts=[], displayed=0;
const BATCH=20;
const colors={Black:'#000',Gold:'#FFD700',Red:'#DC143C',Silver:'#C0C0C0',Green:'#228B22',Burgundy:'#800020',Blue:'#4169E1',Purple:'#9370DB',Cream:'#FFFDD0',Brown:'#8B4513',White:'#FFF',Beige:'#F5F5DC',Gray:'#808080',Pink:'#FF69B4',Orange:'#E8820C',Yellow:'#DAA520',Neutral:'#C4B5A2'};
async function init(){
try{
const r=await fetch('/api/products');
allProducts=await r.json();
filteredProducts=[...allProducts];
document.getElementById('heroCount').textContent=allProducts.length+' luxurious flocked & velvet wallcoverings from the world\'s finest makers.';
buildFeatured();
buildColorFilters();
let savedSort='newest';
try{savedSort=(JSON.parse(localStorage.getItem('flockedwallpaper_grid')||'{}').sort)||'newest';}catch{}
filteredProducts=sortProducts(filteredProducts,savedSort);
displayBatch();
}catch(e){console.error(e)}
}
function buildFeatured(){
const container=document.getElementById('featuredScroll');
const picks=[0,8,20,35,50,70].map(i=>allProducts[i]).filter(Boolean);
picks.forEach(p=>{
const card=document.createElement('div');
card.className='featured-card';
card.onclick=()=>window.open(p.productUrl,'_blank');
card.innerHTML=`<img src="${p.image}" alt="${p.title}" loading="lazy"><div class="name">${shortTitle(p.title)}</div><div class="color">${p.primaryColor||'Flocked Velvet'}</div><div class="price">From $${Math.round(parseFloat(p.price)||425)}</div>`;
container.appendChild(card);
});
}
function buildColorFilters(){
const counts={};
allProducts.forEach(p=>{
if(p.primaryColor&&colors[p.primaryColor])counts[p.primaryColor]=(counts[p.primaryColor]||0)+1;
});
const container=document.getElementById('colorFilters');
// All chip
const all=document.createElement('button');
all.className='color-chip active';
all.innerHTML='<span class="chip-label">All</span>';
all.onclick=()=>filterByColor(null,all);
container.appendChild(all);
Object.entries(counts).sort((a,b)=>b[1]-a[1]).slice(0,8).forEach(([c,n])=>{
const chip=document.createElement('button');
chip.className='color-chip';
chip.innerHTML=`<span class="chip-dot" style="background:${colors[c]};${c==='White'||c==='Cream'?'border:1px solid #ccc':''}"></span><span class="chip-label">${c}</span>`;
chip.onclick=()=>filterByColor(c,chip);
container.appendChild(chip);
});
}
function filterByColor(color,el){
document.querySelectorAll('.color-chip').forEach(c=>c.classList.remove('active'));
el.classList.add('active');
displayed=0;
document.getElementById('productGrid').innerHTML='';
filteredProducts=color?allProducts.filter(p=>p.primaryColor===color):[...allProducts];
let curSort='newest';
try{curSort=(JSON.parse(localStorage.getItem('flockedwallpaper_grid')||'{}').sort)||'newest';}catch{}
filteredProducts=sortProducts(filteredProducts,curSort);
displayBatch();
}
function filterProducts(){
const q=document.getElementById('searchInput').value.toLowerCase();
displayed=0;
document.getElementById('productGrid').innerHTML='';
filteredProducts=q?allProducts.filter(p=>(p.title||'').toLowerCase().includes(q)||(p.primaryColor||'').toLowerCase().includes(q)):[...allProducts];
let curSort='newest';
try{curSort=(JSON.parse(localStorage.getItem('flockedwallpaper_grid')||'{}').sort)||'newest';}catch{}
filteredProducts=sortProducts(filteredProducts,curSort);
displayBatch();
}
function sortProducts(list,mode){
const arr=[...list];
const sku=p=>(p.primarySku||p.handle||'').toLowerCase();
const title=p=>(p.title||'').toLowerCase();
const color=p=>(p.primaryColor||'~').toLowerCase();
const style=p=>((p.tags&&p.tags[0])||p.productType||'~').toLowerCase();
switch(mode){
case 'color': arr.sort((a,b)=>color(a).localeCompare(color(b))||title(a).localeCompare(title(b))); break;
case 'style': arr.sort((a,b)=>style(a).localeCompare(style(b))||title(a).localeCompare(title(b))); break;
case 'sku': arr.sort((a,b)=>sku(a).localeCompare(sku(b))); break;
case 'title': arr.sort((a,b)=>title(a).localeCompare(title(b))); break;
case 'newest': default:
arr.sort((a,b)=>new Date(b.createdAt||0)-new Date(a.createdAt||0)); break;
}
return arr;
}
window.applySort=function(mode){
filteredProducts=sortProducts(filteredProducts,mode);
displayed=0;
document.getElementById('productGrid').innerHTML='';
displayBatch();
};
function displayBatch(){
const grid=document.getElementById('productGrid');
const end=Math.min(displayed+BATCH,filteredProducts.length);
for(let i=displayed;i<end;i++){
const p=filteredProducts[i];
const card=document.createElement('div');
card.className='product-card';
card.onclick=()=>window.open(p.productUrl,'_blank');
card.innerHTML=`<img src="${p.image}" alt="${p.title}" loading="lazy"><div class="name">${shortTitle(p.title)}</div><div class="color">${p.primaryColor||'Flocked Velvet'}</div><div class="shop-link">Shop on DW →</div>`;
grid.appendChild(card);
}
displayed=end;
document.getElementById('loadMore').style.display=displayed<filteredProducts.length?'flex':'none';
}
function shortTitle(t){return(t||'').replace(/\s*\|.*$/,'').replace(/Wallpaper Wallcovering/gi,'').replace(/Wallcovering/gi,'').replace(/Wallpaper/gi,'').trim().slice(0,40)}
function shareProduct(){
if(navigator.share){
navigator.share({title:'FlockedWallpaper.com',text:'Check out these luxury flocked & velvet wallcoverings!',url:window.location.href});
}else{
navigator.clipboard.writeText(window.location.href).then(()=>alert('Link copied!'));
}
}
init();
</script>
<!-- Zendesk Widget -->
<script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=4d4f52ea-1e3e-4837-8859-51f9abd5a82b"></script>
</body>
</html>