← back to Glassbeadedwallpaper
index.html
856 lines
<!DOCTYPE html>
<html lang="en" data-hero-mode="huge">
<head>
<meta charset="UTF-8">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-MFPLD6B0SR"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-MFPLD6B0SR');
</script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>glassbeadedwallpaper — premium glass bead, sequin & glitter wallcoverings.</title>
<!-- SEO Meta Tags -->
<meta name="description" content="glassbeadedwallpaper — a curated wallcovering atelier. Glass bead, sequin, and glitter wallpapers, all Class A Fire Rated. Free memo samples. Trade service.">
<meta name="keywords" content="glass beaded wallpaper, glass bead wallcovering, sequin wallpaper, glitter wallpaper, fire rated wallpaper, luxury wallpaper, metallic wallpaper, shimmering wallcovering, commercial wallpaper, Class A fire rated">
<meta name="author" content="glassbeadedwallpaper.com">
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
<link rel="canonical" href="https://glassbeadedwallpaper.com/">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://glassbeadedwallpaper.com/">
<meta property="og:site_name" content="glassbeadedwallpaper">
<meta property="og:title" content="glassbeadedwallpaper — premium glass bead, sequin & glitter wallcoverings.">
<meta property="og:description" content="glassbeadedwallpaper — a curated wallcovering atelier. All Class A Fire Rated.">
<meta property="og:image" content="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/BDL_1867_S_4e513baa-cc29-45e7-b8ed-f0d6ed0098df.jpg?v=1738861591&width=1200&height=630&crop=center">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Premium glass beaded and sequin wallpaper collection">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="https://glassbeadedwallpaper.com/">
<meta name="twitter:title" content="glassbeadedwallpaper — premium glass bead, sequin & glitter wallcoverings">
<meta name="twitter:description" content="A curated wallcovering atelier. All Class A Fire Rated. Free memo samples.">
<meta property="twitter:image" content="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/BDL_1867_S_4e513baa-cc29-45e7-b8ed-f0d6ed0098df.jpg?v=1738861591&width=1200&height=630&crop=center">
<!-- Additional SEO -->
<meta name="geo.region" content="US">
<meta name="geo.placename" content="United States">
<meta name="language" content="English">
<link rel="stylesheet" href="https://glassbeadedwallpaper.com/styles.css?v=1">
<!-- Structured Data (JSON-LD) -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "glassbeadedwallpaper",
"url": "https://glassbeadedwallpaper.com",
"description": "Premium glass beaded, sequin, and glitter wallcoverings - All Class A Fire Rated",
"potentialAction": {
"@type": "SearchAction",
"target": "https://glassbeadedwallpaper.com/?search={search_term_string}",
"query-input": "required name=search_term_string"
}
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "glassbeadedwallpaper",
"url": "https://glassbeadedwallpaper.com",
"logo": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/BDL_1867_S_4e513baa-cc29-45e7-b8ed-f0d6ed0098df.jpg?v=1738861591&width=400&height=400&crop=center",
"parentOrganization": { "@type": "Organization", "name": "Designer Wallcoverings" },
"address": { "@type": "PostalAddress", "streetAddress": "15442 Ventura Bl #102", "addressLocality": "Sherman Oaks", "addressRegion": "CA", "postalCode": "91403", "addressCountry": "US" },
"sameAs": [
"https://designerwallcoverings.com",
"https://instagram.com/designerwallcoverings"
]
}
</script>
<style id="rebrand-tokens-glassbeadedwallpaper">
:root { --primary: #1A1A1A; --paper: #FAF9F6; --ink: #1A1A1A; --accent: #A98B5B; --line: #D8D2C5; --muted: #A98B5B; }
.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>
<script src="/corner-nav.js" defer></script>
<style id="ns-modal-css">
/* ── Contact modal (.ns-modal) — added by fanout-12 ── */
.ns-modal {
display: none;
position: fixed; inset: 0; z-index: 1000;
background: rgba(10,10,10,0.78);
backdrop-filter: blur(6px);
align-items: center; justify-content: center;
padding: 24px;
font-family: -apple-system, "SF Pro Text", system-ui, sans-serif;
}
.ns-modal.show { display: flex; }
.ns-modal-card {
position: relative;
background: #f5f1e8;
color: #0a0a0a;
width: 100%; max-width: 480px;
padding: 36px 32px 32px;
border-radius: 4px;
box-shadow: 0 30px 80px rgba(0,0,0,0.55);
animation: nsModalIn 220ms cubic-bezier(.2,.7,.2,1);
}
@keyframes nsModalIn { from { opacity:0; transform: translateY(8px) scale(.985); } to { opacity:1; transform:none; } }
.ns-modal-card .close-x {
position: absolute; top: 10px; right: 12px;
width: 32px; height: 32px;
background: transparent; border: 0; cursor: pointer;
font-size: 22px; line-height: 1; color: #6e6e68;
}
.ns-modal-card .close-x:hover { color: #0a0a0a; }
.ns-modal-card h3 {
margin: 0 0 4px;
font: 300 22px/1.2 -apple-system, "SF Pro Display", system-ui, sans-serif;
letter-spacing: -0.005em;
color: #0a0a0a;
}
.ns-modal-card .sub {
margin: 0 0 22px;
font: 13px/1.45 -apple-system, "SF Pro Text", system-ui, sans-serif;
color: #6e6e68;
letter-spacing: 0.005em;
}
.ns-actions { display: flex; flex-direction: column; gap: 10px; }
.ns-action {
display: flex; align-items: center; gap: 14px;
padding: 14px 16px;
background: #ffffff;
border: 1px solid rgba(10,10,10,0.08);
border-radius: 3px;
color: #0a0a0a !important;
text-decoration: none !important;
font: 400 14px/1.3 -apple-system, "SF Pro Text", system-ui, sans-serif;
cursor: pointer;
}
.ns-action:hover { background: #fffdf7; border-color: rgba(10,10,10,0.18); }
.ns-action .ico {
flex-shrink: 0;
width: 38px; height: 38px;
display: inline-flex; align-items: center; justify-content: center;
background: rgba(10,10,10,0.04);
border-radius: 50%;
font-size: 18px;
}
.ns-action .txt { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ns-action .txt b { font-weight: 500; font-size: 14px; color: #0a0a0a; }
.ns-action .txt span {
font-weight: 400; font-size: 12px; color: #6e6e68;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 480px) {
.ns-modal { padding: 14px; }
.ns-modal-card { padding: 28px 22px 22px; }
}
[data-theme="dark"] .ns-modal-card { background: #14110c; color: #f5f1e8; }
[data-theme="dark"] .ns-modal-card h3 { color: #f5f1e8; }
[data-theme="dark"] .ns-modal-card .sub { color: #a39c8b; }
[data-theme="dark"] .ns-action { background: rgba(245,241,232,0.04); border-color: rgba(245,241,232,0.10); color: #f5f1e8 !important; }
[data-theme="dark"] .ns-action:hover { background: rgba(245,241,232,0.08); border-color: rgba(245,241,232,0.22); }
[data-theme="dark"] .ns-action .ico { background: rgba(245,241,232,0.08); }
[data-theme="dark"] .ns-action .txt b { color: #f5f1e8; }
[data-theme="dark"] .ns-action .txt span { color: #a39c8b; }
</style>
<!-- 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>
<style id="r2-hero-anatomy">
/* R2 — Hero anatomy. Photo is full-bleed huge; brand wordmark is below the photo, not painted on it. */
.hero { min-height: clamp(560px, 90vh, 1080px); padding: 0 !important; }
.hero h1 { display: none !important; } /* legacy painted-on title */
.hero p { display: none !important; } /* legacy painted-on paragraph */
.hero .fire-rating-badge { display: none !important; } /* moved to wordmark-block below */
.hero .product-count-hero { display: none !important; }
.cinema-logo { position: absolute; top: 22px; left: 32px; font-family: ui-serif, Georgia, serif; font-size: 18px; font-weight: 500; letter-spacing: 0.02em; color: #fff; text-decoration: none; z-index: 6; text-shadow: 0 1px 4px rgba(0,0,0,0.5); }
.hero-wordmark-block { padding: 38px 32px 32px; text-align: center; background: var(--paper, #faf9f6); }
.hero-wordmark { font-family: ui-serif, Georgia, 'Cormorant Garamond', serif; font-weight: 400; font-size: clamp(48px, 9vw, 128px); letter-spacing: -0.01em; line-height: 1; color: var(--ink, #1a1a1a); margin: 0; text-transform: none; }
.hero-wordmark-sub { display: block; font-family: 'Playfair Display', Georgia, serif; font-style: italic; font-weight: 400; font-size: clamp(13px, 1.4vw, 17px); letter-spacing: 0.04em; text-transform: none; margin-top: 14px; color: var(--accent, #A98B5B); }
@media (max-width: 760px) { .hero-wordmark { font-size: clamp(32px, 12vw, 64px); } }
/* R4 hero modes — both share .hero min-height for CLS-free swap */
[data-hero-mode="four-square"] .hero-bg { display: none; }
[data-hero-mode="four-square"] .hero-grid { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; position: absolute; inset: 0; z-index: -1; }
[data-hero-mode="four-square"] .hero-grid .cell { background-size: cover; background-position: center; border: 1px solid rgba(0,0,0,0.4); }
.hero-grid { display: none; }
</style>
<header class="ns-header">
<a href="/" class="ns-brand" aria-label="Home">
<span class="ns-dot"></span>
<span class="ns-name">glassbeadedwallpaper</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@glassbeadedwallpaper.com?subject=glassbeadedwallpaper%20inquiry"><span class="ico">✉️</span><div class="txt"><b>Email Us</b><span>info@glassbeadedwallpaper.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">
<div class="header-content">
<div class="header-left">
<div>
<a href="/" style="text-decoration: none; color: inherit;">
<div class="logo">GlassBeadedWallpaper.com</div>
<div class="tagline">Luxury Glass Bead, Sequin & Glitter Wallcoverings</div>
</a>
</div>
<button class="mobile-menu-toggle" onclick="toggleMobileMenu()" aria-label="Toggle menu">☰</button>
</div>
<nav class="main-nav" id="mainNav">
<a href="/">Browse Collection</a>
<a href="/about-glass-bead.html">About Glass Bead</a>
<a href="/fire-rating.html">Fire Rating Info</a>
<a href="/gallery.html">Instagram Gallery</a>
<a href="https://www.designerwallcoverings.com/pages/contact-us?contact_posted=true">Contact Us</a>
</nav>
<div class="product-count" id="productCount">Loading products...</div>
</div>
</header>
<!-- Hero Section (R2: huge full-bleed photo, no painted text; logo upper-left, hamburger via ns-header upper-right; wordmark below) -->
<section class="hero" id="hero">
<a class="cinema-logo" href="/" aria-label="glassbeadedwallpaper home">glassbeadedwallpaper</a>
<div class="hero-bg" id="heroBg" aria-hidden="true"></div>
<div class="hero-grid" id="heroGrid" aria-hidden="true"></div>
<div class="hero-overlay" aria-hidden="true"></div>
</section>
<div class="hero-wordmark-block">
<h1 class="hero-wordmark">glassbeadedwallpaper</h1>
<span class="hero-wordmark-sub">Glass bead · Sequin · Glitter · Class "A" Fire Rated</span>
<div class="fire-rating-badge" style="margin-top:18px">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2L9 8H3L8 12L6 18L12 14L18 18L16 12L21 8H15L12 2Z"/></svg>
CLASS "A" FIRE RATED
</div>
<div class="product-count-hero" id="productCountHero" style="margin-top:14px">Loading collection...</div>
</div>
<!-- Fire Rating Notice -->
<div class="fire-rating-notice">
<div class="container">
<div class="notice-content">
<div class="notice-icon">🛡️</div>
<div class="notice-text">
<strong>Class "A" Fire Rated Certification:</strong> All glass beaded, sequin, and glitter wallcoverings in our collection meet Class "A" fire safety standards (ASTM E84), making them suitable for commercial buildings, hospitality projects, and residential applications requiring the highest fire safety rating.
</div>
</div>
</div>
</div>
<!-- Products Container -->
<div class="container">
<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 #productsGrid (declared after
// this block) exists; otherwise getElementById returns null and the density slider
// + 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 = 'glassbeadedwallpaper_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 id="productsGrid" class="products-grid">
<div class="loading-message">
<div class="spinner"></div>
Loading glass beaded wallpapers...
</div>
</div>
</div>
<!-- Instagram Section -->
<section class="instagram-section">
<div class="container">
<h2>Follow Us on Instagram</h2>
<p class="instagram-subtitle">See our glass beaded wallcoverings in real installations</p>
<div id="instagramFeed" class="instagram-feed">
<div class="loading-message">
<div class="spinner"></div>
Loading Instagram feed...
</div>
</div>
<a href="https://instagram.com/designerwallcoverings" target="_blank" rel="noopener noreferrer" class="instagram-follow-btn">
Follow @designerwallcoverings
</a>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="footer-content">
<div class="footer-section">
<h3>About Us</h3>
<p>GlassBeadedWallpaper.com specializes in premium glass beaded, sequin, and glitter wallcoverings. All products are Class "A" Fire Rated and perfect for luxury residential and commercial projects.</p>
</div>
<div class="footer-section">
<h3>Quick Links</h3>
<ul>
<li><a href="/">Browse Collection</a></li>
<li><a href="/about-glass-bead.html">About Glass Bead Wallpaper</a></li>
<li><a href="/fire-rating.html">Fire Rating Information</a></li>
<li><a href="/gallery.html">Instagram Gallery</a></li>
<li><a href="https://www.designerwallcoverings.com/pages/contact-us?contact_posted=true">Contact Us</a></li>
</ul>
</div>
<div class="footer-section">
<h3>Resources</h3>
<ul>
<li><a href="https://designerwallcoverings.com/pages/installation">Installation Guide</a></li>
<li><a href="https://designerwallcoverings.com/pages/care">Care Instructions</a></li>
<li><a href="https://designerwallcoverings.com/pages/samples">Order Samples</a></li>
<li><a href="/fire-rating.html">Class A Fire Rating Info</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>© 2026 glassbeadedwallpaper.com · All Products Class "A" Fire Rated</p>
</div>
</footer>
<script>
// Load glass bead products from JSON
let allProducts = [];
let filteredProducts = [];
let displayedProducts = 0;
let selectedColor = null;
const batchSize = 40;
// Color mapping for swatches and sorting
const colorSwatches = {
'Gold': '#FFD700',
'Silver': '#C0C0C0',
'White': '#FFFFFF',
'Black': '#000000',
'Pink': '#FF69B4',
'Red': '#DC143C',
'Purple': '#9370DB',
'Blue': '#4169E1',
'Green': '#228B22',
'Yellow': '#FFD700',
'Orange': '#FF8C00',
'Brown': '#8B4513',
'Gray': '#808080',
'Multi': '#FF1493',
'Other': '#999999'
};
// Convert hex to HSL for better color sorting
function hexToHSL(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (!result) return { h: 0, s: 0, l: 0 };
let r = parseInt(result[1], 16) / 255;
let g = parseInt(result[2], 16) / 255;
let b = parseInt(result[3], 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
case g: h = ((b - r) / d + 2) / 6; break;
case b: h = ((r - g) / d + 4) / 6; break;
}
}
return { h: h * 360, s: s * 100, l: l * 100 };
}
// Get color hex value for a product
function getProductColorHex(product) {
if (product && product.primaryColor && colorSwatches[product.primaryColor]) {
return colorSwatches[product.primaryColor];
}
return '#999999';
}
// Sort products by color (HSL)
function sortProductsByColor(products) {
return products.sort((a, b) => {
const colorA = getProductColorHex(a);
const colorB = getProductColorHex(b);
const hslA = hexToHSL(colorA);
const hslB = hexToHSL(colorB);
if (Math.abs(hslA.l - hslB.l) > 10) {
return hslB.l - hslA.l; // Bright to dark
}
return hslA.h - hslB.h;
});
}
// Generic multi-mode sort (Newest/Color/Style/SKU/Title) for the sort <select>.
function sortProducts(list, mode) {
const arr = [...list];
const sku = p => (p.primarySku || p.handle || '').toLowerCase();
const title = p => (p.title || '').toLowerCase();
const style = p => ((p.tags && p.tags[0]) || p.category || p.productType || '~').toLowerCase();
switch (mode) {
case 'color': return sortProductsByColor(arr);
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;
}
// Re-sort the current (possibly color-filtered) set and re-render from the top.
window.applySort = function (mode) {
filteredProducts = sortProducts(filteredProducts, mode);
displayedProducts = 0;
const grid = document.getElementById('productsGrid');
if (grid) grid.innerHTML = '';
displayBatch();
};
async function loadProducts() {
const grid = document.getElementById('productsGrid');
console.log('Loading glass beaded products...');
try {
console.log('Fetching products from /api/products');
const response = await fetch('/api/products');
if (!response.ok) {
console.error('Response not OK:', response.status, response.statusText);
throw new Error(`Failed to load products: ${response.status}`);
}
console.log('Response received, parsing JSON...');
allProducts = await response.json();
filteredProducts = allProducts;
console.log(`✓ Loaded ${allProducts.length} glass beaded products`);
// Apply saved sort on load (default Newest per hard-rule), not always-color.
try {
let savedSort = 'newest';
try { savedSort = (JSON.parse(localStorage.getItem('glassbeadedwallpaper_grid') || '{}').sort) || 'newest'; } catch {}
allProducts = sortProducts(allProducts, savedSort);
filteredProducts = allProducts;
console.log('Products sorted by', savedSort);
} catch (err) {
console.error('Error sorting products:', err);
}
console.log('Clearing loading message and displaying products...');
grid.innerHTML = '';
// Display first batch
displayBatch();
console.log(`✓ Displayed ${displayedProducts} products`);
// Update counts
updateCount();
// Setup infinite scroll
setupInfiniteScroll();
} catch (error) {
console.error('✗ ERROR loading products:', error);
console.error('Error stack:', error.stack);
grid.innerHTML = `<div class="loading-message">Error loading products: ${error.message}<br>Please check console and refresh the page.</div>`;
}
}
// Display a batch of products
function displayBatch() {
const grid = document.getElementById('productsGrid');
const start = displayedProducts;
const end = Math.min(start + batchSize, filteredProducts.length);
for (let i = start; i < end; i++) {
const product = filteredProducts[i];
const card = createProductCard(product);
grid.appendChild(card);
}
displayedProducts = end;
}
// Create product card element
function createProductCard(product) {
const card = document.createElement('div');
card.className = 'product-card';
card.onclick = () => window.open(product.productUrl, '_blank');
const imageDiv = document.createElement('div');
imageDiv.className = 'product-image loading';
// Fire Rating Badge
const fireRatingBadge = document.createElement('div');
fireRatingBadge.className = 'fire-rating-badge-card';
fireRatingBadge.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2L9 8H3L8 12L6 18L12 14L18 18L16 12L21 8H15L12 2Z"/>
</svg>
CLASS A
`;
imageDiv.appendChild(fireRatingBadge);
const img = document.createElement('img');
img.src = product.image || 'placeholder.jpg';
img.alt = product.imageAlt || product.title;
img.loading = 'lazy';
img.onload = () => {
imageDiv.classList.remove('loading');
};
img.onerror = () => {
imageDiv.classList.remove('loading');
img.src = `data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"%3E%3Crect width="200" height="200" fill="%23E8D4B0"/%3E%3Ctext x="50%25" y="45%25" text-anchor="middle" fill="%236B4423" font-family="sans-serif" font-size="16" font-weight="bold"%3E${product.primarySku}%3C/text%3E%3Ctext x="50%25" y="55%25" text-anchor="middle" fill="%238B6F47" font-family="sans-serif" font-size="12"%3EGlass Bead%3C/text%3E%3C/svg%3E`;
};
imageDiv.appendChild(img);
const info = document.createElement('div');
info.className = 'product-info';
const sku = document.createElement('div');
sku.className = 'product-sku';
sku.textContent = product.primarySku;
const name = document.createElement('div');
name.className = 'product-name';
name.textContent = product.title;
const category = document.createElement('div');
category.className = 'product-category';
category.textContent = product.category || 'Glass Beaded';
const link = document.createElement('div');
link.className = 'product-link';
link.innerHTML = 'View on DesignerWallcoverings.com →';
info.appendChild(sku);
info.appendChild(name);
info.appendChild(category);
info.appendChild(link);
card.appendChild(imageDiv);
card.appendChild(info);
return card;
}
// Update product count
function updateCount() {
const countEl = document.getElementById('productCount');
const countHeroEl = document.getElementById('productCountHero');
const count = `${allProducts.length} Products - All Class "A" Fire Rated`;
countEl.textContent = count;
countHeroEl.textContent = count;
}
// Setup infinite scroll
function setupInfiniteScroll() {
let isLoading = false;
window.addEventListener('scroll', () => {
if (isLoading) return;
const scrollHeight = document.documentElement.scrollHeight;
const scrollTop = window.scrollY;
const clientHeight = window.innerHeight;
if (scrollTop + clientHeight >= scrollHeight - 500) {
if (displayedProducts < filteredProducts.length) {
isLoading = true;
displayBatch();
isLoading = false;
}
}
});
}
// Load Instagram feed
async function loadInstagramFeed() {
const feed = document.getElementById('instagramFeed');
// For now, display placeholder - Instagram API integration would go here
feed.innerHTML = `
<div class="instagram-placeholder">
<p>Connect with us on Instagram <a href="https://instagram.com/designerwallcoverings" target="_blank" rel="noopener noreferrer">@designerwallcoverings</a> to see our glass beaded wallpapers in action!</p>
</div>
`;
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', () => {
loadProducts();
loadInstagramFeed();
});
// Mobile menu toggle
function toggleMobileMenu() {
const nav = document.getElementById('mainNav');
nav.classList.toggle('active');
}
</script>
<!-- Hero rotating product carousel: latest 10 products, random start each visit, 6s/slide + 1.5s crossfade -->
<script>
(async () => {
const heroBg = document.getElementById('heroBg');
if (!heroBg) return;
try {
const r = await fetch('/api/products');
const all = await r.json();
// Take the latest 25 candidates, then keep only the first 10 whose image actually loads
// (some Shopify size-variant URLs return 404).
const candidates = all
.filter(p => p && p.image)
.sort((a, b) => new Date(b.createdAt || 0) - new Date(a.createdAt || 0))
.slice(0, 25);
const tested = await Promise.all(candidates.map(p => new Promise(res => {
const img = new Image();
img.onload = () => res(p);
img.onerror = () => res(null);
img.src = p.image;
})));
const latest10 = tested.filter(Boolean).slice(0, 10);
if (latest10.length === 0) return;
const slides = latest10.map(p => {
const div = document.createElement('div');
div.className = 'hero-bg__slide';
div.style.backgroundImage = `url("${p.image}")`;
heroBg.appendChild(div);
return div;
});
// Random start index per visit (so different visitors see different first impressions)
let i = Math.floor(Math.random() * slides.length);
slides[i].classList.add('is-active');
if (slides.length === 1) return;
setInterval(() => {
slides[i].classList.remove('is-active');
i = (i + 1) % slides.length;
slides[i].classList.add('is-active');
}, 6000);
} catch (err) {
console.warn('hero carousel disabled:', err.message);
}
})();
</script>
<!-- Start of Zendesk Widget script -->
<script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=4d4f52ea-1e3e-4837-8859-51f9abd5a82b"> </script>
<!-- End of Zendesk Widget script -->
<script>
/* R4 — Alternating hero modes (huge / four-square). Server-side default is huge.
Client flips on visit 2. Both modes share the same .hero min-height (CLS-free).
Crawlers without JS always see huge. */
(function(){
try {
var k='dw-hero-mode';
var prev=parseInt(localStorage.getItem(k)||'0',10);
var next=(prev+1)%2;
localStorage.setItem(k,String(next));
if (prev>0) {
var mode = next===0 ? 'huge' : 'four-square';
document.documentElement.dataset.heroMode = mode;
if (mode === 'four-square') {
// glassbeadedwallpaper exposes glass-bead-products on /api/products
fetch('/api/products?limit=4').then(r=>r.ok?r.json():null).then(j=>{
var items = (j && (j.items || j.products || j)) || [];
if (!items || items.length < 4) {
document.documentElement.dataset.heroMode = 'huge';
console.warn('dw-hero-stale: insufficient items for four-square, falling back to huge');
return;
}
var grid = document.getElementById('heroGrid');
if (!grid) return;
items.slice(0,4).forEach(function(it){
var d = document.createElement('div');
d.className = 'cell';
var img = (it.image_url || it.image || (it.images && it.images[0] && it.images[0].src) || '');
if (img) d.style.backgroundImage = "url('" + img + "')";
grid.appendChild(d);
});
}).catch(function(){
document.documentElement.dataset.heroMode = 'huge';
});
}
}
} catch(e) { /* no-op */ }
})();
</script>
</body>
</html>