← back to Dw Marketing Reels
snapshot before deploy: graduate-flipbook work-in-progress (not authored here)
a80a4b25babb918a9f45d7ae243628bda606ac14 · 2026-09-04 10:39:26 -0700 · Claude
Working tree was dirty on arrival with another lane's in-flight graduate-flipbook
work (server.js + 4 public/collections/graduate-flipbook/* + build-graduate-interactive.mjs
+ 2 storefront/graduate-interactive/*). Snapshotted per standing rule so the
deploy Steve approved is revertable and that lane's work is not lost.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XxMVSyKj1qHnXH2fLCT49
Files touched
A public/collections/graduate-flipbook/index.htmlA public/collections/graduate-flipbook/module.htmlA public/collections/graduate-flipbook/page-flip.cssA public/collections/graduate-flipbook/page-flip.jsA scripts/build-graduate-interactive.mjsM server.jsA storefront/graduate-interactive/PUSH-graduate-interactive.shA storefront/graduate-interactive/dw-collection-hero.NEW.liquid
Diff
commit a80a4b25babb918a9f45d7ae243628bda606ac14
Author: Claude <steve@designerwallcoverings.com>
Date: Fri Sep 4 10:39:26 2026 -0700
snapshot before deploy: graduate-flipbook work-in-progress (not authored here)
Working tree was dirty on arrival with another lane's in-flight graduate-flipbook
work (server.js + 4 public/collections/graduate-flipbook/* + build-graduate-interactive.mjs
+ 2 storefront/graduate-interactive/*). Snapshotted per standing rule so the
deploy Steve approved is revertable and that lane's work is not lost.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XxMVSyKj1qHnXH2fLCT49
---
public/collections/graduate-flipbook/index.html | 1405 ++++++++++++++++++
public/collections/graduate-flipbook/module.html | 1393 +++++++++++++++++
public/collections/graduate-flipbook/page-flip.css | 141 ++
public/collections/graduate-flipbook/page-flip.js | 312 ++++
scripts/build-graduate-interactive.mjs | 205 +++
server.js | 2 +-
.../PUSH-graduate-interactive.sh | 24 +
.../dw-collection-hero.NEW.liquid | 1557 ++++++++++++++++++++
8 files changed, 5038 insertions(+), 1 deletion(-)
diff --git a/public/collections/graduate-flipbook/index.html b/public/collections/graduate-flipbook/index.html
new file mode 100644
index 0000000..80f9f60
--- /dev/null
+++ b/public/collections/graduate-flipbook/index.html
@@ -0,0 +1,1405 @@
+<!doctype html><html lang="en"><head><meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Graduate Collection — Interactive Flip Book (preview)</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&display=swap" rel="stylesheet">
+<style>body{margin:0;background:#f6f1ea;color:#2a241d}
+ .hero{height:34vh;min-height:220px;background:#14110e url('https://marketing.designerwallcoverings.com/public/collections/graduate-banner.jpg') center/cover;display:flex;align-items:flex-end}
+ .hero h1{margin:0;padding:1.2rem 1.4rem;color:#f4ede2;font-family:'Cormorant Garamond',serif;font-size:2rem;text-shadow:0 2px 18px rgba(0,0,0,.5)}
+ .wrap{padding:2rem 0}</style></head>
+<body>
+ <div class="hero"><h1>The Graduate Collection</h1></div>
+ <div class="wrap"><!-- ==== Graduate interactive flip book (unified auto-play) ==== -->
+<style>/*!
+ * page-flip.css — visual layer for page-flip.js.
+ *
+ * The JS drives WHEN things move; this file makes them look like paper. The
+ * shadow work Meng To flagged lives here in three cooperating layers:
+ * 1. .pf-curl — per-leaf ambient-occlusion gradient (opacity driven by JS)
+ * 2. .pf-gutter — the fixed spine shadow down the binding edge
+ * 3. .pf-face — subtle paper grain + a page-edge highlight
+ *
+ * Tunable via CSS custom properties (all overridable per instance):
+ * --pf-persp 3D perspective depth (set by JS from opts.perspective)
+ * --pf-gutter spine-shadow peak opacity (set by JS from opts.gutterShadow)
+ * --pf-paper page background
+ * --pf-ink page text color
+ * --pf-radius corner radius of the book
+ */
+
+.pageflip {
+ --pf-paper: #fbf9f4; /* warm sketchbook stock */
+ --pf-paper-2: #f3efe6; /* backside, slightly darker */
+ --pf-ink: #2a2622;
+ --pf-radius: 10px;
+ --pf-edge: rgba(0, 0, 0, 0.10); /* page-edge line */
+ position: relative;
+ width: 100%;
+ aspect-ratio: 3 / 4; /* portrait sketchbook; override as needed */
+ margin: 0 auto;
+ perspective: var(--pf-persp, 2200px);
+ perspective-origin: 0% 50%; /* eye toward the spine so the turn arcs correctly */
+ touch-action: pan-y; /* let vertical scroll through; we own horizontal */
+ user-select: none;
+ -webkit-user-select: none;
+ outline: none;
+}
+.pageflip.pf-grabbing { cursor: grabbing; }
+.pageflip:not(.pf-grabbing) { cursor: grab; }
+
+/* Each leaf pivots on its spine edge (left). */
+.pf-page {
+ position: absolute;
+ inset: 0;
+ transform-origin: left center;
+ transform-style: preserve-3d;
+ will-change: transform;
+ border-radius: 0 var(--pf-radius) var(--pf-radius) 0;
+ /* No CSS transition — the JS rAF loop owns every frame so the shadow and the
+ transform stay locked together. A CSS transition here would desync them. */
+}
+
+/* Front + back faces. backface-visibility hides whichever side faces away, so
+ the two faces never bleed through each other mid-turn. */
+.pf-face {
+ position: absolute;
+ inset: 0;
+ backface-visibility: hidden;
+ -webkit-backface-visibility: hidden;
+ border-radius: inherit;
+ overflow: hidden;
+ box-sizing: border-box;
+ padding: clamp(16px, 5%, 40px);
+ color: var(--pf-ink);
+ background: var(--pf-paper);
+ /* faint paper grain + a bright page-edge highlight on the free (right) edge */
+ background-image:
+ linear-gradient(90deg, rgba(0,0,0,0.05) 0, rgba(0,0,0,0) 3%), /* spine-side shading */
+ linear-gradient(270deg, rgba(255,255,255,0.6) 0, rgba(255,255,255,0) 2%);/* free-edge highlight */
+ box-shadow: inset 0 0 0 1px var(--pf-edge);
+}
+.pf-front { transform: rotateY(0deg); }
+.pf-back {
+ transform: rotateY(180deg);
+ background: var(--pf-paper-2);
+ /* the back of a sheet: mirror the shading (highlight now on the left) */
+ background-image:
+ linear-gradient(270deg, rgba(0,0,0,0.06) 0, rgba(0,0,0,0) 4%),
+ linear-gradient(90deg, rgba(255,255,255,0.4) 0, rgba(255,255,255,0) 3%);
+}
+
+/*
+ * THE CURL SHADOW — the layer that sells the turn.
+ * Its opacity is set every frame by JS (peaks as the page stands perpendicular).
+ * --pf-curl-dir flips the gradient once we pass 90° so the darkness always
+ * gathers where the sheet is bending away from the light, not on the flat face.
+ */
+.pf-curl {
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ border-radius: inherit;
+ opacity: 0;
+ /* dir 0 (front showing): dark gathers toward the free/right edge */
+ background: linear-gradient(
+ 100deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+/* dir 1 (back showing, past 90°): mirror so dark gathers toward the spine/left */
+.pf-curl[style*="--pf-curl-dir: 1"] {
+ background: linear-gradient(
+ 260deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+
+/* The turning leaf gets a real drop shadow so it lifts off the stack. */
+.pf-page.pf-turning {
+ box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
+}
+
+/*
+ * THE GUTTER / SPINE SHADOW — fixed, always on, so the book reads as bound.
+ * A soft dark band hugging the binding edge (left). Peak opacity from --pf-gutter.
+ */
+.pf-gutter {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 12%;
+ pointer-events: none;
+ z-index: 9999;
+ border-radius: var(--pf-radius) 0 0 var(--pf-radius);
+ background: linear-gradient(
+ 90deg,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 1)) 0,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 0.35)) 40%,
+ rgba(0, 0, 0, 0) 100%
+ );
+ mix-blend-mode: multiply;
+}
+
+/* Respect users who ask for less motion: snap instantly (JS still works, the
+ rAF just completes in one frame's worth of visual change to them via CSS is
+ n/a — but we drop the lift shadow that draws the eye). */
+@media (prefers-reduced-motion: reduce) {
+ .pf-page.pf-turning { box-shadow: none; }
+}
+</style>
+<section class="dw-gbook" aria-label="The Graduate Collection flip book">
+ <div class="dw-gbook__bar">
+ <span class="dw-gbook__label">The Flip Book · interactive</span>
+ <div class="dw-gbook__ctl">
+ <button type="button" class="gb-btn" data-gb="prev" aria-label="Previous page">‹</button>
+ <span class="gb-count" data-gb="count">1 / 56</span>
+ <button type="button" class="gb-btn" data-gb="next" aria-label="Next page">›</button>
+ <button type="button" class="gb-btn gb-btn--play" data-gb="play" aria-label="Play narrated tour">▶ Play narrated</button>
+ </div>
+ </div>
+ <div class="pageflip dw-gbook__book" data-pageflip>
+
+ <div class="pf-page gb-cover" role="group" aria-label="Cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__brand">Designer Wallcoverings</span>
+ <span class="gb-cover__title">The Graduate Collection</span>
+ <span class="gb-cover__sub">Flip through it — or press play for the narrated tour</span>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoalRoom.png?v=1709835248" alt="All Over Leopard - Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Blue</span>
+ <span class="gb-pageno">1 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoal.png?v=1709835248" alt="All Over Leopard - Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoalRoom_e9a4799e-903c-417e-99b9-158270cc5cfd.png?v=1750793863" alt="All Over Leopard Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard Blue</span>
+ <span class="gb-pageno">2 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.37.36PM.png?v=1750793883" alt="All Over Leopard Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.36.55PM.png?v=1750793822" alt="All Over Leopard Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard Charcoal</span>
+ <span class="gb-pageno">3 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.36.31PM.png?v=1750793823" alt="All Over Leopard Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Aubergine">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/A902549B-ECE0-4410-8226-32E31F07196B.jpg?v=1772164893" alt="All Over Leopard - Aubergine in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Aubergine</span>
+ <span class="gb-pageno">4 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/B48C9B51-6F0D-4973-985F-992BBF14F800.jpg?v=1772164893" alt="All Over Leopard - Aubergine pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Brown">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/9B0CD372-BE5E-4886-9E91-0574F2BADC00.jpg?v=1772164915" alt="All Over Leopard - Brown in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Brown</span>
+ <span class="gb-pageno">5 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB.jpg?v=1772164915" alt="All Over Leopard - Brown pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Leopard Brown">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB_f0e70547-6d49-4051-974f-a3d29f49e320.jpg?v=1775598515" alt="Leopard Brown in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">Leopard Brown</span>
+ <span class="gb-pageno">6 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB_f0e70547-6d49-4051-974f-a3d29f49e320.jpg?v=1775598515" alt="Leopard Brown pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian - Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at4.01.27PM.png?v=1633734145" alt="Visitorian - Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian - Taupe</span>
+ <span class="gb-pageno">7 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0001.jpg?v=1570091053" alt="Visitorian - Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Navy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0002.jpg?v=1570091053" alt="Visitorian Navy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Navy</span>
+ <span class="gb-pageno">8 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0002.jpg?v=1570091053" alt="Visitorian Navy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Mauve">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0003.jpg?v=1570091053" alt="Visitorian Mauve in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Mauve</span>
+ <span class="gb-pageno">9 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0003.jpg?v=1570091053" alt="Visitorian Mauve pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at3.49.25PM.png?v=1633733413" alt="Visitorian Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Blue</span>
+ <span class="gb-pageno">10 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0004.jpg?v=1570091053" alt="Visitorian Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Jolly Boy Dog & Friends">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-05-12at7.31.52AM.png?v=1747060363" alt="Jolly Boy Dog & Friends in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Jolly Boy Dog & Friends</span>
+ <span class="gb-pageno">11 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-05-12at7.30.51AM.png?v=1747060405" alt="Jolly Boy Dog & Friends pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Steampunk Notice Board">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/QqjaFxcfRPyeCGYhD9G3_steampunk_notice_board_insitu_grande_7d8d9494-189c-43cb-9488-24944ce782b8.jpg?v=1612388487" alt="Steampunk Notice Board in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Steampunk Notice Board</span>
+ <span class="gb-pageno">12 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0002.jpg?v=1612388486" alt="Steampunk Notice Board pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Portarait Gallery Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portarait_Gallery_Taupe_1.jpg?v=1602006843" alt="Portarait Gallery Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Portarait Gallery Taupe</span>
+ <span class="gb-pageno">13 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portarait_Gallery_Taupe_1.jpg?v=1602006843" alt="Portarait Gallery Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dachshund Dog">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DachshundNaturalRoom_dce6601a-c864-4764-b024-8e4d2ac7b818.png?v=1750792583" alt="Dachshund Dog in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Dachshund Dog</span>
+ <span class="gb-pageno">14 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/NEWDachshund_NATURAL.jpg?v=1750792583" alt="Dachshund Dog pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Colonel Fox at the Gentleman's Club - Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Gentlemans_Club_Mustard.png?v=1730485289" alt="Colonel Fox at the Gentleman's Club - Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Colonel Fox at the Gentleman's Club - Mustard</span>
+ <span class="gb-pageno">15 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8900-DesignerWallcoverings-Los-Angeles-1_e3102e92-3911-4763-8ffd-1bb3d218d57e.jpg?v=1730485220" alt="Colonel Fox at the Gentleman's Club - Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Fashionista Tinted">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/hCdYg71Rm1VQjlktJ1lA_Charlotte_cory_fashionista_wallpaper_roomset_grande_280e48d5-09d9-46fe-becb-43b86046f011.jpg?v=1570091054" alt="Fashionista Tinted in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Fashionista Tinted</span>
+ <span class="gb-pageno">16 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0004.jpg?v=1570091053" alt="Fashionista Tinted pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Fashionista Black & White">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/wyqj6AS0QX6xhm67PvOg_Charlotte_Cory_-_Fashionista_black___white_wallpaper_grande_2c2fac20-d910-402f-bf3a-1b896e520fb8.jpg?v=1570091054" alt="Fashionista Black & White in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Fashionista Black & White</span>
+ <span class="gb-pageno">17 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0005.jpg?v=1570091053" alt="Fashionista Black & White pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Rabbit Rabbit Rabbit">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/MVPwIVSsSJ6IiSxGdW0I_rabbit_rabbit_rabbit_insitu_grande_142657d9-0884-44f7-b0a3-c284dafbae19.jpg?v=1572310841" alt="Rabbit Rabbit Rabbit in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Rabbit Rabbit Rabbit</span>
+ <span class="gb-pageno">18 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0003.jpg?v=1572310841" alt="Rabbit Rabbit Rabbit pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Gold & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.53.12PM.png?v=1694465625" alt="Showgirls Metallic Gold & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Gold & Black</span>
+ <span class="gb-pageno">19 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.53.19PM.png?v=1694465646" alt="Showgirls Metallic Gold & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Mustard & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at11.42.05AM.png?v=1694465398" alt="Showgirls Metallic Mustard & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Mustard & Cream</span>
+ <span class="gb-pageno">20 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.49.13PM.png?v=1694465405" alt="Showgirls Metallic Mustard & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Pink & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-87020-DesignerWallcoverings-Los-Angeles-1.png?v=1694465676" alt="Showgirls Metallic Pink & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Pink & Black</span>
+ <span class="gb-pageno">21 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicPink_Black.jpg?v=1730488614" alt="Showgirls Metallic Pink & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Portrait Gallery Navy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portrait_Gallery_Navy_2.jpg?v=1602006845" alt="Portrait Gallery Navy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Portrait Gallery Navy</span>
+ <span class="gb-pageno">22 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portrait_Gallery_Navy_2.jpg?v=1602006845" alt="Portrait Gallery Navy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Bronze & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.33.07PM.png?v=1694464431" alt="Showgirls Metallic Bronze & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Bronze & Cream</span>
+ <span class="gb-pageno">23 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicBronze_Cream_1024x1024_3f9df313-e6aa-40c7-adac-97b90df0b067.jpg?v=1730488554" alt="Showgirls Metallic Bronze & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Pink & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.38.05PM.png?v=1694464738" alt="Showgirls Metallic Pink & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Pink & Cream</span>
+ <span class="gb-pageno">24 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.37.57PM.png?v=1694465689" alt="Showgirls Metallic Pink & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Teal & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.42.16PM.png?v=1694464957" alt="Showgirls Metallic Teal & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Teal & Black</span>
+ <span class="gb-pageno">25 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicTeal_Black.jpg?v=1730488416" alt="Showgirls Metallic Teal & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Teal & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.45.39PM.png?v=1694465204" alt="Showgirls Metallic Teal & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Teal & Cream</span>
+ <span class="gb-pageno">26 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicTeal_Cream_1024x1024_ba6114de-6784-4aa7-ac31-0f45ffecb3ec.jpg?v=1730488356" alt="Showgirls Metallic Teal & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Bronze & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicBronze_Black.jpg?v=1730488254" alt="Showgirls Metallic Bronze & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Bronze & Black</span>
+ <span class="gb-pageno">27 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.51.20PM.png?v=1694465520" alt="Showgirls Metallic Bronze & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsblueroom_0264483b-3df5-48ca-a4e4-0227be6ccfeb.png?v=1730484646" alt="Cavalcade Of Cats Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Blue</span>
+ <span class="gb-pageno">28 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsblue_fa62827d-3eb7-4812-982a-5ef6150ee8f3.png?v=1730484646" alt="Cavalcade Of Cats Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsmustardroom_a24237f0-6336-4e09-9363-dd56e0bd8261.png?v=1730484639" alt="Cavalcade Of Cats Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Mustard</span>
+ <span class="gb-pageno">29 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsmustard_122455d1-6d9e-4092-bc80-3cc2cd0868b6.png?v=1730484639" alt="Cavalcade Of Cats Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Red">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsredroom_24cc4ace-220e-44e5-baaa-8e5b45352ec5.png?v=1730484633" alt="Cavalcade Of Cats Red in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Red</span>
+ <span class="gb-pageno">30 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsred_18a38a54-b823-4ac2-a1b8-87ee5d1f77ba.png?v=1730484633" alt="Cavalcade Of Cats Red pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogCreamRoom_32e3d309-1b1e-4f35-aedc-112ca25c9228.png?v=1730484609" alt="Top Dog Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog Cream</span>
+ <span class="gb-pageno">31 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogCream_252e8492-113b-46a6-ac5c-558b2a6693bd.png?v=1730484609" alt="Top Dog Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogGreyRoom_8641f7a0-a5bd-4256-ad2e-47f5595dc4e7.png?v=1730484602" alt="Top Dog Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog Grey</span>
+ <span class="gb-pageno">32 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogGrey_d06cfc3e-a80f-49c2-b203-8e42a86b1b58.png?v=1730484602" alt="Top Dog Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Burgundy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryBurgundyroom_cffd75f2-e080-4835-9f37-cdb52caa165e.png?v=1730484596" alt="At The Art Gallery Burgundy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Burgundy</span>
+ <span class="gb-pageno">33 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryBurgundy_4f783d0d-251c-43a2-9519-72ee14418169.png?v=1730484596" alt="At The Art Gallery Burgundy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryCharcoalroom_d9e4cfe7-bd89-401b-9942-8b11bf89473d.png?v=1730484591" alt="At The Art Gallery Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Charcoal</span>
+ <span class="gb-pageno">34 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryCharcoal_b0e9858f-c4ee-46b7-b6e5-6c37739a23c1.png?v=1730484591" alt="At The Art Gallery Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGallerytealroom_6b1945f9-f9dd-4808-9254-81ed6963a351.png?v=1730484584" alt="At The Art Gallery Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Teal</span>
+ <span class="gb-pageno">35 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryteal_d8dd0ab4-a676-4120-9ed7-a55f46f02724.png?v=1730484584" alt="At The Art Gallery Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDog_GREEN_Roomset1.jpg?v=1722271854" alt="Top Dog in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog</span>
+ <span class="gb-pageno">36 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Top_Dog_Green_5ed388b8-f593-4438-9b5b-3d289a825f81.jpg?v=1722271739" alt="Top Dog pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Rose">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8901-DesignerWallcoverings-Los-Angeles-1.jpg?v=1730485679" alt="The Soire Rose in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Rose</span>
+ <span class="gb-pageno">37 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8901-DesignerWallcoverings-Los-Angeles-1_5aaf1b13-ea6e-4ce8-9e3f-53cb54939af2.jpg?v=1730485729" alt="The Soire Rose pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8902-DesignerWallcoverings-Los-Angeles-1_65b1df4d-b2bb-4708-add6-8236787a35fd.jpg?v=1730489384" alt="The Soire Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Blue</span>
+ <span class="gb-pageno">38 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8902-DesignerWallcoverings-Los-Angeles-1_65b1df4d-b2bb-4708-add6-8236787a35fd.jpg?v=1730489384" alt="The Soire Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Peach">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8903-DesignerWallcoverings-Los-Angeles-1_0d792d9d-49e8-451d-87d8-cb988273943b.jpg?v=1730489929" alt="The Soire Peach in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Peach</span>
+ <span class="gb-pageno">39 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8903-DesignerWallcoverings-Los-Angeles-1_0d792d9d-49e8-451d-87d8-cb988273943b.jpg?v=1730489929" alt="The Soire Peach pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Plaster">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_ce2a9161-c4a3-470c-8a2f-57f8c6ad2951.jpg?v=1730490279" alt="The Soire Plaster in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Plaster</span>
+ <span class="gb-pageno">40 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_ce2a9161-c4a3-470c-8a2f-57f8c6ad2951.jpg?v=1730490279" alt="The Soire Plaster pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_d30a1059-c72c-4b5a-84b3-a863a568b776.jpg?v=1730490513" alt="The Soire Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Taupe</span>
+ <span class="gb-pageno">41 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_d30a1059-c72c-4b5a-84b3-a863a568b776.jpg?v=1730490513" alt="The Soire Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8906-DesignerWallcoverings-Los-Angeles-1_a03ddfea-1e9f-48ca-9c90-4e08b979c0a0.jpg?v=1730490810" alt="The Soire Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Mustard</span>
+ <span class="gb-pageno">42 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8906-DesignerWallcoverings-Los-Angeles-1_a03ddfea-1e9f-48ca-9c90-4e08b979c0a0.jpg?v=1730490810" alt="The Soire Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande - Plum">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/stag_plum_offset_grande_7ce7d09c-2260-43df-9408-be0985c14fe0.jpg?v=1570091054" alt="Stag Grande - Plum in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande - Plum</span>
+ <span class="gb-pageno">43 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0002.jpg?v=1570091054" alt="Stag Grande - Plum pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_Teal_Large_head_grande_e3b54fee-2979-4805-9de2-145b12fe2eed.jpg?v=1570091054" alt="Stag Grande Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande Teal</span>
+ <span class="gb-pageno">44 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0006.jpg?v=1570091054" alt="Stag Grande Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ABgIgtqVS3OOiOgAFth3_stag_head_grey_grande_28e10eef-c4f6-4ac0-831d-139f08c675f3.jpg?v=1570091054" alt="Stag Grande Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande Grey</span>
+ <span class="gb-pageno">45 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0007.jpg?v=1570091054" alt="Stag Grande Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Stag_Print_Wallpaper_-_Teal_1024x1024_74130f65-820d-4318-862d-4a3bb0bf93a5.png?v=1730488729" alt="Small Stag Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Teal</span>
+ <span class="gb-pageno">46 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at3.36.54PM.png?v=1633732668" alt="Small Stag Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllicGold_TealRoom_891a94b2-3962-4f18-b19d-102772052fd7.png?v=1730484627" alt="Dipped In Moonlight Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Charcoal</span>
+ <span class="gb-pageno">47 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllicGold_Teal_c272519f-6ae8-4897-b33d-f518c24008df.png?v=1730484627" alt="Dipped In Moonlight Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_CreamRoom_b6207c57-e66f-4645-979e-cb39a415a9fb.png?v=1730484621" alt="Dipped In Moonlight Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Cream</span>
+ <span class="gb-pageno">48 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_Cream_4c873c3d-77ee-4fcf-8900-ad39cdbdfe1c.png?v=1730484621" alt="Dipped In Moonlight Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_TealRoom_cada0f29-52ed-43d3-b40c-4e78c71b3e1e.png?v=1730484615" alt="Dipped In Moonlight Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Teal</span>
+ <span class="gb-pageno">49 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_Teal_fc6a1852-7e7d-472b-a075-06ef92f14c8a.png?v=1730484615" alt="Dipped In Moonlight Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Plum">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/stag_print_plum_grande_b0ad71c0-d6ed-47fc-8527-c9aecd18856f.jpg?v=1570091054" alt="Small Stag Plum in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Plum</span>
+ <span class="gb-pageno">50 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0003.jpg?v=1570091054" alt="Small Stag Plum pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_print_grey_grande_4c9922c5-ea6f-408f-b033-ec070caa69ad.jpg?v=1689895357" alt="Small Stag Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Grey</span>
+ <span class="gb-pageno">51 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-87043-DesignerWallcoverings-Los-Angeles-2.png?v=1689895357" alt="Small Stag Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_1.jpg?v=1602006861" alt="Stag in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag</span>
+ <span class="gb-pageno">52 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_1.jpg?v=1602006861" alt="Stag pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Pistachio">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.31.12PM.png?v=1709670701" alt="Vestige Pistachio in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Pistachio</span>
+ <span class="gb-pageno">53 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.30.53PM.png?v=1709670718" alt="Vestige Pistachio pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.38.06PM.png?v=1776370140" alt="Vestige Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Mustard</span>
+ <span class="gb-pageno">54 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.38.25PM.png?v=1776370140" alt="Vestige Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.41.19PM.png?v=1709671326" alt="Vestige Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Grey</span>
+ <span class="gb-pageno">55 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.41.06PM.png?v=1709671354" alt="Vestige Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page gb-cover gb-cover--back" role="group" aria-label="Back cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__title">Shop the Graduate Collection</span>
+ <a class="gb-cover__cta" href="https://www.designerwallcoverings.com/collections/the-graduate-collection">Browse all 55 patterns →</a>
+ </div>
+ </div>
+ </div>
+ <audio class="dw-gbook__audio" data-gb="audio" preload="none" src="https://marketing.designerwallcoverings.com/reels/graduate-narration.mp4"></audio>
+</section>
+<style>
+ .dw-gbook{max-width:1100px;margin:0 auto 1.75rem;padding:0 1rem;font-family:'Cormorant Garamond',Georgia,serif;}
+ .dw-gbook__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:0 0 .6rem;flex-wrap:wrap;}
+ .dw-gbook__label{font-size:.95rem;letter-spacing:.12em;text-transform:uppercase;color:#8a7f72;}
+ .dw-gbook__ctl{display:flex;align-items:center;gap:.4rem;}
+ .gb-btn{border:1px solid #cbb8a3;background:#fff;color:#3a3128;border-radius:999px;padding:.35rem .8rem;font:inherit;font-size:.9rem;cursor:pointer;line-height:1;transition:background .15s,color .15s;}
+ .gb-btn:hover{background:#f3ece2;}
+ .gb-btn--play{background:#14110e;color:#f4ede2;border-color:#14110e;}
+ .gb-btn--play:hover{background:#2a2118;}
+ .gb-btn--play.is-playing{background:#8a1f2b;border-color:#8a1f2b;}
+ .gb-count{min-width:4.5em;text-align:center;color:#6b6055;font-size:.9rem;}
+ .dw-gbook__book{aspect-ratio:16/9;background:#14110e;border-radius:10px;box-shadow:0 14px 48px rgba(0,0,0,.22);}
+ /* spread: verso (room + name) | recto (pattern) */
+ .gb-spread{position:absolute;inset:0;display:grid;grid-template-columns:1fr 1fr;background:#fbf7f1;}
+ .gb-verso{position:relative;overflow:hidden;background:#efe7db;}
+ .gb-room{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-room--none{background:linear-gradient(135deg,#e7ddce,#d8ccba);}
+ .gb-meta{position:absolute;left:0;right:0;bottom:0;padding:1rem 1.1rem;display:flex;flex-direction:column;gap:.15rem;background:linear-gradient(0deg,rgba(20,17,14,.72),rgba(20,17,14,0));color:#fdf8f0;}
+ .gb-chapter{font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;opacity:.85;}
+ .gb-name{font-size:1.45rem;line-height:1.1;}
+ .gb-pageno{font-size:.72rem;opacity:.7;letter-spacing:.1em;}
+ .gb-recto{position:relative;overflow:hidden;background:#fff;}
+ .gb-swatch{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-cover__inner{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:.5rem;background:radial-gradient(120% 120% at 50% 20%,#241d15,#14110e);color:#f4ede2;padding:2rem;}
+ .gb-cover__brand{font-size:.8rem;letter-spacing:.28em;text-transform:uppercase;color:#c9a86a;}
+ .gb-cover__title{font-size:2.1rem;line-height:1.05;}
+ .gb-cover__sub{font-size:1rem;color:#b6a894;}
+ .gb-cover__cta{margin-top:.4rem;color:#14110e;background:#c9a86a;border-radius:999px;padding:.5rem 1.1rem;text-decoration:none;font-size:.95rem;}
+ @media(max-width:640px){.gb-name{font-size:1.15rem}.gb-cover__title{font-size:1.5rem}.dw-gbook__book{aspect-ratio:4/3}}
+ @media(prefers-reduced-motion:reduce){.dw-gbook__book{scroll-behavior:auto}}
+</style>
+<script>/*!
+ * page-flip.js — a zero-dependency drag-to-paginate book / sketchbook UI.
+ *
+ * Seeded by Meng To (@MengTo)'s 2026-08-06 "page-flipping sketchbook" post:
+ * "AI gives you the basics unless you hand it a solid open-source to work
+ * from. So I asked for drag to paginate, which took many fixes for shadows."
+ * This file IS that solid open-source to work from. The hard parts it gets
+ * right — the ones "the basics" skip — are called out inline: the curl
+ * ambient-occlusion shadow, the gutter/spine shadow, velocity-flick release,
+ * and keeping the shadow synced to the page THROUGH the snap animation.
+ *
+ * Contract (see demo.html):
+ * <div class="pageflip" data-pageflip>
+ * <div class="pf-page">…page 1…</div>
+ * <div class="pf-page">…page 2…</div>
+ * …
+ * </div>
+ * Each direct .pf-page child becomes one leaf. Author content lives on the
+ * front; the back is an auto-generated paper backside.
+ *
+ * Usage:
+ * const book = new PageFlip(el, { onFlip(i){…} }); // or auto-init below
+ * book.next(); book.prev(); book.goTo(3);
+ *
+ * No build step, no framework, no license friction — vanilla ES2019.
+ */
+(function (global) {
+ 'use strict';
+
+ var DEFAULTS = {
+ dragZone: 0.5, // fraction of page width (from the outer edge) that starts a drag
+ flipThreshold: 0.5, // release past this fraction of the turn (0..1) completes the flip
+ flickVelocity: 0.6, // px/ms; a faster release completes the flip regardless of threshold
+ snapMs: 420, // snap animation duration
+ curlShadow: 0.42, // peak opacity of the curl ambient-occlusion shadow (0..1)
+ gutterShadow: 0.28, // peak opacity of the fixed spine/gutter shadow (0..1)
+ perspective: 2200, // px; larger = flatter/less dramatic depth
+ onFlip: null, // (index) => void, fired after a completed flip settles
+ onTurn: null // (progress, dir) => void, fired continuously while turning (progress 0..1)
+ };
+
+ // power-in-out easing keeps the snap feeling weighted, not linear/robotic.
+ function easeInOut(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }
+ function clamp(v, lo, hi) { return v < lo ? lo : v > hi ? hi : v; }
+
+ function PageFlip(root, opts) {
+ if (!root) throw new Error('PageFlip: root element required');
+ if (root.__pageflip) return root.__pageflip; // idempotent
+ this.root = root;
+ this.o = Object.assign({}, DEFAULTS, opts || {});
+ this.pages = [];
+ this.index = 0; // top face-up leaf
+ this.dragging = false;
+ this.raf = 0;
+ root.__pageflip = this;
+ this._build();
+ this._bind();
+ this._layout();
+ }
+
+ PageFlip.prototype._build = function () {
+ var root = this.root;
+ root.classList.add('pageflip');
+ root.style.setProperty('--pf-persp', this.o.perspective + 'px');
+
+ // Promote each .pf-page child into a two-faced leaf with a curl-shadow layer.
+ var kids = Array.prototype.filter.call(root.children, function (c) {
+ return c.classList && c.classList.contains('pf-page');
+ });
+ var self = this;
+ kids.forEach(function (leaf, i) {
+ // Move author content into a front face (once — re-init safe).
+ if (!leaf.querySelector(':scope > .pf-front')) {
+ var front = document.createElement('div');
+ front.className = 'pf-face pf-front';
+ while (leaf.firstChild) front.appendChild(leaf.firstChild);
+ leaf.appendChild(front);
+
+ var back = document.createElement('div');
+ back.className = 'pf-face pf-back';
+ back.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(back);
+
+ // Curl shadow: a gradient overlay whose opacity we drive from the turn
+ // angle. This is the "many fixes for shadows" layer — see physics.md.
+ var curl = document.createElement('div');
+ curl.className = 'pf-curl';
+ curl.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(curl);
+ }
+ leaf.dataset.pfIndex = String(i);
+ leaf.setAttribute('role', 'group');
+ leaf.setAttribute('aria-roledescription', 'page');
+ self.pages.push(leaf);
+ });
+
+ // Fixed gutter/spine shadow — always present at the binding edge so the
+ // book reads as bound even when no page is turning.
+ if (!root.querySelector(':scope > .pf-gutter')) {
+ var gutter = document.createElement('div');
+ gutter.className = 'pf-gutter';
+ gutter.setAttribute('aria-hidden', 'true');
+ root.appendChild(gutter);
+ root.style.setProperty('--pf-gutter', this.o.gutterShadow);
+ }
+ };
+
+ PageFlip.prototype._layout = function () {
+ // Resting state: leaves before `index` are turned (-180°) and stack on the
+ // left ascending; leaves at/after `index` are flat and stack on the right
+ // with `index` on top.
+ var n = this.pages.length;
+ for (var i = 0; i < n; i++) {
+ var leaf = this.pages[i];
+ if (i < this.index) {
+ this._setLeaf(leaf, -180, 0);
+ leaf.style.zIndex = String(i); // earlier turned pages sink lower
+ leaf.classList.add('pf-turned');
+ } else {
+ this._setLeaf(leaf, 0, 0);
+ leaf.style.zIndex = String(n - i); // current on top, rest descend
+ leaf.classList.remove('pf-turned');
+ }
+ leaf.setAttribute('aria-hidden', i === this.index || i === this.index + 1 ? 'false' : 'true');
+ }
+ this.root.dataset.pfIndex = String(this.index);
+ };
+
+ // Apply a rotation + its matching shadow to one leaf. angleDeg in [-180, 0].
+ PageFlip.prototype._setLeaf = function (leaf, angleDeg, forceShadow) {
+ leaf.style.transform = 'rotateY(' + angleDeg + 'deg)';
+ var curl = leaf.querySelector(':scope > .pf-curl');
+ if (!curl) return;
+ // sin() peaks at 90° (page standing up) and vanishes flat at 0°/180° — the
+ // physically-right shape for ambient occlusion of a curling sheet.
+ var a = Math.abs(angleDeg);
+ var s = (forceShadow != null ? forceShadow : Math.sin(a * Math.PI / 180)) * this.o.curlShadow;
+ curl.style.opacity = String(s);
+ // Past 90° we're looking at the back of the sheet: flip the gradient so the
+ // shading gathers toward the (now leading) spine edge, not the free edge.
+ curl.style.setProperty('--pf-curl-dir', a > 90 ? '1' : '0');
+ };
+
+ PageFlip.prototype._bind = function () {
+ var self = this;
+ this._onDown = function (e) { self._down(e); };
+ this._onMove = function (e) { self._move(e); };
+ this._onUp = function (e) { self._up(e); };
+ this.root.addEventListener('pointerdown', this._onDown);
+ // Keyboard paging for accessibility. Only set tabIndex when the element
+ // has no explicit tabindex attribute; avoids overwriting intentional -1.
+ if (!this.root.hasAttribute('tabindex')) this.root.tabIndex = 0;
+ // Stored (not anonymous) so destroy() can remove it — otherwise re-init on
+ // the same element stacks keydown listeners.
+ this._onKey = function (e) {
+ if (e.key === 'ArrowRight' || e.key === 'PageDown') { self.next(); e.preventDefault(); }
+ else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { self.prev(); e.preventDefault(); }
+ };
+ this.root.addEventListener('keydown', this._onKey);
+ this._onResize = function () { self.width = self.root.clientWidth; };
+ window.addEventListener('resize', this._onResize);
+ this.width = this.root.clientWidth;
+ };
+
+ PageFlip.prototype._down = function (e) {
+ if (this.animating) return;
+ var rect = this.root.getBoundingClientRect();
+ var x = (e.clientX - rect.left) / rect.width; // 0 (spine/left) .. 1 (outer/right)
+ var dir;
+ // Right dragZone turns forward (needs a next page); left turns back.
+ if (x >= 1 - this.o.dragZone && this.index < this.pages.length - 1) dir = 1;
+ else if (x <= this.o.dragZone && this.index > 0) dir = -1;
+ else return;
+
+ this.dragging = true;
+ this.dir = dir;
+ this.startX = e.clientX;
+ this.width = rect.width;
+ this.lastX = e.clientX;
+ this.lastT = e.timeStamp;
+ this.vel = 0;
+
+ // The leaf that visually turns: the current leaf when going forward, the
+ // previous (already-turned) leaf when going back.
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1); // ride on top while turning
+ this.active.classList.add('pf-turning');
+ this.root.classList.add('pf-grabbing');
+
+ try { this.root.setPointerCapture(e.pointerId); } catch (_) {}
+ window.addEventListener('pointermove', this._onMove);
+ window.addEventListener('pointerup', this._onUp);
+ window.addEventListener('pointercancel', this._onUp);
+ e.preventDefault();
+ };
+
+ PageFlip.prototype._move = function (e) {
+ if (!this.dragging) return;
+ var dt = e.timeStamp - this.lastT;
+ if (dt > 0) this.vel = (e.clientX - this.lastX) / dt; // px/ms, signed
+ this.lastX = e.clientX; this.lastT = e.timeStamp;
+
+ var dx = e.clientX - this.startX;
+ // progress 0 (flat/resting) .. 1 (fully turned) for this drag direction.
+ var progress = this.dir === 1
+ ? clamp(-dx / this.width, 0, 1) // forward: drag left (dx<0)
+ : clamp(dx / this.width, 0, 1); // back: drag right (dx>0)
+ // Forward turns the current leaf 0 -> -180; back turns the prev leaf -180 -> 0.
+ var angle = this.dir === 1 ? -progress * 180 : -180 + progress * 180;
+ this._setLeaf(this.active, angle);
+ this.progress = progress;
+ if (this.o.onTurn) this.o.onTurn(progress, this.dir);
+ };
+
+ PageFlip.prototype._up = function () {
+ if (!this.dragging) return;
+ this.dragging = false;
+ this.root.classList.remove('pf-grabbing');
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+
+ // A quick flick completes the flip even if you didn't cross the threshold —
+ // velocity sign must agree with the turn direction (drag left = negative).
+ var flick = (this.dir === 1 && this.vel < -this.o.flickVelocity) ||
+ (this.dir === -1 && this.vel > this.o.flickVelocity);
+ var complete = this.progress >= this.o.flipThreshold || flick;
+ this._settle(complete);
+ };
+
+ // Animate the active leaf to its resting angle, driving the shadow the whole
+ // way so it never "pops" at the seam between drag and snap.
+ PageFlip.prototype._settle = function (complete) {
+ var self = this;
+ this.animating = true;
+ var fromProg = this.progress || 0;
+ var toProg = complete ? 1 : 0;
+ var t0 = null;
+ cancelAnimationFrame(this.raf);
+
+ function frame(t) {
+ if (t0 == null) t0 = t;
+ var k = clamp((t - t0) / self.o.snapMs, 0, 1);
+ var p = fromProg + (toProg - fromProg) * easeInOut(k);
+ var angle = self.dir === 1 ? -p * 180 : -180 + p * 180;
+ self._setLeaf(self.active, angle);
+ if (self.o.onTurn) self.o.onTurn(p, self.dir);
+ if (k < 1) { self.raf = requestAnimationFrame(frame); return; }
+
+ // Landed. Commit the index and re-layout to the clean resting state.
+ self.active.classList.remove('pf-turning');
+ if (complete) self.index += self.dir;
+ self.animating = false;
+ self._layout();
+ if (complete && self.o.onFlip) self.o.onFlip(self.index);
+ }
+ this.raf = requestAnimationFrame(frame);
+ };
+
+ // Programmatic paging animates via the same settle path for a consistent feel.
+ PageFlip.prototype._go = function (dir) {
+ if (this.animating || this.dragging) return false;
+ if (dir === 1 && this.index >= this.pages.length - 1) return false;
+ if (dir === -1 && this.index <= 0) return false;
+ this.dir = dir;
+ this.width = this.root.clientWidth;
+ this.progress = 0;
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1);
+ this.active.classList.add('pf-turning');
+ this._settle(true);
+ return true;
+ };
+
+ PageFlip.prototype.next = function () { return this._go(1); };
+ PageFlip.prototype.prev = function () { return this._go(-1); };
+ PageFlip.prototype.goTo = function (i) {
+ i = clamp(i | 0, 0, this.pages.length - 1);
+ if (this.animating || this.dragging) return;
+ this.index = i; this._layout();
+ if (this.o.onFlip) this.o.onFlip(this.index);
+ };
+ PageFlip.prototype.count = function () { return this.pages.length; };
+ PageFlip.prototype.current = function () { return this.index; };
+
+ PageFlip.prototype.destroy = function () {
+ cancelAnimationFrame(this.raf);
+ this.root.removeEventListener('pointerdown', this._onDown);
+ this.root.removeEventListener('keydown', this._onKey);
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+ window.removeEventListener('resize', this._onResize);
+ delete this.root.__pageflip;
+ };
+
+ // Auto-init any [data-pageflip] on DOM ready so the drop-in "just works".
+ function auto() {
+ var els = document.querySelectorAll('[data-pageflip]');
+ Array.prototype.forEach.call(els, function (el) {
+ if (!el.__pageflip) new PageFlip(el);
+ });
+ }
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', auto);
+ } else {
+ auto();
+ }
+
+ global.PageFlip = PageFlip;
+ if (typeof module !== 'undefined' && module.exports) module.exports = PageFlip;
+})(typeof window !== 'undefined' ? window : this);
+</script>
+<script>
+(function(){
+ var root=document.querySelector('.dw-gbook'); if(!root) return;
+ var el=root.querySelector('[data-pageflip]');
+ var audio=root.querySelector('[data-gb=audio]');
+ var playBtn=root.querySelector('[data-gb=play]');
+ var countEl=root.querySelector('[data-gb=count]');
+ var COVER=2.20, INTERVAL=2.113, DUR=124.2, TOTAL=56;
+ // page-flip auto-inits on DOMContentLoaded; init now if not yet (PageFlip is idempotent).
+ var book=el.__pageflip||new PageFlip(el); if(!book){ return; }
+ var auto=false, raf=0, startT=0;
+ function count(){ countEl.textContent=(book.current()+1)+' / '+TOTAL; }
+ book.o.onFlip=count; count();
+ // manual paging (buttons stop auto-play, then turn — animated)
+ root.querySelector('[data-gb=prev]').addEventListener('click',function(){ stop(); book.prev(); });
+ root.querySelector('[data-gb=next]').addEventListener('click',function(){ stop(); book.next(); });
+ // grabbing a page mid-play cancels auto-play (you took the wheel)
+ el.addEventListener('pointerdown',function(){ if(auto) stop(); },true);
+
+ // Clock: prefer the narration's own currentTime (so pages track the VO), but fall
+ // back to a wall-clock timer so PLAY still flips the pages even if audio is blocked.
+ function elapsed(){
+ if(audio && !audio.paused && audio.currentTime>0.05) return audio.currentTime;
+ return (performance.now()-startT)/1000;
+ }
+ function tick(){
+ if(!auto) return;
+ var t=elapsed();
+ var target=t<COVER?0:Math.min(TOTAL-1,1+Math.floor((t-COVER)/INTERVAL));
+ // advance with the ANIMATED page-turn (next/prev), one step per frame as needed
+ if(target>book.current()) book.next();
+ else if(target<book.current()) book.prev();
+ if((audio&&audio.ended) || (t>=DUR && book.current()>=TOTAL-1)){ stop(); return; }
+ raf=requestAnimationFrame(tick);
+ }
+ function play(){
+ auto=true; playBtn.classList.add('is-playing'); playBtn.textContent='⏸ Pause';
+ if(book.current()>=TOTAL-1) book.goTo(0);
+ startT=performance.now();
+ if(audio){ try{ audio.currentTime=0; }catch(e){}
+ audio.play().then(function(){ startT=performance.now()-audio.currentTime*1000; })
+ .catch(function(){ /* audio blocked — pages still flip on the timer */ }); }
+ cancelAnimationFrame(raf); raf=requestAnimationFrame(tick);
+ }
+ function stop(){
+ auto=false; playBtn.classList.remove('is-playing'); playBtn.textContent='▶ Play narrated';
+ if(audio) audio.pause(); cancelAnimationFrame(raf);
+ }
+ playBtn.addEventListener('click',function(){ auto?stop():play(); });
+ if(audio) audio.addEventListener('ended',stop);
+})();
+</script>
+<!-- ==== /Graduate interactive flip book ==== --></div>
+</body></html>
\ No newline at end of file
diff --git a/public/collections/graduate-flipbook/module.html b/public/collections/graduate-flipbook/module.html
new file mode 100644
index 0000000..5401a90
--- /dev/null
+++ b/public/collections/graduate-flipbook/module.html
@@ -0,0 +1,1393 @@
+<!-- ==== Graduate interactive flip book (unified auto-play) ==== -->
+<style>/*!
+ * page-flip.css — visual layer for page-flip.js.
+ *
+ * The JS drives WHEN things move; this file makes them look like paper. The
+ * shadow work Meng To flagged lives here in three cooperating layers:
+ * 1. .pf-curl — per-leaf ambient-occlusion gradient (opacity driven by JS)
+ * 2. .pf-gutter — the fixed spine shadow down the binding edge
+ * 3. .pf-face — subtle paper grain + a page-edge highlight
+ *
+ * Tunable via CSS custom properties (all overridable per instance):
+ * --pf-persp 3D perspective depth (set by JS from opts.perspective)
+ * --pf-gutter spine-shadow peak opacity (set by JS from opts.gutterShadow)
+ * --pf-paper page background
+ * --pf-ink page text color
+ * --pf-radius corner radius of the book
+ */
+
+.pageflip {
+ --pf-paper: #fbf9f4; /* warm sketchbook stock */
+ --pf-paper-2: #f3efe6; /* backside, slightly darker */
+ --pf-ink: #2a2622;
+ --pf-radius: 10px;
+ --pf-edge: rgba(0, 0, 0, 0.10); /* page-edge line */
+ position: relative;
+ width: 100%;
+ aspect-ratio: 3 / 4; /* portrait sketchbook; override as needed */
+ margin: 0 auto;
+ perspective: var(--pf-persp, 2200px);
+ perspective-origin: 0% 50%; /* eye toward the spine so the turn arcs correctly */
+ touch-action: pan-y; /* let vertical scroll through; we own horizontal */
+ user-select: none;
+ -webkit-user-select: none;
+ outline: none;
+}
+.pageflip.pf-grabbing { cursor: grabbing; }
+.pageflip:not(.pf-grabbing) { cursor: grab; }
+
+/* Each leaf pivots on its spine edge (left). */
+.pf-page {
+ position: absolute;
+ inset: 0;
+ transform-origin: left center;
+ transform-style: preserve-3d;
+ will-change: transform;
+ border-radius: 0 var(--pf-radius) var(--pf-radius) 0;
+ /* No CSS transition — the JS rAF loop owns every frame so the shadow and the
+ transform stay locked together. A CSS transition here would desync them. */
+}
+
+/* Front + back faces. backface-visibility hides whichever side faces away, so
+ the two faces never bleed through each other mid-turn. */
+.pf-face {
+ position: absolute;
+ inset: 0;
+ backface-visibility: hidden;
+ -webkit-backface-visibility: hidden;
+ border-radius: inherit;
+ overflow: hidden;
+ box-sizing: border-box;
+ padding: clamp(16px, 5%, 40px);
+ color: var(--pf-ink);
+ background: var(--pf-paper);
+ /* faint paper grain + a bright page-edge highlight on the free (right) edge */
+ background-image:
+ linear-gradient(90deg, rgba(0,0,0,0.05) 0, rgba(0,0,0,0) 3%), /* spine-side shading */
+ linear-gradient(270deg, rgba(255,255,255,0.6) 0, rgba(255,255,255,0) 2%);/* free-edge highlight */
+ box-shadow: inset 0 0 0 1px var(--pf-edge);
+}
+.pf-front { transform: rotateY(0deg); }
+.pf-back {
+ transform: rotateY(180deg);
+ background: var(--pf-paper-2);
+ /* the back of a sheet: mirror the shading (highlight now on the left) */
+ background-image:
+ linear-gradient(270deg, rgba(0,0,0,0.06) 0, rgba(0,0,0,0) 4%),
+ linear-gradient(90deg, rgba(255,255,255,0.4) 0, rgba(255,255,255,0) 3%);
+}
+
+/*
+ * THE CURL SHADOW — the layer that sells the turn.
+ * Its opacity is set every frame by JS (peaks as the page stands perpendicular).
+ * --pf-curl-dir flips the gradient once we pass 90° so the darkness always
+ * gathers where the sheet is bending away from the light, not on the flat face.
+ */
+.pf-curl {
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ border-radius: inherit;
+ opacity: 0;
+ /* dir 0 (front showing): dark gathers toward the free/right edge */
+ background: linear-gradient(
+ 100deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+/* dir 1 (back showing, past 90°): mirror so dark gathers toward the spine/left */
+.pf-curl[style*="--pf-curl-dir: 1"] {
+ background: linear-gradient(
+ 260deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+
+/* The turning leaf gets a real drop shadow so it lifts off the stack. */
+.pf-page.pf-turning {
+ box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
+}
+
+/*
+ * THE GUTTER / SPINE SHADOW — fixed, always on, so the book reads as bound.
+ * A soft dark band hugging the binding edge (left). Peak opacity from --pf-gutter.
+ */
+.pf-gutter {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 12%;
+ pointer-events: none;
+ z-index: 9999;
+ border-radius: var(--pf-radius) 0 0 var(--pf-radius);
+ background: linear-gradient(
+ 90deg,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 1)) 0,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 0.35)) 40%,
+ rgba(0, 0, 0, 0) 100%
+ );
+ mix-blend-mode: multiply;
+}
+
+/* Respect users who ask for less motion: snap instantly (JS still works, the
+ rAF just completes in one frame's worth of visual change to them via CSS is
+ n/a — but we drop the lift shadow that draws the eye). */
+@media (prefers-reduced-motion: reduce) {
+ .pf-page.pf-turning { box-shadow: none; }
+}
+</style>
+<section class="dw-gbook" aria-label="The Graduate Collection flip book">
+ <div class="dw-gbook__bar">
+ <span class="dw-gbook__label">The Flip Book · interactive</span>
+ <div class="dw-gbook__ctl">
+ <button type="button" class="gb-btn" data-gb="prev" aria-label="Previous page">‹</button>
+ <span class="gb-count" data-gb="count">1 / 56</span>
+ <button type="button" class="gb-btn" data-gb="next" aria-label="Next page">›</button>
+ <button type="button" class="gb-btn gb-btn--play" data-gb="play" aria-label="Play narrated tour">▶ Play narrated</button>
+ </div>
+ </div>
+ <div class="pageflip dw-gbook__book" data-pageflip>
+
+ <div class="pf-page gb-cover" role="group" aria-label="Cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__brand">Designer Wallcoverings</span>
+ <span class="gb-cover__title">The Graduate Collection</span>
+ <span class="gb-cover__sub">Flip through it — or press play for the narrated tour</span>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoalRoom.png?v=1709835248" alt="All Over Leopard - Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Blue</span>
+ <span class="gb-pageno">1 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoal.png?v=1709835248" alt="All Over Leopard - Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoalRoom_e9a4799e-903c-417e-99b9-158270cc5cfd.png?v=1750793863" alt="All Over Leopard Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard Blue</span>
+ <span class="gb-pageno">2 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.37.36PM.png?v=1750793883" alt="All Over Leopard Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.36.55PM.png?v=1750793822" alt="All Over Leopard Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard Charcoal</span>
+ <span class="gb-pageno">3 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.36.31PM.png?v=1750793823" alt="All Over Leopard Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Aubergine">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/A902549B-ECE0-4410-8226-32E31F07196B.jpg?v=1772164893" alt="All Over Leopard - Aubergine in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Aubergine</span>
+ <span class="gb-pageno">4 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/B48C9B51-6F0D-4973-985F-992BBF14F800.jpg?v=1772164893" alt="All Over Leopard - Aubergine pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Brown">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/9B0CD372-BE5E-4886-9E91-0574F2BADC00.jpg?v=1772164915" alt="All Over Leopard - Brown in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Brown</span>
+ <span class="gb-pageno">5 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB.jpg?v=1772164915" alt="All Over Leopard - Brown pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Leopard Brown">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB_f0e70547-6d49-4051-974f-a3d29f49e320.jpg?v=1775598515" alt="Leopard Brown in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">Leopard Brown</span>
+ <span class="gb-pageno">6 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB_f0e70547-6d49-4051-974f-a3d29f49e320.jpg?v=1775598515" alt="Leopard Brown pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian - Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at4.01.27PM.png?v=1633734145" alt="Visitorian - Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian - Taupe</span>
+ <span class="gb-pageno">7 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0001.jpg?v=1570091053" alt="Visitorian - Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Navy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0002.jpg?v=1570091053" alt="Visitorian Navy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Navy</span>
+ <span class="gb-pageno">8 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0002.jpg?v=1570091053" alt="Visitorian Navy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Mauve">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0003.jpg?v=1570091053" alt="Visitorian Mauve in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Mauve</span>
+ <span class="gb-pageno">9 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0003.jpg?v=1570091053" alt="Visitorian Mauve pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at3.49.25PM.png?v=1633733413" alt="Visitorian Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Blue</span>
+ <span class="gb-pageno">10 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0004.jpg?v=1570091053" alt="Visitorian Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Jolly Boy Dog & Friends">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-05-12at7.31.52AM.png?v=1747060363" alt="Jolly Boy Dog & Friends in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Jolly Boy Dog & Friends</span>
+ <span class="gb-pageno">11 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-05-12at7.30.51AM.png?v=1747060405" alt="Jolly Boy Dog & Friends pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Steampunk Notice Board">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/QqjaFxcfRPyeCGYhD9G3_steampunk_notice_board_insitu_grande_7d8d9494-189c-43cb-9488-24944ce782b8.jpg?v=1612388487" alt="Steampunk Notice Board in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Steampunk Notice Board</span>
+ <span class="gb-pageno">12 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0002.jpg?v=1612388486" alt="Steampunk Notice Board pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Portarait Gallery Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portarait_Gallery_Taupe_1.jpg?v=1602006843" alt="Portarait Gallery Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Portarait Gallery Taupe</span>
+ <span class="gb-pageno">13 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portarait_Gallery_Taupe_1.jpg?v=1602006843" alt="Portarait Gallery Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dachshund Dog">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DachshundNaturalRoom_dce6601a-c864-4764-b024-8e4d2ac7b818.png?v=1750792583" alt="Dachshund Dog in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Dachshund Dog</span>
+ <span class="gb-pageno">14 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/NEWDachshund_NATURAL.jpg?v=1750792583" alt="Dachshund Dog pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Colonel Fox at the Gentleman's Club - Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Gentlemans_Club_Mustard.png?v=1730485289" alt="Colonel Fox at the Gentleman's Club - Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Colonel Fox at the Gentleman's Club - Mustard</span>
+ <span class="gb-pageno">15 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8900-DesignerWallcoverings-Los-Angeles-1_e3102e92-3911-4763-8ffd-1bb3d218d57e.jpg?v=1730485220" alt="Colonel Fox at the Gentleman's Club - Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Fashionista Tinted">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/hCdYg71Rm1VQjlktJ1lA_Charlotte_cory_fashionista_wallpaper_roomset_grande_280e48d5-09d9-46fe-becb-43b86046f011.jpg?v=1570091054" alt="Fashionista Tinted in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Fashionista Tinted</span>
+ <span class="gb-pageno">16 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0004.jpg?v=1570091053" alt="Fashionista Tinted pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Fashionista Black & White">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/wyqj6AS0QX6xhm67PvOg_Charlotte_Cory_-_Fashionista_black___white_wallpaper_grande_2c2fac20-d910-402f-bf3a-1b896e520fb8.jpg?v=1570091054" alt="Fashionista Black & White in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Fashionista Black & White</span>
+ <span class="gb-pageno">17 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0005.jpg?v=1570091053" alt="Fashionista Black & White pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Rabbit Rabbit Rabbit">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/MVPwIVSsSJ6IiSxGdW0I_rabbit_rabbit_rabbit_insitu_grande_142657d9-0884-44f7-b0a3-c284dafbae19.jpg?v=1572310841" alt="Rabbit Rabbit Rabbit in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Rabbit Rabbit Rabbit</span>
+ <span class="gb-pageno">18 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0003.jpg?v=1572310841" alt="Rabbit Rabbit Rabbit pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Gold & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.53.12PM.png?v=1694465625" alt="Showgirls Metallic Gold & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Gold & Black</span>
+ <span class="gb-pageno">19 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.53.19PM.png?v=1694465646" alt="Showgirls Metallic Gold & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Mustard & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at11.42.05AM.png?v=1694465398" alt="Showgirls Metallic Mustard & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Mustard & Cream</span>
+ <span class="gb-pageno">20 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.49.13PM.png?v=1694465405" alt="Showgirls Metallic Mustard & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Pink & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-87020-DesignerWallcoverings-Los-Angeles-1.png?v=1694465676" alt="Showgirls Metallic Pink & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Pink & Black</span>
+ <span class="gb-pageno">21 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicPink_Black.jpg?v=1730488614" alt="Showgirls Metallic Pink & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Portrait Gallery Navy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portrait_Gallery_Navy_2.jpg?v=1602006845" alt="Portrait Gallery Navy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Portrait Gallery Navy</span>
+ <span class="gb-pageno">22 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portrait_Gallery_Navy_2.jpg?v=1602006845" alt="Portrait Gallery Navy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Bronze & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.33.07PM.png?v=1694464431" alt="Showgirls Metallic Bronze & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Bronze & Cream</span>
+ <span class="gb-pageno">23 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicBronze_Cream_1024x1024_3f9df313-e6aa-40c7-adac-97b90df0b067.jpg?v=1730488554" alt="Showgirls Metallic Bronze & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Pink & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.38.05PM.png?v=1694464738" alt="Showgirls Metallic Pink & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Pink & Cream</span>
+ <span class="gb-pageno">24 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.37.57PM.png?v=1694465689" alt="Showgirls Metallic Pink & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Teal & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.42.16PM.png?v=1694464957" alt="Showgirls Metallic Teal & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Teal & Black</span>
+ <span class="gb-pageno">25 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicTeal_Black.jpg?v=1730488416" alt="Showgirls Metallic Teal & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Teal & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.45.39PM.png?v=1694465204" alt="Showgirls Metallic Teal & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Teal & Cream</span>
+ <span class="gb-pageno">26 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicTeal_Cream_1024x1024_ba6114de-6784-4aa7-ac31-0f45ffecb3ec.jpg?v=1730488356" alt="Showgirls Metallic Teal & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Bronze & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicBronze_Black.jpg?v=1730488254" alt="Showgirls Metallic Bronze & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Bronze & Black</span>
+ <span class="gb-pageno">27 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.51.20PM.png?v=1694465520" alt="Showgirls Metallic Bronze & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsblueroom_0264483b-3df5-48ca-a4e4-0227be6ccfeb.png?v=1730484646" alt="Cavalcade Of Cats Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Blue</span>
+ <span class="gb-pageno">28 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsblue_fa62827d-3eb7-4812-982a-5ef6150ee8f3.png?v=1730484646" alt="Cavalcade Of Cats Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsmustardroom_a24237f0-6336-4e09-9363-dd56e0bd8261.png?v=1730484639" alt="Cavalcade Of Cats Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Mustard</span>
+ <span class="gb-pageno">29 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsmustard_122455d1-6d9e-4092-bc80-3cc2cd0868b6.png?v=1730484639" alt="Cavalcade Of Cats Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Red">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsredroom_24cc4ace-220e-44e5-baaa-8e5b45352ec5.png?v=1730484633" alt="Cavalcade Of Cats Red in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Red</span>
+ <span class="gb-pageno">30 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsred_18a38a54-b823-4ac2-a1b8-87ee5d1f77ba.png?v=1730484633" alt="Cavalcade Of Cats Red pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogCreamRoom_32e3d309-1b1e-4f35-aedc-112ca25c9228.png?v=1730484609" alt="Top Dog Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog Cream</span>
+ <span class="gb-pageno">31 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogCream_252e8492-113b-46a6-ac5c-558b2a6693bd.png?v=1730484609" alt="Top Dog Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogGreyRoom_8641f7a0-a5bd-4256-ad2e-47f5595dc4e7.png?v=1730484602" alt="Top Dog Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog Grey</span>
+ <span class="gb-pageno">32 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogGrey_d06cfc3e-a80f-49c2-b203-8e42a86b1b58.png?v=1730484602" alt="Top Dog Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Burgundy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryBurgundyroom_cffd75f2-e080-4835-9f37-cdb52caa165e.png?v=1730484596" alt="At The Art Gallery Burgundy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Burgundy</span>
+ <span class="gb-pageno">33 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryBurgundy_4f783d0d-251c-43a2-9519-72ee14418169.png?v=1730484596" alt="At The Art Gallery Burgundy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryCharcoalroom_d9e4cfe7-bd89-401b-9942-8b11bf89473d.png?v=1730484591" alt="At The Art Gallery Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Charcoal</span>
+ <span class="gb-pageno">34 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryCharcoal_b0e9858f-c4ee-46b7-b6e5-6c37739a23c1.png?v=1730484591" alt="At The Art Gallery Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGallerytealroom_6b1945f9-f9dd-4808-9254-81ed6963a351.png?v=1730484584" alt="At The Art Gallery Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Teal</span>
+ <span class="gb-pageno">35 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryteal_d8dd0ab4-a676-4120-9ed7-a55f46f02724.png?v=1730484584" alt="At The Art Gallery Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDog_GREEN_Roomset1.jpg?v=1722271854" alt="Top Dog in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog</span>
+ <span class="gb-pageno">36 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Top_Dog_Green_5ed388b8-f593-4438-9b5b-3d289a825f81.jpg?v=1722271739" alt="Top Dog pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Rose">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8901-DesignerWallcoverings-Los-Angeles-1.jpg?v=1730485679" alt="The Soire Rose in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Rose</span>
+ <span class="gb-pageno">37 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8901-DesignerWallcoverings-Los-Angeles-1_5aaf1b13-ea6e-4ce8-9e3f-53cb54939af2.jpg?v=1730485729" alt="The Soire Rose pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8902-DesignerWallcoverings-Los-Angeles-1_65b1df4d-b2bb-4708-add6-8236787a35fd.jpg?v=1730489384" alt="The Soire Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Blue</span>
+ <span class="gb-pageno">38 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8902-DesignerWallcoverings-Los-Angeles-1_65b1df4d-b2bb-4708-add6-8236787a35fd.jpg?v=1730489384" alt="The Soire Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Peach">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8903-DesignerWallcoverings-Los-Angeles-1_0d792d9d-49e8-451d-87d8-cb988273943b.jpg?v=1730489929" alt="The Soire Peach in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Peach</span>
+ <span class="gb-pageno">39 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8903-DesignerWallcoverings-Los-Angeles-1_0d792d9d-49e8-451d-87d8-cb988273943b.jpg?v=1730489929" alt="The Soire Peach pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Plaster">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_ce2a9161-c4a3-470c-8a2f-57f8c6ad2951.jpg?v=1730490279" alt="The Soire Plaster in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Plaster</span>
+ <span class="gb-pageno">40 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_ce2a9161-c4a3-470c-8a2f-57f8c6ad2951.jpg?v=1730490279" alt="The Soire Plaster pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_d30a1059-c72c-4b5a-84b3-a863a568b776.jpg?v=1730490513" alt="The Soire Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Taupe</span>
+ <span class="gb-pageno">41 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_d30a1059-c72c-4b5a-84b3-a863a568b776.jpg?v=1730490513" alt="The Soire Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8906-DesignerWallcoverings-Los-Angeles-1_a03ddfea-1e9f-48ca-9c90-4e08b979c0a0.jpg?v=1730490810" alt="The Soire Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Mustard</span>
+ <span class="gb-pageno">42 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8906-DesignerWallcoverings-Los-Angeles-1_a03ddfea-1e9f-48ca-9c90-4e08b979c0a0.jpg?v=1730490810" alt="The Soire Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande - Plum">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/stag_plum_offset_grande_7ce7d09c-2260-43df-9408-be0985c14fe0.jpg?v=1570091054" alt="Stag Grande - Plum in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande - Plum</span>
+ <span class="gb-pageno">43 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0002.jpg?v=1570091054" alt="Stag Grande - Plum pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_Teal_Large_head_grande_e3b54fee-2979-4805-9de2-145b12fe2eed.jpg?v=1570091054" alt="Stag Grande Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande Teal</span>
+ <span class="gb-pageno">44 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0006.jpg?v=1570091054" alt="Stag Grande Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ABgIgtqVS3OOiOgAFth3_stag_head_grey_grande_28e10eef-c4f6-4ac0-831d-139f08c675f3.jpg?v=1570091054" alt="Stag Grande Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande Grey</span>
+ <span class="gb-pageno">45 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0007.jpg?v=1570091054" alt="Stag Grande Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Stag_Print_Wallpaper_-_Teal_1024x1024_74130f65-820d-4318-862d-4a3bb0bf93a5.png?v=1730488729" alt="Small Stag Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Teal</span>
+ <span class="gb-pageno">46 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at3.36.54PM.png?v=1633732668" alt="Small Stag Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllicGold_TealRoom_891a94b2-3962-4f18-b19d-102772052fd7.png?v=1730484627" alt="Dipped In Moonlight Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Charcoal</span>
+ <span class="gb-pageno">47 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllicGold_Teal_c272519f-6ae8-4897-b33d-f518c24008df.png?v=1730484627" alt="Dipped In Moonlight Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_CreamRoom_b6207c57-e66f-4645-979e-cb39a415a9fb.png?v=1730484621" alt="Dipped In Moonlight Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Cream</span>
+ <span class="gb-pageno">48 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_Cream_4c873c3d-77ee-4fcf-8900-ad39cdbdfe1c.png?v=1730484621" alt="Dipped In Moonlight Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_TealRoom_cada0f29-52ed-43d3-b40c-4e78c71b3e1e.png?v=1730484615" alt="Dipped In Moonlight Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Teal</span>
+ <span class="gb-pageno">49 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_Teal_fc6a1852-7e7d-472b-a075-06ef92f14c8a.png?v=1730484615" alt="Dipped In Moonlight Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Plum">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/stag_print_plum_grande_b0ad71c0-d6ed-47fc-8527-c9aecd18856f.jpg?v=1570091054" alt="Small Stag Plum in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Plum</span>
+ <span class="gb-pageno">50 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0003.jpg?v=1570091054" alt="Small Stag Plum pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_print_grey_grande_4c9922c5-ea6f-408f-b033-ec070caa69ad.jpg?v=1689895357" alt="Small Stag Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Grey</span>
+ <span class="gb-pageno">51 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-87043-DesignerWallcoverings-Los-Angeles-2.png?v=1689895357" alt="Small Stag Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_1.jpg?v=1602006861" alt="Stag in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag</span>
+ <span class="gb-pageno">52 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_1.jpg?v=1602006861" alt="Stag pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Pistachio">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.31.12PM.png?v=1709670701" alt="Vestige Pistachio in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Pistachio</span>
+ <span class="gb-pageno">53 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.30.53PM.png?v=1709670718" alt="Vestige Pistachio pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.38.06PM.png?v=1776370140" alt="Vestige Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Mustard</span>
+ <span class="gb-pageno">54 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.38.25PM.png?v=1776370140" alt="Vestige Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.41.19PM.png?v=1709671326" alt="Vestige Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Grey</span>
+ <span class="gb-pageno">55 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.41.06PM.png?v=1709671354" alt="Vestige Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page gb-cover gb-cover--back" role="group" aria-label="Back cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__title">Shop the Graduate Collection</span>
+ <a class="gb-cover__cta" href="https://www.designerwallcoverings.com/collections/the-graduate-collection">Browse all 55 patterns →</a>
+ </div>
+ </div>
+ </div>
+ <audio class="dw-gbook__audio" data-gb="audio" preload="none" src="https://marketing.designerwallcoverings.com/reels/graduate-narration.mp4"></audio>
+</section>
+<style>
+ .dw-gbook{max-width:1100px;margin:0 auto 1.75rem;padding:0 1rem;font-family:'Cormorant Garamond',Georgia,serif;}
+ .dw-gbook__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:0 0 .6rem;flex-wrap:wrap;}
+ .dw-gbook__label{font-size:.95rem;letter-spacing:.12em;text-transform:uppercase;color:#8a7f72;}
+ .dw-gbook__ctl{display:flex;align-items:center;gap:.4rem;}
+ .gb-btn{border:1px solid #cbb8a3;background:#fff;color:#3a3128;border-radius:999px;padding:.35rem .8rem;font:inherit;font-size:.9rem;cursor:pointer;line-height:1;transition:background .15s,color .15s;}
+ .gb-btn:hover{background:#f3ece2;}
+ .gb-btn--play{background:#14110e;color:#f4ede2;border-color:#14110e;}
+ .gb-btn--play:hover{background:#2a2118;}
+ .gb-btn--play.is-playing{background:#8a1f2b;border-color:#8a1f2b;}
+ .gb-count{min-width:4.5em;text-align:center;color:#6b6055;font-size:.9rem;}
+ .dw-gbook__book{aspect-ratio:16/9;background:#14110e;border-radius:10px;box-shadow:0 14px 48px rgba(0,0,0,.22);}
+ /* spread: verso (room + name) | recto (pattern) */
+ .gb-spread{position:absolute;inset:0;display:grid;grid-template-columns:1fr 1fr;background:#fbf7f1;}
+ .gb-verso{position:relative;overflow:hidden;background:#efe7db;}
+ .gb-room{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-room--none{background:linear-gradient(135deg,#e7ddce,#d8ccba);}
+ .gb-meta{position:absolute;left:0;right:0;bottom:0;padding:1rem 1.1rem;display:flex;flex-direction:column;gap:.15rem;background:linear-gradient(0deg,rgba(20,17,14,.72),rgba(20,17,14,0));color:#fdf8f0;}
+ .gb-chapter{font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;opacity:.85;}
+ .gb-name{font-size:1.45rem;line-height:1.1;}
+ .gb-pageno{font-size:.72rem;opacity:.7;letter-spacing:.1em;}
+ .gb-recto{position:relative;overflow:hidden;background:#fff;}
+ .gb-swatch{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-cover__inner{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:.5rem;background:radial-gradient(120% 120% at 50% 20%,#241d15,#14110e);color:#f4ede2;padding:2rem;}
+ .gb-cover__brand{font-size:.8rem;letter-spacing:.28em;text-transform:uppercase;color:#c9a86a;}
+ .gb-cover__title{font-size:2.1rem;line-height:1.05;}
+ .gb-cover__sub{font-size:1rem;color:#b6a894;}
+ .gb-cover__cta{margin-top:.4rem;color:#14110e;background:#c9a86a;border-radius:999px;padding:.5rem 1.1rem;text-decoration:none;font-size:.95rem;}
+ @media(max-width:640px){.gb-name{font-size:1.15rem}.gb-cover__title{font-size:1.5rem}.dw-gbook__book{aspect-ratio:4/3}}
+ @media(prefers-reduced-motion:reduce){.dw-gbook__book{scroll-behavior:auto}}
+</style>
+<script>/*!
+ * page-flip.js — a zero-dependency drag-to-paginate book / sketchbook UI.
+ *
+ * Seeded by Meng To (@MengTo)'s 2026-08-06 "page-flipping sketchbook" post:
+ * "AI gives you the basics unless you hand it a solid open-source to work
+ * from. So I asked for drag to paginate, which took many fixes for shadows."
+ * This file IS that solid open-source to work from. The hard parts it gets
+ * right — the ones "the basics" skip — are called out inline: the curl
+ * ambient-occlusion shadow, the gutter/spine shadow, velocity-flick release,
+ * and keeping the shadow synced to the page THROUGH the snap animation.
+ *
+ * Contract (see demo.html):
+ * <div class="pageflip" data-pageflip>
+ * <div class="pf-page">…page 1…</div>
+ * <div class="pf-page">…page 2…</div>
+ * …
+ * </div>
+ * Each direct .pf-page child becomes one leaf. Author content lives on the
+ * front; the back is an auto-generated paper backside.
+ *
+ * Usage:
+ * const book = new PageFlip(el, { onFlip(i){…} }); // or auto-init below
+ * book.next(); book.prev(); book.goTo(3);
+ *
+ * No build step, no framework, no license friction — vanilla ES2019.
+ */
+(function (global) {
+ 'use strict';
+
+ var DEFAULTS = {
+ dragZone: 0.5, // fraction of page width (from the outer edge) that starts a drag
+ flipThreshold: 0.5, // release past this fraction of the turn (0..1) completes the flip
+ flickVelocity: 0.6, // px/ms; a faster release completes the flip regardless of threshold
+ snapMs: 420, // snap animation duration
+ curlShadow: 0.42, // peak opacity of the curl ambient-occlusion shadow (0..1)
+ gutterShadow: 0.28, // peak opacity of the fixed spine/gutter shadow (0..1)
+ perspective: 2200, // px; larger = flatter/less dramatic depth
+ onFlip: null, // (index) => void, fired after a completed flip settles
+ onTurn: null // (progress, dir) => void, fired continuously while turning (progress 0..1)
+ };
+
+ // power-in-out easing keeps the snap feeling weighted, not linear/robotic.
+ function easeInOut(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }
+ function clamp(v, lo, hi) { return v < lo ? lo : v > hi ? hi : v; }
+
+ function PageFlip(root, opts) {
+ if (!root) throw new Error('PageFlip: root element required');
+ if (root.__pageflip) return root.__pageflip; // idempotent
+ this.root = root;
+ this.o = Object.assign({}, DEFAULTS, opts || {});
+ this.pages = [];
+ this.index = 0; // top face-up leaf
+ this.dragging = false;
+ this.raf = 0;
+ root.__pageflip = this;
+ this._build();
+ this._bind();
+ this._layout();
+ }
+
+ PageFlip.prototype._build = function () {
+ var root = this.root;
+ root.classList.add('pageflip');
+ root.style.setProperty('--pf-persp', this.o.perspective + 'px');
+
+ // Promote each .pf-page child into a two-faced leaf with a curl-shadow layer.
+ var kids = Array.prototype.filter.call(root.children, function (c) {
+ return c.classList && c.classList.contains('pf-page');
+ });
+ var self = this;
+ kids.forEach(function (leaf, i) {
+ // Move author content into a front face (once — re-init safe).
+ if (!leaf.querySelector(':scope > .pf-front')) {
+ var front = document.createElement('div');
+ front.className = 'pf-face pf-front';
+ while (leaf.firstChild) front.appendChild(leaf.firstChild);
+ leaf.appendChild(front);
+
+ var back = document.createElement('div');
+ back.className = 'pf-face pf-back';
+ back.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(back);
+
+ // Curl shadow: a gradient overlay whose opacity we drive from the turn
+ // angle. This is the "many fixes for shadows" layer — see physics.md.
+ var curl = document.createElement('div');
+ curl.className = 'pf-curl';
+ curl.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(curl);
+ }
+ leaf.dataset.pfIndex = String(i);
+ leaf.setAttribute('role', 'group');
+ leaf.setAttribute('aria-roledescription', 'page');
+ self.pages.push(leaf);
+ });
+
+ // Fixed gutter/spine shadow — always present at the binding edge so the
+ // book reads as bound even when no page is turning.
+ if (!root.querySelector(':scope > .pf-gutter')) {
+ var gutter = document.createElement('div');
+ gutter.className = 'pf-gutter';
+ gutter.setAttribute('aria-hidden', 'true');
+ root.appendChild(gutter);
+ root.style.setProperty('--pf-gutter', this.o.gutterShadow);
+ }
+ };
+
+ PageFlip.prototype._layout = function () {
+ // Resting state: leaves before `index` are turned (-180°) and stack on the
+ // left ascending; leaves at/after `index` are flat and stack on the right
+ // with `index` on top.
+ var n = this.pages.length;
+ for (var i = 0; i < n; i++) {
+ var leaf = this.pages[i];
+ if (i < this.index) {
+ this._setLeaf(leaf, -180, 0);
+ leaf.style.zIndex = String(i); // earlier turned pages sink lower
+ leaf.classList.add('pf-turned');
+ } else {
+ this._setLeaf(leaf, 0, 0);
+ leaf.style.zIndex = String(n - i); // current on top, rest descend
+ leaf.classList.remove('pf-turned');
+ }
+ leaf.setAttribute('aria-hidden', i === this.index || i === this.index + 1 ? 'false' : 'true');
+ }
+ this.root.dataset.pfIndex = String(this.index);
+ };
+
+ // Apply a rotation + its matching shadow to one leaf. angleDeg in [-180, 0].
+ PageFlip.prototype._setLeaf = function (leaf, angleDeg, forceShadow) {
+ leaf.style.transform = 'rotateY(' + angleDeg + 'deg)';
+ var curl = leaf.querySelector(':scope > .pf-curl');
+ if (!curl) return;
+ // sin() peaks at 90° (page standing up) and vanishes flat at 0°/180° — the
+ // physically-right shape for ambient occlusion of a curling sheet.
+ var a = Math.abs(angleDeg);
+ var s = (forceShadow != null ? forceShadow : Math.sin(a * Math.PI / 180)) * this.o.curlShadow;
+ curl.style.opacity = String(s);
+ // Past 90° we're looking at the back of the sheet: flip the gradient so the
+ // shading gathers toward the (now leading) spine edge, not the free edge.
+ curl.style.setProperty('--pf-curl-dir', a > 90 ? '1' : '0');
+ };
+
+ PageFlip.prototype._bind = function () {
+ var self = this;
+ this._onDown = function (e) { self._down(e); };
+ this._onMove = function (e) { self._move(e); };
+ this._onUp = function (e) { self._up(e); };
+ this.root.addEventListener('pointerdown', this._onDown);
+ // Keyboard paging for accessibility. Only set tabIndex when the element
+ // has no explicit tabindex attribute; avoids overwriting intentional -1.
+ if (!this.root.hasAttribute('tabindex')) this.root.tabIndex = 0;
+ // Stored (not anonymous) so destroy() can remove it — otherwise re-init on
+ // the same element stacks keydown listeners.
+ this._onKey = function (e) {
+ if (e.key === 'ArrowRight' || e.key === 'PageDown') { self.next(); e.preventDefault(); }
+ else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { self.prev(); e.preventDefault(); }
+ };
+ this.root.addEventListener('keydown', this._onKey);
+ this._onResize = function () { self.width = self.root.clientWidth; };
+ window.addEventListener('resize', this._onResize);
+ this.width = this.root.clientWidth;
+ };
+
+ PageFlip.prototype._down = function (e) {
+ if (this.animating) return;
+ var rect = this.root.getBoundingClientRect();
+ var x = (e.clientX - rect.left) / rect.width; // 0 (spine/left) .. 1 (outer/right)
+ var dir;
+ // Right dragZone turns forward (needs a next page); left turns back.
+ if (x >= 1 - this.o.dragZone && this.index < this.pages.length - 1) dir = 1;
+ else if (x <= this.o.dragZone && this.index > 0) dir = -1;
+ else return;
+
+ this.dragging = true;
+ this.dir = dir;
+ this.startX = e.clientX;
+ this.width = rect.width;
+ this.lastX = e.clientX;
+ this.lastT = e.timeStamp;
+ this.vel = 0;
+
+ // The leaf that visually turns: the current leaf when going forward, the
+ // previous (already-turned) leaf when going back.
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1); // ride on top while turning
+ this.active.classList.add('pf-turning');
+ this.root.classList.add('pf-grabbing');
+
+ try { this.root.setPointerCapture(e.pointerId); } catch (_) {}
+ window.addEventListener('pointermove', this._onMove);
+ window.addEventListener('pointerup', this._onUp);
+ window.addEventListener('pointercancel', this._onUp);
+ e.preventDefault();
+ };
+
+ PageFlip.prototype._move = function (e) {
+ if (!this.dragging) return;
+ var dt = e.timeStamp - this.lastT;
+ if (dt > 0) this.vel = (e.clientX - this.lastX) / dt; // px/ms, signed
+ this.lastX = e.clientX; this.lastT = e.timeStamp;
+
+ var dx = e.clientX - this.startX;
+ // progress 0 (flat/resting) .. 1 (fully turned) for this drag direction.
+ var progress = this.dir === 1
+ ? clamp(-dx / this.width, 0, 1) // forward: drag left (dx<0)
+ : clamp(dx / this.width, 0, 1); // back: drag right (dx>0)
+ // Forward turns the current leaf 0 -> -180; back turns the prev leaf -180 -> 0.
+ var angle = this.dir === 1 ? -progress * 180 : -180 + progress * 180;
+ this._setLeaf(this.active, angle);
+ this.progress = progress;
+ if (this.o.onTurn) this.o.onTurn(progress, this.dir);
+ };
+
+ PageFlip.prototype._up = function () {
+ if (!this.dragging) return;
+ this.dragging = false;
+ this.root.classList.remove('pf-grabbing');
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+
+ // A quick flick completes the flip even if you didn't cross the threshold —
+ // velocity sign must agree with the turn direction (drag left = negative).
+ var flick = (this.dir === 1 && this.vel < -this.o.flickVelocity) ||
+ (this.dir === -1 && this.vel > this.o.flickVelocity);
+ var complete = this.progress >= this.o.flipThreshold || flick;
+ this._settle(complete);
+ };
+
+ // Animate the active leaf to its resting angle, driving the shadow the whole
+ // way so it never "pops" at the seam between drag and snap.
+ PageFlip.prototype._settle = function (complete) {
+ var self = this;
+ this.animating = true;
+ var fromProg = this.progress || 0;
+ var toProg = complete ? 1 : 0;
+ var t0 = null;
+ cancelAnimationFrame(this.raf);
+
+ function frame(t) {
+ if (t0 == null) t0 = t;
+ var k = clamp((t - t0) / self.o.snapMs, 0, 1);
+ var p = fromProg + (toProg - fromProg) * easeInOut(k);
+ var angle = self.dir === 1 ? -p * 180 : -180 + p * 180;
+ self._setLeaf(self.active, angle);
+ if (self.o.onTurn) self.o.onTurn(p, self.dir);
+ if (k < 1) { self.raf = requestAnimationFrame(frame); return; }
+
+ // Landed. Commit the index and re-layout to the clean resting state.
+ self.active.classList.remove('pf-turning');
+ if (complete) self.index += self.dir;
+ self.animating = false;
+ self._layout();
+ if (complete && self.o.onFlip) self.o.onFlip(self.index);
+ }
+ this.raf = requestAnimationFrame(frame);
+ };
+
+ // Programmatic paging animates via the same settle path for a consistent feel.
+ PageFlip.prototype._go = function (dir) {
+ if (this.animating || this.dragging) return false;
+ if (dir === 1 && this.index >= this.pages.length - 1) return false;
+ if (dir === -1 && this.index <= 0) return false;
+ this.dir = dir;
+ this.width = this.root.clientWidth;
+ this.progress = 0;
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1);
+ this.active.classList.add('pf-turning');
+ this._settle(true);
+ return true;
+ };
+
+ PageFlip.prototype.next = function () { return this._go(1); };
+ PageFlip.prototype.prev = function () { return this._go(-1); };
+ PageFlip.prototype.goTo = function (i) {
+ i = clamp(i | 0, 0, this.pages.length - 1);
+ if (this.animating || this.dragging) return;
+ this.index = i; this._layout();
+ if (this.o.onFlip) this.o.onFlip(this.index);
+ };
+ PageFlip.prototype.count = function () { return this.pages.length; };
+ PageFlip.prototype.current = function () { return this.index; };
+
+ PageFlip.prototype.destroy = function () {
+ cancelAnimationFrame(this.raf);
+ this.root.removeEventListener('pointerdown', this._onDown);
+ this.root.removeEventListener('keydown', this._onKey);
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+ window.removeEventListener('resize', this._onResize);
+ delete this.root.__pageflip;
+ };
+
+ // Auto-init any [data-pageflip] on DOM ready so the drop-in "just works".
+ function auto() {
+ var els = document.querySelectorAll('[data-pageflip]');
+ Array.prototype.forEach.call(els, function (el) {
+ if (!el.__pageflip) new PageFlip(el);
+ });
+ }
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', auto);
+ } else {
+ auto();
+ }
+
+ global.PageFlip = PageFlip;
+ if (typeof module !== 'undefined' && module.exports) module.exports = PageFlip;
+})(typeof window !== 'undefined' ? window : this);
+</script>
+<script>
+(function(){
+ var root=document.querySelector('.dw-gbook'); if(!root) return;
+ var el=root.querySelector('[data-pageflip]');
+ var audio=root.querySelector('[data-gb=audio]');
+ var playBtn=root.querySelector('[data-gb=play]');
+ var countEl=root.querySelector('[data-gb=count]');
+ var COVER=2.20, INTERVAL=2.113, DUR=124.2, TOTAL=56;
+ // page-flip auto-inits on DOMContentLoaded; init now if not yet (PageFlip is idempotent).
+ var book=el.__pageflip||new PageFlip(el); if(!book){ return; }
+ var auto=false, raf=0, startT=0;
+ function count(){ countEl.textContent=(book.current()+1)+' / '+TOTAL; }
+ book.o.onFlip=count; count();
+ // manual paging (buttons stop auto-play, then turn — animated)
+ root.querySelector('[data-gb=prev]').addEventListener('click',function(){ stop(); book.prev(); });
+ root.querySelector('[data-gb=next]').addEventListener('click',function(){ stop(); book.next(); });
+ // grabbing a page mid-play cancels auto-play (you took the wheel)
+ el.addEventListener('pointerdown',function(){ if(auto) stop(); },true);
+
+ // Clock: prefer the narration's own currentTime (so pages track the VO), but fall
+ // back to a wall-clock timer so PLAY still flips the pages even if audio is blocked.
+ function elapsed(){
+ if(audio && !audio.paused && audio.currentTime>0.05) return audio.currentTime;
+ return (performance.now()-startT)/1000;
+ }
+ function tick(){
+ if(!auto) return;
+ var t=elapsed();
+ var target=t<COVER?0:Math.min(TOTAL-1,1+Math.floor((t-COVER)/INTERVAL));
+ // advance with the ANIMATED page-turn (next/prev), one step per frame as needed
+ if(target>book.current()) book.next();
+ else if(target<book.current()) book.prev();
+ if((audio&&audio.ended) || (t>=DUR && book.current()>=TOTAL-1)){ stop(); return; }
+ raf=requestAnimationFrame(tick);
+ }
+ function play(){
+ auto=true; playBtn.classList.add('is-playing'); playBtn.textContent='⏸ Pause';
+ if(book.current()>=TOTAL-1) book.goTo(0);
+ startT=performance.now();
+ if(audio){ try{ audio.currentTime=0; }catch(e){}
+ audio.play().then(function(){ startT=performance.now()-audio.currentTime*1000; })
+ .catch(function(){ /* audio blocked — pages still flip on the timer */ }); }
+ cancelAnimationFrame(raf); raf=requestAnimationFrame(tick);
+ }
+ function stop(){
+ auto=false; playBtn.classList.remove('is-playing'); playBtn.textContent='▶ Play narrated';
+ if(audio) audio.pause(); cancelAnimationFrame(raf);
+ }
+ playBtn.addEventListener('click',function(){ auto?stop():play(); });
+ if(audio) audio.addEventListener('ended',stop);
+})();
+</script>
+<!-- ==== /Graduate interactive flip book ==== -->
\ No newline at end of file
diff --git a/public/collections/graduate-flipbook/page-flip.css b/public/collections/graduate-flipbook/page-flip.css
new file mode 100644
index 0000000..cc3b1b1
--- /dev/null
+++ b/public/collections/graduate-flipbook/page-flip.css
@@ -0,0 +1,141 @@
+/*!
+ * page-flip.css — visual layer for page-flip.js.
+ *
+ * The JS drives WHEN things move; this file makes them look like paper. The
+ * shadow work Meng To flagged lives here in three cooperating layers:
+ * 1. .pf-curl — per-leaf ambient-occlusion gradient (opacity driven by JS)
+ * 2. .pf-gutter — the fixed spine shadow down the binding edge
+ * 3. .pf-face — subtle paper grain + a page-edge highlight
+ *
+ * Tunable via CSS custom properties (all overridable per instance):
+ * --pf-persp 3D perspective depth (set by JS from opts.perspective)
+ * --pf-gutter spine-shadow peak opacity (set by JS from opts.gutterShadow)
+ * --pf-paper page background
+ * --pf-ink page text color
+ * --pf-radius corner radius of the book
+ */
+
+.pageflip {
+ --pf-paper: #fbf9f4; /* warm sketchbook stock */
+ --pf-paper-2: #f3efe6; /* backside, slightly darker */
+ --pf-ink: #2a2622;
+ --pf-radius: 10px;
+ --pf-edge: rgba(0, 0, 0, 0.10); /* page-edge line */
+ position: relative;
+ width: 100%;
+ aspect-ratio: 3 / 4; /* portrait sketchbook; override as needed */
+ margin: 0 auto;
+ perspective: var(--pf-persp, 2200px);
+ perspective-origin: 0% 50%; /* eye toward the spine so the turn arcs correctly */
+ touch-action: pan-y; /* let vertical scroll through; we own horizontal */
+ user-select: none;
+ -webkit-user-select: none;
+ outline: none;
+}
+.pageflip.pf-grabbing { cursor: grabbing; }
+.pageflip:not(.pf-grabbing) { cursor: grab; }
+
+/* Each leaf pivots on its spine edge (left). */
+.pf-page {
+ position: absolute;
+ inset: 0;
+ transform-origin: left center;
+ transform-style: preserve-3d;
+ will-change: transform;
+ border-radius: 0 var(--pf-radius) var(--pf-radius) 0;
+ /* No CSS transition — the JS rAF loop owns every frame so the shadow and the
+ transform stay locked together. A CSS transition here would desync them. */
+}
+
+/* Front + back faces. backface-visibility hides whichever side faces away, so
+ the two faces never bleed through each other mid-turn. */
+.pf-face {
+ position: absolute;
+ inset: 0;
+ backface-visibility: hidden;
+ -webkit-backface-visibility: hidden;
+ border-radius: inherit;
+ overflow: hidden;
+ box-sizing: border-box;
+ padding: clamp(16px, 5%, 40px);
+ color: var(--pf-ink);
+ background: var(--pf-paper);
+ /* faint paper grain + a bright page-edge highlight on the free (right) edge */
+ background-image:
+ linear-gradient(90deg, rgba(0,0,0,0.05) 0, rgba(0,0,0,0) 3%), /* spine-side shading */
+ linear-gradient(270deg, rgba(255,255,255,0.6) 0, rgba(255,255,255,0) 2%);/* free-edge highlight */
+ box-shadow: inset 0 0 0 1px var(--pf-edge);
+}
+.pf-front { transform: rotateY(0deg); }
+.pf-back {
+ transform: rotateY(180deg);
+ background: var(--pf-paper-2);
+ /* the back of a sheet: mirror the shading (highlight now on the left) */
+ background-image:
+ linear-gradient(270deg, rgba(0,0,0,0.06) 0, rgba(0,0,0,0) 4%),
+ linear-gradient(90deg, rgba(255,255,255,0.4) 0, rgba(255,255,255,0) 3%);
+}
+
+/*
+ * THE CURL SHADOW — the layer that sells the turn.
+ * Its opacity is set every frame by JS (peaks as the page stands perpendicular).
+ * --pf-curl-dir flips the gradient once we pass 90° so the darkness always
+ * gathers where the sheet is bending away from the light, not on the flat face.
+ */
+.pf-curl {
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ border-radius: inherit;
+ opacity: 0;
+ /* dir 0 (front showing): dark gathers toward the free/right edge */
+ background: linear-gradient(
+ 100deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+/* dir 1 (back showing, past 90°): mirror so dark gathers toward the spine/left */
+.pf-curl[style*="--pf-curl-dir: 1"] {
+ background: linear-gradient(
+ 260deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+
+/* The turning leaf gets a real drop shadow so it lifts off the stack. */
+.pf-page.pf-turning {
+ box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
+}
+
+/*
+ * THE GUTTER / SPINE SHADOW — fixed, always on, so the book reads as bound.
+ * A soft dark band hugging the binding edge (left). Peak opacity from --pf-gutter.
+ */
+.pf-gutter {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 12%;
+ pointer-events: none;
+ z-index: 9999;
+ border-radius: var(--pf-radius) 0 0 var(--pf-radius);
+ background: linear-gradient(
+ 90deg,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 1)) 0,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 0.35)) 40%,
+ rgba(0, 0, 0, 0) 100%
+ );
+ mix-blend-mode: multiply;
+}
+
+/* Respect users who ask for less motion: snap instantly (JS still works, the
+ rAF just completes in one frame's worth of visual change to them via CSS is
+ n/a — but we drop the lift shadow that draws the eye). */
+@media (prefers-reduced-motion: reduce) {
+ .pf-page.pf-turning { box-shadow: none; }
+}
diff --git a/public/collections/graduate-flipbook/page-flip.js b/public/collections/graduate-flipbook/page-flip.js
new file mode 100644
index 0000000..3a92f33
--- /dev/null
+++ b/public/collections/graduate-flipbook/page-flip.js
@@ -0,0 +1,312 @@
+/*!
+ * page-flip.js — a zero-dependency drag-to-paginate book / sketchbook UI.
+ *
+ * Seeded by Meng To (@MengTo)'s 2026-08-06 "page-flipping sketchbook" post:
+ * "AI gives you the basics unless you hand it a solid open-source to work
+ * from. So I asked for drag to paginate, which took many fixes for shadows."
+ * This file IS that solid open-source to work from. The hard parts it gets
+ * right — the ones "the basics" skip — are called out inline: the curl
+ * ambient-occlusion shadow, the gutter/spine shadow, velocity-flick release,
+ * and keeping the shadow synced to the page THROUGH the snap animation.
+ *
+ * Contract (see demo.html):
+ * <div class="pageflip" data-pageflip>
+ * <div class="pf-page">…page 1…</div>
+ * <div class="pf-page">…page 2…</div>
+ * …
+ * </div>
+ * Each direct .pf-page child becomes one leaf. Author content lives on the
+ * front; the back is an auto-generated paper backside.
+ *
+ * Usage:
+ * const book = new PageFlip(el, { onFlip(i){…} }); // or auto-init below
+ * book.next(); book.prev(); book.goTo(3);
+ *
+ * No build step, no framework, no license friction — vanilla ES2019.
+ */
+(function (global) {
+ 'use strict';
+
+ var DEFAULTS = {
+ dragZone: 0.5, // fraction of page width (from the outer edge) that starts a drag
+ flipThreshold: 0.5, // release past this fraction of the turn (0..1) completes the flip
+ flickVelocity: 0.6, // px/ms; a faster release completes the flip regardless of threshold
+ snapMs: 420, // snap animation duration
+ curlShadow: 0.42, // peak opacity of the curl ambient-occlusion shadow (0..1)
+ gutterShadow: 0.28, // peak opacity of the fixed spine/gutter shadow (0..1)
+ perspective: 2200, // px; larger = flatter/less dramatic depth
+ onFlip: null, // (index) => void, fired after a completed flip settles
+ onTurn: null // (progress, dir) => void, fired continuously while turning (progress 0..1)
+ };
+
+ // power-in-out easing keeps the snap feeling weighted, not linear/robotic.
+ function easeInOut(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }
+ function clamp(v, lo, hi) { return v < lo ? lo : v > hi ? hi : v; }
+
+ function PageFlip(root, opts) {
+ if (!root) throw new Error('PageFlip: root element required');
+ if (root.__pageflip) return root.__pageflip; // idempotent
+ this.root = root;
+ this.o = Object.assign({}, DEFAULTS, opts || {});
+ this.pages = [];
+ this.index = 0; // top face-up leaf
+ this.dragging = false;
+ this.raf = 0;
+ root.__pageflip = this;
+ this._build();
+ this._bind();
+ this._layout();
+ }
+
+ PageFlip.prototype._build = function () {
+ var root = this.root;
+ root.classList.add('pageflip');
+ root.style.setProperty('--pf-persp', this.o.perspective + 'px');
+
+ // Promote each .pf-page child into a two-faced leaf with a curl-shadow layer.
+ var kids = Array.prototype.filter.call(root.children, function (c) {
+ return c.classList && c.classList.contains('pf-page');
+ });
+ var self = this;
+ kids.forEach(function (leaf, i) {
+ // Move author content into a front face (once — re-init safe).
+ if (!leaf.querySelector(':scope > .pf-front')) {
+ var front = document.createElement('div');
+ front.className = 'pf-face pf-front';
+ while (leaf.firstChild) front.appendChild(leaf.firstChild);
+ leaf.appendChild(front);
+
+ var back = document.createElement('div');
+ back.className = 'pf-face pf-back';
+ back.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(back);
+
+ // Curl shadow: a gradient overlay whose opacity we drive from the turn
+ // angle. This is the "many fixes for shadows" layer — see physics.md.
+ var curl = document.createElement('div');
+ curl.className = 'pf-curl';
+ curl.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(curl);
+ }
+ leaf.dataset.pfIndex = String(i);
+ leaf.setAttribute('role', 'group');
+ leaf.setAttribute('aria-roledescription', 'page');
+ self.pages.push(leaf);
+ });
+
+ // Fixed gutter/spine shadow — always present at the binding edge so the
+ // book reads as bound even when no page is turning.
+ if (!root.querySelector(':scope > .pf-gutter')) {
+ var gutter = document.createElement('div');
+ gutter.className = 'pf-gutter';
+ gutter.setAttribute('aria-hidden', 'true');
+ root.appendChild(gutter);
+ root.style.setProperty('--pf-gutter', this.o.gutterShadow);
+ }
+ };
+
+ PageFlip.prototype._layout = function () {
+ // Resting state: leaves before `index` are turned (-180°) and stack on the
+ // left ascending; leaves at/after `index` are flat and stack on the right
+ // with `index` on top.
+ var n = this.pages.length;
+ for (var i = 0; i < n; i++) {
+ var leaf = this.pages[i];
+ if (i < this.index) {
+ this._setLeaf(leaf, -180, 0);
+ leaf.style.zIndex = String(i); // earlier turned pages sink lower
+ leaf.classList.add('pf-turned');
+ } else {
+ this._setLeaf(leaf, 0, 0);
+ leaf.style.zIndex = String(n - i); // current on top, rest descend
+ leaf.classList.remove('pf-turned');
+ }
+ leaf.setAttribute('aria-hidden', i === this.index || i === this.index + 1 ? 'false' : 'true');
+ }
+ this.root.dataset.pfIndex = String(this.index);
+ };
+
+ // Apply a rotation + its matching shadow to one leaf. angleDeg in [-180, 0].
+ PageFlip.prototype._setLeaf = function (leaf, angleDeg, forceShadow) {
+ leaf.style.transform = 'rotateY(' + angleDeg + 'deg)';
+ var curl = leaf.querySelector(':scope > .pf-curl');
+ if (!curl) return;
+ // sin() peaks at 90° (page standing up) and vanishes flat at 0°/180° — the
+ // physically-right shape for ambient occlusion of a curling sheet.
+ var a = Math.abs(angleDeg);
+ var s = (forceShadow != null ? forceShadow : Math.sin(a * Math.PI / 180)) * this.o.curlShadow;
+ curl.style.opacity = String(s);
+ // Past 90° we're looking at the back of the sheet: flip the gradient so the
+ // shading gathers toward the (now leading) spine edge, not the free edge.
+ curl.style.setProperty('--pf-curl-dir', a > 90 ? '1' : '0');
+ };
+
+ PageFlip.prototype._bind = function () {
+ var self = this;
+ this._onDown = function (e) { self._down(e); };
+ this._onMove = function (e) { self._move(e); };
+ this._onUp = function (e) { self._up(e); };
+ this.root.addEventListener('pointerdown', this._onDown);
+ // Keyboard paging for accessibility. Only set tabIndex when the element
+ // has no explicit tabindex attribute; avoids overwriting intentional -1.
+ if (!this.root.hasAttribute('tabindex')) this.root.tabIndex = 0;
+ // Stored (not anonymous) so destroy() can remove it — otherwise re-init on
+ // the same element stacks keydown listeners.
+ this._onKey = function (e) {
+ if (e.key === 'ArrowRight' || e.key === 'PageDown') { self.next(); e.preventDefault(); }
+ else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { self.prev(); e.preventDefault(); }
+ };
+ this.root.addEventListener('keydown', this._onKey);
+ this._onResize = function () { self.width = self.root.clientWidth; };
+ window.addEventListener('resize', this._onResize);
+ this.width = this.root.clientWidth;
+ };
+
+ PageFlip.prototype._down = function (e) {
+ if (this.animating) return;
+ var rect = this.root.getBoundingClientRect();
+ var x = (e.clientX - rect.left) / rect.width; // 0 (spine/left) .. 1 (outer/right)
+ var dir;
+ // Right dragZone turns forward (needs a next page); left turns back.
+ if (x >= 1 - this.o.dragZone && this.index < this.pages.length - 1) dir = 1;
+ else if (x <= this.o.dragZone && this.index > 0) dir = -1;
+ else return;
+
+ this.dragging = true;
+ this.dir = dir;
+ this.startX = e.clientX;
+ this.width = rect.width;
+ this.lastX = e.clientX;
+ this.lastT = e.timeStamp;
+ this.vel = 0;
+
+ // The leaf that visually turns: the current leaf when going forward, the
+ // previous (already-turned) leaf when going back.
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1); // ride on top while turning
+ this.active.classList.add('pf-turning');
+ this.root.classList.add('pf-grabbing');
+
+ try { this.root.setPointerCapture(e.pointerId); } catch (_) {}
+ window.addEventListener('pointermove', this._onMove);
+ window.addEventListener('pointerup', this._onUp);
+ window.addEventListener('pointercancel', this._onUp);
+ e.preventDefault();
+ };
+
+ PageFlip.prototype._move = function (e) {
+ if (!this.dragging) return;
+ var dt = e.timeStamp - this.lastT;
+ if (dt > 0) this.vel = (e.clientX - this.lastX) / dt; // px/ms, signed
+ this.lastX = e.clientX; this.lastT = e.timeStamp;
+
+ var dx = e.clientX - this.startX;
+ // progress 0 (flat/resting) .. 1 (fully turned) for this drag direction.
+ var progress = this.dir === 1
+ ? clamp(-dx / this.width, 0, 1) // forward: drag left (dx<0)
+ : clamp(dx / this.width, 0, 1); // back: drag right (dx>0)
+ // Forward turns the current leaf 0 -> -180; back turns the prev leaf -180 -> 0.
+ var angle = this.dir === 1 ? -progress * 180 : -180 + progress * 180;
+ this._setLeaf(this.active, angle);
+ this.progress = progress;
+ if (this.o.onTurn) this.o.onTurn(progress, this.dir);
+ };
+
+ PageFlip.prototype._up = function () {
+ if (!this.dragging) return;
+ this.dragging = false;
+ this.root.classList.remove('pf-grabbing');
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+
+ // A quick flick completes the flip even if you didn't cross the threshold —
+ // velocity sign must agree with the turn direction (drag left = negative).
+ var flick = (this.dir === 1 && this.vel < -this.o.flickVelocity) ||
+ (this.dir === -1 && this.vel > this.o.flickVelocity);
+ var complete = this.progress >= this.o.flipThreshold || flick;
+ this._settle(complete);
+ };
+
+ // Animate the active leaf to its resting angle, driving the shadow the whole
+ // way so it never "pops" at the seam between drag and snap.
+ PageFlip.prototype._settle = function (complete) {
+ var self = this;
+ this.animating = true;
+ var fromProg = this.progress || 0;
+ var toProg = complete ? 1 : 0;
+ var t0 = null;
+ cancelAnimationFrame(this.raf);
+
+ function frame(t) {
+ if (t0 == null) t0 = t;
+ var k = clamp((t - t0) / self.o.snapMs, 0, 1);
+ var p = fromProg + (toProg - fromProg) * easeInOut(k);
+ var angle = self.dir === 1 ? -p * 180 : -180 + p * 180;
+ self._setLeaf(self.active, angle);
+ if (self.o.onTurn) self.o.onTurn(p, self.dir);
+ if (k < 1) { self.raf = requestAnimationFrame(frame); return; }
+
+ // Landed. Commit the index and re-layout to the clean resting state.
+ self.active.classList.remove('pf-turning');
+ if (complete) self.index += self.dir;
+ self.animating = false;
+ self._layout();
+ if (complete && self.o.onFlip) self.o.onFlip(self.index);
+ }
+ this.raf = requestAnimationFrame(frame);
+ };
+
+ // Programmatic paging animates via the same settle path for a consistent feel.
+ PageFlip.prototype._go = function (dir) {
+ if (this.animating || this.dragging) return false;
+ if (dir === 1 && this.index >= this.pages.length - 1) return false;
+ if (dir === -1 && this.index <= 0) return false;
+ this.dir = dir;
+ this.width = this.root.clientWidth;
+ this.progress = 0;
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1);
+ this.active.classList.add('pf-turning');
+ this._settle(true);
+ return true;
+ };
+
+ PageFlip.prototype.next = function () { return this._go(1); };
+ PageFlip.prototype.prev = function () { return this._go(-1); };
+ PageFlip.prototype.goTo = function (i) {
+ i = clamp(i | 0, 0, this.pages.length - 1);
+ if (this.animating || this.dragging) return;
+ this.index = i; this._layout();
+ if (this.o.onFlip) this.o.onFlip(this.index);
+ };
+ PageFlip.prototype.count = function () { return this.pages.length; };
+ PageFlip.prototype.current = function () { return this.index; };
+
+ PageFlip.prototype.destroy = function () {
+ cancelAnimationFrame(this.raf);
+ this.root.removeEventListener('pointerdown', this._onDown);
+ this.root.removeEventListener('keydown', this._onKey);
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+ window.removeEventListener('resize', this._onResize);
+ delete this.root.__pageflip;
+ };
+
+ // Auto-init any [data-pageflip] on DOM ready so the drop-in "just works".
+ function auto() {
+ var els = document.querySelectorAll('[data-pageflip]');
+ Array.prototype.forEach.call(els, function (el) {
+ if (!el.__pageflip) new PageFlip(el);
+ });
+ }
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', auto);
+ } else {
+ auto();
+ }
+
+ global.PageFlip = PageFlip;
+ if (typeof module !== 'undefined' && module.exports) module.exports = PageFlip;
+})(typeof window !== 'undefined' ? window : this);
diff --git a/scripts/build-graduate-interactive.mjs b/scripts/build-graduate-interactive.mjs
new file mode 100644
index 0000000..d55a638
--- /dev/null
+++ b/scripts/build-graduate-interactive.mjs
@@ -0,0 +1,205 @@
+#!/usr/bin/env node
+/**
+ * build-graduate-interactive.mjs — emit the "unified auto-play flip book" module for
+ * the Graduate Collection: a draggable page-flip book (page-flip-ui) the visitor turns
+ * themselves, PLUS a ▶ Play that auto-advances the pages to the narration extracted
+ * from the existing 124.2s flip-book video. Grabbing a page pauses auto-play.
+ *
+ * Output: public/collections/graduate-flipbook/index.html (standalone local preview)
+ * + prints the embeddable <section> so it can be dropped into the marketing.dw page
+ * and the Shopify dw-collection-hero.liquid.
+ *
+ * Images come straight from cdn.shopify.com URLs in data/graduate-combined.json, so the
+ * SAME module works on marketing.dw and Shopify with zero image hosting. Only the two
+ * local assets (page-flip.js/css) + the narration .m4a live under /collections/graduate-flipbook/.
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const PROJ = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
+const OUTDIR = path.join(PROJ, 'public', 'collections', 'graduate-flipbook');
+// asset base: local preview serves from same dir; on prod both surfaces reach it at this absolute URL
+const BASE = process.argv.includes('--prod')
+ ? 'https://marketing.designerwallcoverings.com/public/collections/graduate-flipbook'
+ : '.';
+
+const products = JSON.parse(fs.readFileSync(path.join(PROJ, 'data', 'graduate-combined.json'), 'utf8'))
+ .filter(p => p.image);
+const N = products.length;
+
+// Self-contained mode: inline the flip engine + css, and serve narration from the
+// public /reels/*.mp4 route (the /public/collections/<slug>/ subdir is routed to a
+// different app by nginx, so external asset URLs there 401). No external deps except
+// the narration mp4 (public) + cdn.shopify.com images.
+const CSS_INLINE = fs.readFileSync(path.join(OUTDIR, 'page-flip.css'), 'utf8');
+const JS_INLINE = fs.readFileSync(path.join(OUTDIR, 'page-flip.js'), 'utf8');
+const AUDIO_SRC = process.argv.includes('--prod')
+ ? 'https://marketing.designerwallcoverings.com/reels/graduate-narration.mp4'
+ : './graduate-narration.m4a';
+
+// video timing (from the render): a ~2s cover hold, then pages riffle, ~6s of hold+outro tail.
+const DUR = 124.2, COVER = 2.2, TAIL = 5.8;
+const INTERVAL = (DUR - COVER - TAIL) / N; // seconds per page during auto-play
+
+const esc = s => String(s || '').replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]));
+
+// each leaf = one spread page: left verso (room-setting + name), right recto (pattern swatch)
+const leaves = products.map((p, i) => `
+ <div class="pf-page" role="group" aria-label="${esc(p.title)}">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ ${p.room ? `<img class="gb-room" src="${esc(p.room)}" alt="${esc(p.title)} in a room setting" loading="lazy">`
+ : `<div class="gb-room gb-room--none"></div>`}
+ <div class="gb-meta">
+ ${p.chapter ? `<span class="gb-chapter">${esc(p.chapter)}</span>` : ''}
+ <span class="gb-name">${esc(p.title)}</span>
+ <span class="gb-pageno">${i + 1} / ${N}</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="${esc(p.image)}" alt="${esc(p.title)} pattern" loading="lazy">
+ </div>
+ </div>
+ </div>`).join('');
+
+const cover = `
+ <div class="pf-page gb-cover" role="group" aria-label="Cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__brand">Designer Wallcoverings</span>
+ <span class="gb-cover__title">The Graduate Collection</span>
+ <span class="gb-cover__sub">Flip through it — or press play for the narrated tour</span>
+ </div>
+ </div>`;
+
+// The reusable module (markup + scoped CSS + JS). Absolute asset URLs via BASE.
+const MODULE = `<!-- ==== Graduate interactive flip book (unified auto-play) ==== -->
+<style>${CSS_INLINE}</style>
+<section class="dw-gbook" aria-label="The Graduate Collection flip book">
+ <div class="dw-gbook__bar">
+ <span class="dw-gbook__label">The Flip Book · interactive</span>
+ <div class="dw-gbook__ctl">
+ <button type="button" class="gb-btn" data-gb="prev" aria-label="Previous page">‹</button>
+ <span class="gb-count" data-gb="count">1 / ${N + 1}</span>
+ <button type="button" class="gb-btn" data-gb="next" aria-label="Next page">›</button>
+ <button type="button" class="gb-btn gb-btn--play" data-gb="play" aria-label="Play narrated tour">▶ Play narrated</button>
+ </div>
+ </div>
+ <div class="pageflip dw-gbook__book" data-pageflip>
+ ${cover}${leaves}
+ <div class="pf-page gb-cover gb-cover--back" role="group" aria-label="Back cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__title">Shop the Graduate Collection</span>
+ <a class="gb-cover__cta" href="https://www.designerwallcoverings.com/collections/the-graduate-collection">Browse all ${N} patterns →</a>
+ </div>
+ </div>
+ </div>
+ <audio class="dw-gbook__audio" data-gb="audio" preload="none" src="${AUDIO_SRC}"></audio>
+</section>
+<style>
+ .dw-gbook{max-width:1100px;margin:0 auto 1.75rem;padding:0 1rem;font-family:'Cormorant Garamond',Georgia,serif;}
+ .dw-gbook__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:0 0 .6rem;flex-wrap:wrap;}
+ .dw-gbook__label{font-size:.95rem;letter-spacing:.12em;text-transform:uppercase;color:#8a7f72;}
+ .dw-gbook__ctl{display:flex;align-items:center;gap:.4rem;}
+ .gb-btn{border:1px solid #cbb8a3;background:#fff;color:#3a3128;border-radius:999px;padding:.35rem .8rem;font:inherit;font-size:.9rem;cursor:pointer;line-height:1;transition:background .15s,color .15s;}
+ .gb-btn:hover{background:#f3ece2;}
+ .gb-btn--play{background:#14110e;color:#f4ede2;border-color:#14110e;}
+ .gb-btn--play:hover{background:#2a2118;}
+ .gb-btn--play.is-playing{background:#8a1f2b;border-color:#8a1f2b;}
+ .gb-count{min-width:4.5em;text-align:center;color:#6b6055;font-size:.9rem;}
+ .dw-gbook__book{aspect-ratio:16/9;background:#14110e;border-radius:10px;box-shadow:0 14px 48px rgba(0,0,0,.22);}
+ /* spread: verso (room + name) | recto (pattern) */
+ .gb-spread{position:absolute;inset:0;display:grid;grid-template-columns:1fr 1fr;background:#fbf7f1;}
+ .gb-verso{position:relative;overflow:hidden;background:#efe7db;}
+ .gb-room{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-room--none{background:linear-gradient(135deg,#e7ddce,#d8ccba);}
+ .gb-meta{position:absolute;left:0;right:0;bottom:0;padding:1rem 1.1rem;display:flex;flex-direction:column;gap:.15rem;background:linear-gradient(0deg,rgba(20,17,14,.72),rgba(20,17,14,0));color:#fdf8f0;}
+ .gb-chapter{font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;opacity:.85;}
+ .gb-name{font-size:1.45rem;line-height:1.1;}
+ .gb-pageno{font-size:.72rem;opacity:.7;letter-spacing:.1em;}
+ .gb-recto{position:relative;overflow:hidden;background:#fff;}
+ .gb-swatch{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-cover__inner{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:.5rem;background:radial-gradient(120% 120% at 50% 20%,#241d15,#14110e);color:#f4ede2;padding:2rem;}
+ .gb-cover__brand{font-size:.8rem;letter-spacing:.28em;text-transform:uppercase;color:#c9a86a;}
+ .gb-cover__title{font-size:2.1rem;line-height:1.05;}
+ .gb-cover__sub{font-size:1rem;color:#b6a894;}
+ .gb-cover__cta{margin-top:.4rem;color:#14110e;background:#c9a86a;border-radius:999px;padding:.5rem 1.1rem;text-decoration:none;font-size:.95rem;}
+ @media(max-width:640px){.gb-name{font-size:1.15rem}.gb-cover__title{font-size:1.5rem}.dw-gbook__book{aspect-ratio:4/3}}
+ @media(prefers-reduced-motion:reduce){.dw-gbook__book{scroll-behavior:auto}}
+</style>
+<script>${JS_INLINE}</script>
+<script>
+(function(){
+ var root=document.querySelector('.dw-gbook'); if(!root) return;
+ var el=root.querySelector('[data-pageflip]');
+ var audio=root.querySelector('[data-gb=audio]');
+ var playBtn=root.querySelector('[data-gb=play]');
+ var countEl=root.querySelector('[data-gb=count]');
+ var COVER=${COVER.toFixed(2)}, INTERVAL=${INTERVAL.toFixed(3)}, DUR=${DUR.toFixed(1)}, TOTAL=${N + 1};
+ // page-flip auto-inits on DOMContentLoaded; init now if not yet (PageFlip is idempotent).
+ var book=el.__pageflip||new PageFlip(el); if(!book){ return; }
+ var auto=false, raf=0, startT=0;
+ function count(){ countEl.textContent=(book.current()+1)+' / '+TOTAL; }
+ book.o.onFlip=count; count();
+ // manual paging (buttons stop auto-play, then turn — animated)
+ root.querySelector('[data-gb=prev]').addEventListener('click',function(){ stop(); book.prev(); });
+ root.querySelector('[data-gb=next]').addEventListener('click',function(){ stop(); book.next(); });
+ // grabbing a page mid-play cancels auto-play (you took the wheel)
+ el.addEventListener('pointerdown',function(){ if(auto) stop(); },true);
+
+ // Clock: prefer the narration's own currentTime (so pages track the VO), but fall
+ // back to a wall-clock timer so PLAY still flips the pages even if audio is blocked.
+ function elapsed(){
+ if(audio && !audio.paused && audio.currentTime>0.05) return audio.currentTime;
+ return (performance.now()-startT)/1000;
+ }
+ function tick(){
+ if(!auto) return;
+ var t=elapsed();
+ var target=t<COVER?0:Math.min(TOTAL-1,1+Math.floor((t-COVER)/INTERVAL));
+ // advance with the ANIMATED page-turn (next/prev), one step per frame as needed
+ if(target>book.current()) book.next();
+ else if(target<book.current()) book.prev();
+ if((audio&&audio.ended) || (t>=DUR && book.current()>=TOTAL-1)){ stop(); return; }
+ raf=requestAnimationFrame(tick);
+ }
+ function play(){
+ auto=true; playBtn.classList.add('is-playing'); playBtn.textContent='⏸ Pause';
+ if(book.current()>=TOTAL-1) book.goTo(0);
+ startT=performance.now();
+ if(audio){ try{ audio.currentTime=0; }catch(e){}
+ audio.play().then(function(){ startT=performance.now()-audio.currentTime*1000; })
+ .catch(function(){ /* audio blocked — pages still flip on the timer */ }); }
+ cancelAnimationFrame(raf); raf=requestAnimationFrame(tick);
+ }
+ function stop(){
+ auto=false; playBtn.classList.remove('is-playing'); playBtn.textContent='▶ Play narrated';
+ if(audio) audio.pause(); cancelAnimationFrame(raf);
+ }
+ playBtn.addEventListener('click',function(){ auto?stop():play(); });
+ if(audio) audio.addEventListener('ended',stop);
+})();
+</script>
+<!-- ==== /Graduate interactive flip book ==== -->`;
+
+// standalone local preview page
+const PREVIEW = `<!doctype html><html lang="en"><head><meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Graduate Collection — Interactive Flip Book (preview)</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&display=swap" rel="stylesheet">
+<style>body{margin:0;background:#f6f1ea;color:#2a241d}
+ .hero{height:34vh;min-height:220px;background:#14110e url('https://marketing.designerwallcoverings.com/public/collections/graduate-banner.jpg') center/cover;display:flex;align-items:flex-end}
+ .hero h1{margin:0;padding:1.2rem 1.4rem;color:#f4ede2;font-family:'Cormorant Garamond',serif;font-size:2rem;text-shadow:0 2px 18px rgba(0,0,0,.5)}
+ .wrap{padding:2rem 0}</style></head>
+<body>
+ <div class="hero"><h1>The Graduate Collection</h1></div>
+ <div class="wrap">${MODULE}</div>
+</body></html>`;
+
+fs.mkdirSync(OUTDIR, { recursive: true });
+fs.writeFileSync(path.join(OUTDIR, 'index.html'), PREVIEW);
+fs.writeFileSync(path.join(OUTDIR, 'module.html'), MODULE);
+console.log(`Built ${N} spread leaves → ${path.relative(PROJ, OUTDIR)}/index.html`);
+console.log(`Auto-play: cover ${COVER}s, ${INTERVAL.toFixed(2)}s/page over ${DUR}s narration.`);
+console.log(`Embeddable module → ${path.relative(PROJ, OUTDIR)}/module.html`);
diff --git a/server.js b/server.js
index f5a5095..04cbb70 100644
--- a/server.js
+++ b/server.js
@@ -139,7 +139,7 @@ async function serveFile(fp, req, res) {
// must be able to fetch them — so GET /reels/*.mp4 is the ONE unauthenticated path.
// Everything else (console, APIs, data) stays Basic-Auth gated.
// Reel MP4s + published collection-page assets (banner/poster) are public marketing media.
-const PUBLIC_MEDIA = /^\/reels\/[^/]+\.mp4$|^\/public\/collections\/[a-z0-9-]+\.(?:jpg|jpeg|png|webp)$/;
+const PUBLIC_MEDIA = /^\/reels\/[^/]+\.mp4$|^\/public\/collections\/[a-z0-9-]+\.(?:jpg|jpeg|png|webp)$|^\/public\/collections\/[a-z0-9-]+\/[a-z0-9._-]+\.(?:js|css|m4a|mp3|mp4|jpg|jpeg|png|webp)$/;
// Public legal pages + published collection landing pages must be readable without auth.
const PUBLIC_PAGES = /^\/(privacy|terms|showcase|collections\/[a-z0-9-]+)$/;
const isPublicMedia = req => (req.method === 'GET' || req.method === 'HEAD') && (PUBLIC_MEDIA.test(new URL(req.url, 'http://localhost').pathname) || PUBLIC_PAGES.test(new URL(req.url, 'http://localhost').pathname));
diff --git a/storefront/graduate-interactive/PUSH-graduate-interactive.sh b/storefront/graduate-interactive/PUSH-graduate-interactive.sh
new file mode 100755
index 0000000..0479c6c
--- /dev/null
+++ b/storefront/graduate-interactive/PUSH-graduate-interactive.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+# GATED — customer-facing LIVE Shopify theme write. Do NOT run without Steve's go.
+# Swaps the graduate collection hero's plain <video> for the interactive auto-play
+# flip book. Rollback-first: snapshots the current live section before PUT.
+set -euo pipefail
+DOMAIN="designer-laboratory-sandbox.myshopify.com"; VER="2024-10"; THEME="145121607731"
+KEY="sections/dw-collection-hero.liquid"
+NEW="$HOME/Projects/dw-marketing-reels/storefront/graduate-interactive/dw-collection-hero.NEW.liquid"
+BAK="$HOME/Projects/dw-marketing-reels/storefront/graduate-interactive/ROLLBACK-dw-collection-hero-$(date +%Y%m%d-%H%M%S).json"
+TOK="$(grep -E '^SHOPIFY_THEME_TOKEN=' "$HOME/Projects/secrets-manager/.env" | head -1 | cut -d= -f2-)"
+echo "== 1. ROLLBACK SNAPSHOT of current live section → $BAK"
+curl -s "https://$DOMAIN/admin/api/$VER/themes/$THEME/assets.json?asset%5Bkey%5D=$KEY" -H "X-Shopify-Access-Token: $TOK" > "$BAK"
+grep -q '"value"' "$BAK" && echo " saved (rollback = re-PUT this .json's value)" || { echo " ✗ no current value fetched — ABORT"; exit 1; }
+echo "== 2. PUT new section (interactive flip book)"
+NEW="$NEW" KEY="$KEY" DOMAIN="$DOMAIN" VER="$VER" THEME="$THEME" TOK="$TOK" node -e '
+const fs=require("fs"),https=require("https");
+const val=fs.readFileSync(process.env.NEW,"utf8");
+const body=JSON.stringify({asset:{key:process.env.KEY,value:val}});
+const req=https.request({method:"PUT",host:process.env.DOMAIN,path:`/admin/api/${process.env.VER}/themes/${process.env.THEME}/assets.json`,headers:{"X-Shopify-Access-Token":process.env.TOK,"Content-Type":"application/json","Content-Length":Buffer.byteLength(body)}},r=>{let s="";r.on("data",d=>s+=d);r.on("end",()=>{console.log(" HTTP",r.statusCode);console.log(" ",s.slice(0,300));process.exit(r.statusCode<300?0:1);});});
+req.on("error",e=>{console.error(e);process.exit(1)});req.write(body);req.end();
+'
+echo "== 3. VERIFY live page"
+sleep 3
+curl -s "https://www.designerwallcoverings.com/collections/the-graduate-collection" | grep -c "dw-gbook" | xargs echo " dw-gbook on live page:"
diff --git a/storefront/graduate-interactive/dw-collection-hero.NEW.liquid b/storefront/graduate-interactive/dw-collection-hero.NEW.liquid
new file mode 100644
index 0000000..75b8c57
--- /dev/null
+++ b/storefront/graduate-interactive/dw-collection-hero.NEW.liquid
@@ -0,0 +1,1557 @@
+{%- comment -%}
+ DW Collection Hero — Steve standing rule (2026-06-23): every collection page
+ must have a background "bg" hero image. Renders collection.image as a full-bleed
+ cover background with the title + breadcrumbs + description on a SEMI-OPAQUE
+ CONTRASTING PANEL (dark scrim panel) so the text stays legible over any image.
+ Collections with no image fall back to a branded gradient so the page is never
+ broken; audit-collection-hero-images.py lists which collections still need one.
+
+ Also HIDES the Boost AI Search & Filter app's own collection banner (the
+ duplicate lower banner) + any legacy theme breadcrumbs, so only this hero shows.
+
+ Toggle by removing it from templates/collection.json "order".
+{%- endcomment -%}
+{%- comment -%}
+ BANNER RESOLUTION GATE (Steve 2026-07-30, TK-10053): a full-bleed hero must
+ NEVER stretch a low-res source (e.g. a 500px sample swatch) — that is what
+ produced the blurry Hollywood Wallcoverings banner. Three render modes:
+ image -> collection.image is high-res (>= dw_min_w) : single full-bleed cover (sharp)
+ mosaic -> no high-res file "for that build" : 2x2 quadrant of product
+ images, each cell ~half page-width so a 500px source stretches
+ ~1.3x instead of ~5x (visibly sharp) and 4 swatches read as curated
+ fallback-> collection has no usable product image : branded gradient
+{%- endcomment -%}
+{%- liquid
+ assign dw_min_w = 1400
+ assign dw_hero_img = collection.image
+ unless dw_hero_img
+ assign dw_hero_img = collection.products.first.featured_image
+ endunless
+ assign dw_mode = 'fallback'
+ if dw_hero_img and dw_hero_img.width >= dw_min_w
+ assign dw_mode = 'image'
+ endif
+-%}
+{%- if dw_mode != 'image' -%}
+ {%- comment -%} gather up to 4 distinct product images for the 2x2 mosaic {%- endcomment -%}
+ {%- assign dw_tiles = '' -%}
+ {%- assign dw_seen = ',' -%}
+ {%- assign dw_ntiles = 0 -%}
+ {%- for dw_p in collection.products limit: 40 -%}
+ {%- if dw_ntiles >= 4 -%}{%- break -%}{%- endif -%}
+ {%- if dw_p.featured_image -%}
+ {%- comment -%} dedup by stable image id (not URL string — version-bumped ?v= URLs would slip through) {%- endcomment -%}
+ {%- assign dw_probe = dw_p.featured_image.id | prepend: ',' | append: ',' -%}
+ {%- unless dw_seen contains dw_probe -%}
+ {%- assign dw_seen = dw_seen | append: dw_p.featured_image.id | append: ',' -%}
+ {%- assign dw_url = dw_p.featured_image | img_url: '800x' -%}
+ {%- assign dw_tiles = dw_tiles | append: dw_url | append: '|' -%}
+ {%- assign dw_ntiles = dw_ntiles | plus: 1 -%}
+ {%- endunless -%}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if dw_ntiles >= 1 -%}{%- assign dw_mode = 'mosaic' -%}{%- endif -%}
+ {%- assign dw_tile_list = dw_tiles | split: '|' -%}
+{%- endif -%}
+<div class="dw-collection-hero dw-collection-hero--{{ dw_mode }}"
+ {% if dw_mode == 'image' %}style="background-image:url({{ dw_hero_img | img_url: '2048x' }});"{% endif %}
+ data-dw-collection-hero data-hero-mode="{{ dw_mode }}">
+ {%- if dw_mode == 'mosaic' -%}
+ <div class="dw-collection-hero__mosaic" aria-hidden="true">
+ {%- for dw_t in dw_tile_list -%}
+ <span class="dw-collection-hero__cell" style="background-image:url({{ dw_t }});"></span>
+ {%- endfor -%}
+ </div>
+ {%- endif -%}
+ <div class="dw-collection-hero__inner page-width">
+ <div class="dw-collection-hero__panel">
+ <nav class="dw-collection-hero__crumbs" aria-label="Breadcrumb">
+ <a href="/">Home</a> <span aria-hidden="true">/</span>
+ <a href="/collections">Collections</a> <span aria-hidden="true">/</span>
+ <span aria-current="page">{{ collection.title }}</span>
+ </nav>
+ <h1 class="dw-collection-hero__title">{{ collection.title }}</h1>
+ {%- assign aeo_cat = collection.metafields.custom.category | default: 'wallcovering' -%}
+ <p class="dw-collection-hero__answer">A curated {{ aeo_cat }} collection for the design trade — {{ collection.products_count }} designs, samples and trade pricing on request.</p>
+ {%- if section.settings.show_description and collection.description != blank -%}
+ <div class="dw-collection-hero__desc">{{ collection.description | strip_html | truncatewords: 32 }}</div>
+ {%- endif -%}
+ </div>
+ </div>
+</div>
+{%- if collection.handle == 'the-graduate-collection' -%}
+<!-- ==== Graduate interactive flip book (unified auto-play) ==== -->
+<style>/*!
+ * page-flip.css — visual layer for page-flip.js.
+ *
+ * The JS drives WHEN things move; this file makes them look like paper. The
+ * shadow work Meng To flagged lives here in three cooperating layers:
+ * 1. .pf-curl — per-leaf ambient-occlusion gradient (opacity driven by JS)
+ * 2. .pf-gutter — the fixed spine shadow down the binding edge
+ * 3. .pf-face — subtle paper grain + a page-edge highlight
+ *
+ * Tunable via CSS custom properties (all overridable per instance):
+ * --pf-persp 3D perspective depth (set by JS from opts.perspective)
+ * --pf-gutter spine-shadow peak opacity (set by JS from opts.gutterShadow)
+ * --pf-paper page background
+ * --pf-ink page text color
+ * --pf-radius corner radius of the book
+ */
+
+.pageflip {
+ --pf-paper: #fbf9f4; /* warm sketchbook stock */
+ --pf-paper-2: #f3efe6; /* backside, slightly darker */
+ --pf-ink: #2a2622;
+ --pf-radius: 10px;
+ --pf-edge: rgba(0, 0, 0, 0.10); /* page-edge line */
+ position: relative;
+ width: 100%;
+ aspect-ratio: 3 / 4; /* portrait sketchbook; override as needed */
+ margin: 0 auto;
+ perspective: var(--pf-persp, 2200px);
+ perspective-origin: 0% 50%; /* eye toward the spine so the turn arcs correctly */
+ touch-action: pan-y; /* let vertical scroll through; we own horizontal */
+ user-select: none;
+ -webkit-user-select: none;
+ outline: none;
+}
+.pageflip.pf-grabbing { cursor: grabbing; }
+.pageflip:not(.pf-grabbing) { cursor: grab; }
+
+/* Each leaf pivots on its spine edge (left). */
+.pf-page {
+ position: absolute;
+ inset: 0;
+ transform-origin: left center;
+ transform-style: preserve-3d;
+ will-change: transform;
+ border-radius: 0 var(--pf-radius) var(--pf-radius) 0;
+ /* No CSS transition — the JS rAF loop owns every frame so the shadow and the
+ transform stay locked together. A CSS transition here would desync them. */
+}
+
+/* Front + back faces. backface-visibility hides whichever side faces away, so
+ the two faces never bleed through each other mid-turn. */
+.pf-face {
+ position: absolute;
+ inset: 0;
+ backface-visibility: hidden;
+ -webkit-backface-visibility: hidden;
+ border-radius: inherit;
+ overflow: hidden;
+ box-sizing: border-box;
+ padding: clamp(16px, 5%, 40px);
+ color: var(--pf-ink);
+ background: var(--pf-paper);
+ /* faint paper grain + a bright page-edge highlight on the free (right) edge */
+ background-image:
+ linear-gradient(90deg, rgba(0,0,0,0.05) 0, rgba(0,0,0,0) 3%), /* spine-side shading */
+ linear-gradient(270deg, rgba(255,255,255,0.6) 0, rgba(255,255,255,0) 2%);/* free-edge highlight */
+ box-shadow: inset 0 0 0 1px var(--pf-edge);
+}
+.pf-front { transform: rotateY(0deg); }
+.pf-back {
+ transform: rotateY(180deg);
+ background: var(--pf-paper-2);
+ /* the back of a sheet: mirror the shading (highlight now on the left) */
+ background-image:
+ linear-gradient(270deg, rgba(0,0,0,0.06) 0, rgba(0,0,0,0) 4%),
+ linear-gradient(90deg, rgba(255,255,255,0.4) 0, rgba(255,255,255,0) 3%);
+}
+
+/*
+ * THE CURL SHADOW — the layer that sells the turn.
+ * Its opacity is set every frame by JS (peaks as the page stands perpendicular).
+ * --pf-curl-dir flips the gradient once we pass 90° so the darkness always
+ * gathers where the sheet is bending away from the light, not on the flat face.
+ */
+.pf-curl {
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ border-radius: inherit;
+ opacity: 0;
+ /* dir 0 (front showing): dark gathers toward the free/right edge */
+ background: linear-gradient(
+ 100deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+/* dir 1 (back showing, past 90°): mirror so dark gathers toward the spine/left */
+.pf-curl[style*="--pf-curl-dir: 1"] {
+ background: linear-gradient(
+ 260deg,
+ rgba(0, 0, 0, 0) 30%,
+ rgba(0, 0, 0, 0.35) 78%,
+ rgba(0, 0, 0, 0.55) 100%
+ );
+}
+
+/* The turning leaf gets a real drop shadow so it lifts off the stack. */
+.pf-page.pf-turning {
+ box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
+}
+
+/*
+ * THE GUTTER / SPINE SHADOW — fixed, always on, so the book reads as bound.
+ * A soft dark band hugging the binding edge (left). Peak opacity from --pf-gutter.
+ */
+.pf-gutter {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 12%;
+ pointer-events: none;
+ z-index: 9999;
+ border-radius: var(--pf-radius) 0 0 var(--pf-radius);
+ background: linear-gradient(
+ 90deg,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 1)) 0,
+ rgba(0, 0, 0, calc(var(--pf-gutter, 0.28) * 0.35)) 40%,
+ rgba(0, 0, 0, 0) 100%
+ );
+ mix-blend-mode: multiply;
+}
+
+/* Respect users who ask for less motion: snap instantly (JS still works, the
+ rAF just completes in one frame's worth of visual change to them via CSS is
+ n/a — but we drop the lift shadow that draws the eye). */
+@media (prefers-reduced-motion: reduce) {
+ .pf-page.pf-turning { box-shadow: none; }
+}
+</style>
+<section class="dw-gbook" aria-label="The Graduate Collection flip book">
+ <div class="dw-gbook__bar">
+ <span class="dw-gbook__label">The Flip Book · interactive</span>
+ <div class="dw-gbook__ctl">
+ <button type="button" class="gb-btn" data-gb="prev" aria-label="Previous page">‹</button>
+ <span class="gb-count" data-gb="count">1 / 56</span>
+ <button type="button" class="gb-btn" data-gb="next" aria-label="Next page">›</button>
+ <button type="button" class="gb-btn gb-btn--play" data-gb="play" aria-label="Play narrated tour">▶ Play narrated</button>
+ </div>
+ </div>
+ <div class="pageflip dw-gbook__book" data-pageflip>
+
+ <div class="pf-page gb-cover" role="group" aria-label="Cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__brand">Designer Wallcoverings</span>
+ <span class="gb-cover__title">The Graduate Collection</span>
+ <span class="gb-cover__sub">Flip through it — or press play for the narrated tour</span>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoalRoom.png?v=1709835248" alt="All Over Leopard - Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Blue</span>
+ <span class="gb-pageno">1 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoal.png?v=1709835248" alt="All Over Leopard - Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AlloverLeopardCharcoalRoom_e9a4799e-903c-417e-99b9-158270cc5cfd.png?v=1750793863" alt="All Over Leopard Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard Blue</span>
+ <span class="gb-pageno">2 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.37.36PM.png?v=1750793883" alt="All Over Leopard Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.36.55PM.png?v=1750793822" alt="All Over Leopard Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard Charcoal</span>
+ <span class="gb-pageno">3 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-06-24at12.36.31PM.png?v=1750793823" alt="All Over Leopard Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Aubergine">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/A902549B-ECE0-4410-8226-32E31F07196B.jpg?v=1772164893" alt="All Over Leopard - Aubergine in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Aubergine</span>
+ <span class="gb-pageno">4 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/B48C9B51-6F0D-4973-985F-992BBF14F800.jpg?v=1772164893" alt="All Over Leopard - Aubergine pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="All Over Leopard - Brown">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/9B0CD372-BE5E-4886-9E91-0574F2BADC00.jpg?v=1772164915" alt="All Over Leopard - Brown in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">All Over Leopard - Brown</span>
+ <span class="gb-pageno">5 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB.jpg?v=1772164915" alt="All Over Leopard - Brown pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Leopard Brown">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB_f0e70547-6d49-4051-974f-a3d29f49e320.jpg?v=1775598515" alt="Leopard Brown in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">big cats</span>
+ <span class="gb-name">Leopard Brown</span>
+ <span class="gb-pageno">6 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/80F7ADF4-D400-4D78-89E2-E8024E0C12EB_f0e70547-6d49-4051-974f-a3d29f49e320.jpg?v=1775598515" alt="Leopard Brown pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian - Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at4.01.27PM.png?v=1633734145" alt="Visitorian - Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian - Taupe</span>
+ <span class="gb-pageno">7 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0001.jpg?v=1570091053" alt="Visitorian - Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Navy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0002.jpg?v=1570091053" alt="Visitorian Navy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Navy</span>
+ <span class="gb-pageno">8 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0002.jpg?v=1570091053" alt="Visitorian Navy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Mauve">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0003.jpg?v=1570091053" alt="Visitorian Mauve in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Mauve</span>
+ <span class="gb-pageno">9 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0003.jpg?v=1570091053" alt="Visitorian Mauve pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Visitorian Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at3.49.25PM.png?v=1633733413" alt="Visitorian Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Visitorian Blue</span>
+ <span class="gb-pageno">10 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_06_Image_0004.jpg?v=1570091053" alt="Visitorian Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Jolly Boy Dog & Friends">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-05-12at7.31.52AM.png?v=1747060363" alt="Jolly Boy Dog & Friends in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Jolly Boy Dog & Friends</span>
+ <span class="gb-pageno">11 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Screenshot2025-05-12at7.30.51AM.png?v=1747060405" alt="Jolly Boy Dog & Friends pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Steampunk Notice Board">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/QqjaFxcfRPyeCGYhD9G3_steampunk_notice_board_insitu_grande_7d8d9494-189c-43cb-9488-24944ce782b8.jpg?v=1612388487" alt="Steampunk Notice Board in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Steampunk Notice Board</span>
+ <span class="gb-pageno">12 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0002.jpg?v=1612388486" alt="Steampunk Notice Board pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Portarait Gallery Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portarait_Gallery_Taupe_1.jpg?v=1602006843" alt="Portarait Gallery Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Portarait Gallery Taupe</span>
+ <span class="gb-pageno">13 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portarait_Gallery_Taupe_1.jpg?v=1602006843" alt="Portarait Gallery Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dachshund Dog">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DachshundNaturalRoom_dce6601a-c864-4764-b024-8e4d2ac7b818.png?v=1750792583" alt="Dachshund Dog in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Dachshund Dog</span>
+ <span class="gb-pageno">14 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/NEWDachshund_NATURAL.jpg?v=1750792583" alt="Dachshund Dog pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Colonel Fox at the Gentleman's Club - Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Gentlemans_Club_Mustard.png?v=1730485289" alt="Colonel Fox at the Gentleman's Club - Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Colonel Fox at the Gentleman's Club - Mustard</span>
+ <span class="gb-pageno">15 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8900-DesignerWallcoverings-Los-Angeles-1_e3102e92-3911-4763-8ffd-1bb3d218d57e.jpg?v=1730485220" alt="Colonel Fox at the Gentleman's Club - Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Fashionista Tinted">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/hCdYg71Rm1VQjlktJ1lA_Charlotte_cory_fashionista_wallpaper_roomset_grande_280e48d5-09d9-46fe-becb-43b86046f011.jpg?v=1570091054" alt="Fashionista Tinted in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Fashionista Tinted</span>
+ <span class="gb-pageno">16 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0004.jpg?v=1570091053" alt="Fashionista Tinted pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Fashionista Black & White">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/wyqj6AS0QX6xhm67PvOg_Charlotte_Cory_-_Fashionista_black___white_wallpaper_grande_2c2fac20-d910-402f-bf3a-1b896e520fb8.jpg?v=1570091054" alt="Fashionista Black & White in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Fashionista Black & White</span>
+ <span class="gb-pageno">17 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0005.jpg?v=1570091053" alt="Fashionista Black & White pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Rabbit Rabbit Rabbit">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/MVPwIVSsSJ6IiSxGdW0I_rabbit_rabbit_rabbit_insitu_grande_142657d9-0884-44f7-b0a3-c284dafbae19.jpg?v=1572310841" alt="Rabbit Rabbit Rabbit in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Rabbit Rabbit Rabbit</span>
+ <span class="gb-pageno">18 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_07_Image_0003.jpg?v=1572310841" alt="Rabbit Rabbit Rabbit pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Gold & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.53.12PM.png?v=1694465625" alt="Showgirls Metallic Gold & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Gold & Black</span>
+ <span class="gb-pageno">19 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.53.19PM.png?v=1694465646" alt="Showgirls Metallic Gold & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Mustard & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at11.42.05AM.png?v=1694465398" alt="Showgirls Metallic Mustard & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Mustard & Cream</span>
+ <span class="gb-pageno">20 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.49.13PM.png?v=1694465405" alt="Showgirls Metallic Mustard & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Pink & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-87020-DesignerWallcoverings-Los-Angeles-1.png?v=1694465676" alt="Showgirls Metallic Pink & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Pink & Black</span>
+ <span class="gb-pageno">21 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicPink_Black.jpg?v=1730488614" alt="Showgirls Metallic Pink & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Portrait Gallery Navy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portrait_Gallery_Navy_2.jpg?v=1602006845" alt="Portrait Gallery Navy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Portrait Gallery Navy</span>
+ <span class="gb-pageno">22 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Portrait_Gallery_Navy_2.jpg?v=1602006845" alt="Portrait Gallery Navy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Bronze & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.33.07PM.png?v=1694464431" alt="Showgirls Metallic Bronze & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Bronze & Cream</span>
+ <span class="gb-pageno">23 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicBronze_Cream_1024x1024_3f9df313-e6aa-40c7-adac-97b90df0b067.jpg?v=1730488554" alt="Showgirls Metallic Bronze & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Pink & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.38.05PM.png?v=1694464738" alt="Showgirls Metallic Pink & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Pink & Cream</span>
+ <span class="gb-pageno">24 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.37.57PM.png?v=1694465689" alt="Showgirls Metallic Pink & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Teal & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.42.16PM.png?v=1694464957" alt="Showgirls Metallic Teal & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Teal & Black</span>
+ <span class="gb-pageno">25 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicTeal_Black.jpg?v=1730488416" alt="Showgirls Metallic Teal & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Teal & Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.45.39PM.png?v=1694465204" alt="Showgirls Metallic Teal & Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Teal & Cream</span>
+ <span class="gb-pageno">26 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicTeal_Cream_1024x1024_ba6114de-6784-4aa7-ac31-0f45ffecb3ec.jpg?v=1730488356" alt="Showgirls Metallic Teal & Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Showgirls Metallic Bronze & Black">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Showgirls_MetallicBronze_Black.jpg?v=1730488254" alt="Showgirls Metallic Bronze & Black in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Showgirls Metallic Bronze & Black</span>
+ <span class="gb-pageno">27 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2023-09-11at1.51.20PM.png?v=1694465520" alt="Showgirls Metallic Bronze & Black pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsblueroom_0264483b-3df5-48ca-a4e4-0227be6ccfeb.png?v=1730484646" alt="Cavalcade Of Cats Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Blue</span>
+ <span class="gb-pageno">28 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsblue_fa62827d-3eb7-4812-982a-5ef6150ee8f3.png?v=1730484646" alt="Cavalcade Of Cats Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsmustardroom_a24237f0-6336-4e09-9363-dd56e0bd8261.png?v=1730484639" alt="Cavalcade Of Cats Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Mustard</span>
+ <span class="gb-pageno">29 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsmustard_122455d1-6d9e-4092-bc80-3cc2cd0868b6.png?v=1730484639" alt="Cavalcade Of Cats Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Cavalcade Of Cats Red">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsredroom_24cc4ace-220e-44e5-baaa-8e5b45352ec5.png?v=1730484633" alt="Cavalcade Of Cats Red in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Cavalcade Of Cats Red</span>
+ <span class="gb-pageno">30 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ACavalcadeofCatsred_18a38a54-b823-4ac2-a1b8-87ee5d1f77ba.png?v=1730484633" alt="Cavalcade Of Cats Red pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogCreamRoom_32e3d309-1b1e-4f35-aedc-112ca25c9228.png?v=1730484609" alt="Top Dog Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog Cream</span>
+ <span class="gb-pageno">31 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogCream_252e8492-113b-46a6-ac5c-558b2a6693bd.png?v=1730484609" alt="Top Dog Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogGreyRoom_8641f7a0-a5bd-4256-ad2e-47f5595dc4e7.png?v=1730484602" alt="Top Dog Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog Grey</span>
+ <span class="gb-pageno">32 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDogGrey_d06cfc3e-a80f-49c2-b203-8e42a86b1b58.png?v=1730484602" alt="Top Dog Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Burgundy">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryBurgundyroom_cffd75f2-e080-4835-9f37-cdb52caa165e.png?v=1730484596" alt="At The Art Gallery Burgundy in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Burgundy</span>
+ <span class="gb-pageno">33 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryBurgundy_4f783d0d-251c-43a2-9519-72ee14418169.png?v=1730484596" alt="At The Art Gallery Burgundy pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryCharcoalroom_d9e4cfe7-bd89-401b-9942-8b11bf89473d.png?v=1730484591" alt="At The Art Gallery Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Charcoal</span>
+ <span class="gb-pageno">34 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryCharcoal_b0e9858f-c4ee-46b7-b6e5-6c37739a23c1.png?v=1730484591" alt="At The Art Gallery Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="At The Art Gallery Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGallerytealroom_6b1945f9-f9dd-4808-9254-81ed6963a351.png?v=1730484584" alt="At The Art Gallery Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">At The Art Gallery Teal</span>
+ <span class="gb-pageno">35 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AttheArtGalleryteal_d8dd0ab4-a676-4120-9ed7-a55f46f02724.png?v=1730484584" alt="At The Art Gallery Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Top Dog">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TopDog_GREEN_Roomset1.jpg?v=1722271854" alt="Top Dog in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">Top Dog</span>
+ <span class="gb-pageno">36 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Top_Dog_Green_5ed388b8-f593-4438-9b5b-3d289a825f81.jpg?v=1722271739" alt="Top Dog pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Rose">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8901-DesignerWallcoverings-Los-Angeles-1.jpg?v=1730485679" alt="The Soire Rose in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Rose</span>
+ <span class="gb-pageno">37 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8901-DesignerWallcoverings-Los-Angeles-1_5aaf1b13-ea6e-4ce8-9e3f-53cb54939af2.jpg?v=1730485729" alt="The Soire Rose pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Blue">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8902-DesignerWallcoverings-Los-Angeles-1_65b1df4d-b2bb-4708-add6-8236787a35fd.jpg?v=1730489384" alt="The Soire Blue in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Blue</span>
+ <span class="gb-pageno">38 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8902-DesignerWallcoverings-Los-Angeles-1_65b1df4d-b2bb-4708-add6-8236787a35fd.jpg?v=1730489384" alt="The Soire Blue pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Peach">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8903-DesignerWallcoverings-Los-Angeles-1_0d792d9d-49e8-451d-87d8-cb988273943b.jpg?v=1730489929" alt="The Soire Peach in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Peach</span>
+ <span class="gb-pageno">39 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8903-DesignerWallcoverings-Los-Angeles-1_0d792d9d-49e8-451d-87d8-cb988273943b.jpg?v=1730489929" alt="The Soire Peach pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Plaster">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_ce2a9161-c4a3-470c-8a2f-57f8c6ad2951.jpg?v=1730490279" alt="The Soire Plaster in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Plaster</span>
+ <span class="gb-pageno">40 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_ce2a9161-c4a3-470c-8a2f-57f8c6ad2951.jpg?v=1730490279" alt="The Soire Plaster pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Taupe">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_d30a1059-c72c-4b5a-84b3-a863a568b776.jpg?v=1730490513" alt="The Soire Taupe in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Taupe</span>
+ <span class="gb-pageno">41 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8904-DesignerWallcoverings-Los-Angeles-1_d30a1059-c72c-4b5a-84b3-a863a568b776.jpg?v=1730490513" alt="The Soire Taupe pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="The Soire Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8906-DesignerWallcoverings-Los-Angeles-1_a03ddfea-1e9f-48ca-9c90-4e08b979c0a0.jpg?v=1730490810" alt="The Soire Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">characters</span>
+ <span class="gb-name">The Soire Mustard</span>
+ <span class="gb-pageno">42 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-8906-DesignerWallcoverings-Los-Angeles-1_a03ddfea-1e9f-48ca-9c90-4e08b979c0a0.jpg?v=1730490810" alt="The Soire Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande - Plum">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/stag_plum_offset_grande_7ce7d09c-2260-43df-9408-be0985c14fe0.jpg?v=1570091054" alt="Stag Grande - Plum in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande - Plum</span>
+ <span class="gb-pageno">43 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0002.jpg?v=1570091054" alt="Stag Grande - Plum pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_Teal_Large_head_grande_e3b54fee-2979-4805-9de2-145b12fe2eed.jpg?v=1570091054" alt="Stag Grande Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande Teal</span>
+ <span class="gb-pageno">44 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0006.jpg?v=1570091054" alt="Stag Grande Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag Grande Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ABgIgtqVS3OOiOgAFth3_stag_head_grey_grande_28e10eef-c4f6-4ac0-831d-139f08c675f3.jpg?v=1570091054" alt="Stag Grande Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag Grande Grey</span>
+ <span class="gb-pageno">45 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0007.jpg?v=1570091054" alt="Stag Grande Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Stag_Print_Wallpaper_-_Teal_1024x1024_74130f65-820d-4318-862d-4a3bb0bf93a5.png?v=1730488729" alt="Small Stag Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Teal</span>
+ <span class="gb-pageno">46 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/ScreenShot2021-10-08at3.36.54PM.png?v=1633732668" alt="Small Stag Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Charcoal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllicGold_TealRoom_891a94b2-3962-4f18-b19d-102772052fd7.png?v=1730484627" alt="Dipped In Moonlight Charcoal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Charcoal</span>
+ <span class="gb-pageno">47 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllicGold_Teal_c272519f-6ae8-4897-b33d-f518c24008df.png?v=1730484627" alt="Dipped In Moonlight Charcoal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Cream">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_CreamRoom_b6207c57-e66f-4645-979e-cb39a415a9fb.png?v=1730484621" alt="Dipped In Moonlight Cream in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Cream</span>
+ <span class="gb-pageno">48 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_Cream_4c873c3d-77ee-4fcf-8900-ad39cdbdfe1c.png?v=1730484621" alt="Dipped In Moonlight Cream pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Dipped In Moonlight Teal">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_TealRoom_cada0f29-52ed-43d3-b40c-4e78c71b3e1e.png?v=1730484615" alt="Dipped In Moonlight Teal in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Dipped In Moonlight Teal</span>
+ <span class="gb-pageno">49 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DippedinMoonlightMetalllic_Teal_fc6a1852-7e7d-472b-a075-06ef92f14c8a.png?v=1730484615" alt="Dipped In Moonlight Teal pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Plum">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/stag_print_plum_grande_b0ad71c0-d6ed-47fc-8527-c9aecd18856f.jpg?v=1570091054" alt="Small Stag Plum in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Plum</span>
+ <span class="gb-pageno">50 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Graduate_Collection_wallpaper_trade_book_Page_17_Image_0003.jpg?v=1570091054" alt="Small Stag Plum pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Small Stag Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_print_grey_grande_4c9922c5-ea6f-408f-b033-ec070caa69ad.jpg?v=1689895357" alt="Small Stag Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Small Stag Grey</span>
+ <span class="gb-pageno">51 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GRD-87043-DesignerWallcoverings-Los-Angeles-2.png?v=1689895357" alt="Small Stag Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Stag">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_1.jpg?v=1602006861" alt="Stag in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Stag</span>
+ <span class="gb-pageno">52 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/products/Stag_1.jpg?v=1602006861" alt="Stag pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Pistachio">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.31.12PM.png?v=1709670701" alt="Vestige Pistachio in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Pistachio</span>
+ <span class="gb-pageno">53 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.30.53PM.png?v=1709670718" alt="Vestige Pistachio pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Mustard">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.38.06PM.png?v=1776370140" alt="Vestige Mustard in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Mustard</span>
+ <span class="gb-pageno">54 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.38.25PM.png?v=1776370140" alt="Vestige Mustard pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page" role="group" aria-label="Vestige Grey">
+ <div class="gb-spread">
+ <div class="gb-verso">
+ <img class="gb-room" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.41.19PM.png?v=1709671326" alt="Vestige Grey in a room setting" loading="lazy">
+ <div class="gb-meta">
+ <span class="gb-chapter">stags</span>
+ <span class="gb-name">Vestige Grey</span>
+ <span class="gb-pageno">55 / 55</span>
+ </div>
+ </div>
+ <div class="gb-recto">
+ <img class="gb-swatch" src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ScreenShot2024-03-05at12.41.06PM.png?v=1709671354" alt="Vestige Grey pattern" loading="lazy">
+ </div>
+ </div>
+ </div>
+ <div class="pf-page gb-cover gb-cover--back" role="group" aria-label="Back cover">
+ <div class="gb-cover__inner">
+ <span class="gb-cover__title">Shop the Graduate Collection</span>
+ <a class="gb-cover__cta" href="https://www.designerwallcoverings.com/collections/the-graduate-collection">Browse all 55 patterns →</a>
+ </div>
+ </div>
+ </div>
+ <audio class="dw-gbook__audio" data-gb="audio" preload="none" src="https://marketing.designerwallcoverings.com/reels/graduate-narration.mp4"></audio>
+</section>
+<style>
+ .dw-gbook{max-width:1100px;margin:0 auto 1.75rem;padding:0 1rem;font-family:'Cormorant Garamond',Georgia,serif;}
+ .dw-gbook__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:0 0 .6rem;flex-wrap:wrap;}
+ .dw-gbook__label{font-size:.95rem;letter-spacing:.12em;text-transform:uppercase;color:#8a7f72;}
+ .dw-gbook__ctl{display:flex;align-items:center;gap:.4rem;}
+ .gb-btn{border:1px solid #cbb8a3;background:#fff;color:#3a3128;border-radius:999px;padding:.35rem .8rem;font:inherit;font-size:.9rem;cursor:pointer;line-height:1;transition:background .15s,color .15s;}
+ .gb-btn:hover{background:#f3ece2;}
+ .gb-btn--play{background:#14110e;color:#f4ede2;border-color:#14110e;}
+ .gb-btn--play:hover{background:#2a2118;}
+ .gb-btn--play.is-playing{background:#8a1f2b;border-color:#8a1f2b;}
+ .gb-count{min-width:4.5em;text-align:center;color:#6b6055;font-size:.9rem;}
+ .dw-gbook__book{aspect-ratio:16/9;background:#14110e;border-radius:10px;box-shadow:0 14px 48px rgba(0,0,0,.22);}
+ /* spread: verso (room + name) | recto (pattern) */
+ .gb-spread{position:absolute;inset:0;display:grid;grid-template-columns:1fr 1fr;background:#fbf7f1;}
+ .gb-verso{position:relative;overflow:hidden;background:#efe7db;}
+ .gb-room{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-room--none{background:linear-gradient(135deg,#e7ddce,#d8ccba);}
+ .gb-meta{position:absolute;left:0;right:0;bottom:0;padding:1rem 1.1rem;display:flex;flex-direction:column;gap:.15rem;background:linear-gradient(0deg,rgba(20,17,14,.72),rgba(20,17,14,0));color:#fdf8f0;}
+ .gb-chapter{font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;opacity:.85;}
+ .gb-name{font-size:1.45rem;line-height:1.1;}
+ .gb-pageno{font-size:.72rem;opacity:.7;letter-spacing:.1em;}
+ .gb-recto{position:relative;overflow:hidden;background:#fff;}
+ .gb-swatch{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
+ .gb-cover__inner{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:.5rem;background:radial-gradient(120% 120% at 50% 20%,#241d15,#14110e);color:#f4ede2;padding:2rem;}
+ .gb-cover__brand{font-size:.8rem;letter-spacing:.28em;text-transform:uppercase;color:#c9a86a;}
+ .gb-cover__title{font-size:2.1rem;line-height:1.05;}
+ .gb-cover__sub{font-size:1rem;color:#b6a894;}
+ .gb-cover__cta{margin-top:.4rem;color:#14110e;background:#c9a86a;border-radius:999px;padding:.5rem 1.1rem;text-decoration:none;font-size:.95rem;}
+ @media(max-width:640px){.gb-name{font-size:1.15rem}.gb-cover__title{font-size:1.5rem}.dw-gbook__book{aspect-ratio:4/3}}
+ @media(prefers-reduced-motion:reduce){.dw-gbook__book{scroll-behavior:auto}}
+</style>
+<script>/*!
+ * page-flip.js — a zero-dependency drag-to-paginate book / sketchbook UI.
+ *
+ * Seeded by Meng To (@MengTo)'s 2026-08-06 "page-flipping sketchbook" post:
+ * "AI gives you the basics unless you hand it a solid open-source to work
+ * from. So I asked for drag to paginate, which took many fixes for shadows."
+ * This file IS that solid open-source to work from. The hard parts it gets
+ * right — the ones "the basics" skip — are called out inline: the curl
+ * ambient-occlusion shadow, the gutter/spine shadow, velocity-flick release,
+ * and keeping the shadow synced to the page THROUGH the snap animation.
+ *
+ * Contract (see demo.html):
+ * <div class="pageflip" data-pageflip>
+ * <div class="pf-page">…page 1…</div>
+ * <div class="pf-page">…page 2…</div>
+ * …
+ * </div>
+ * Each direct .pf-page child becomes one leaf. Author content lives on the
+ * front; the back is an auto-generated paper backside.
+ *
+ * Usage:
+ * const book = new PageFlip(el, { onFlip(i){…} }); // or auto-init below
+ * book.next(); book.prev(); book.goTo(3);
+ *
+ * No build step, no framework, no license friction — vanilla ES2019.
+ */
+(function (global) {
+ 'use strict';
+
+ var DEFAULTS = {
+ dragZone: 0.5, // fraction of page width (from the outer edge) that starts a drag
+ flipThreshold: 0.5, // release past this fraction of the turn (0..1) completes the flip
+ flickVelocity: 0.6, // px/ms; a faster release completes the flip regardless of threshold
+ snapMs: 420, // snap animation duration
+ curlShadow: 0.42, // peak opacity of the curl ambient-occlusion shadow (0..1)
+ gutterShadow: 0.28, // peak opacity of the fixed spine/gutter shadow (0..1)
+ perspective: 2200, // px; larger = flatter/less dramatic depth
+ onFlip: null, // (index) => void, fired after a completed flip settles
+ onTurn: null // (progress, dir) => void, fired continuously while turning (progress 0..1)
+ };
+
+ // power-in-out easing keeps the snap feeling weighted, not linear/robotic.
+ function easeInOut(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }
+ function clamp(v, lo, hi) { return v < lo ? lo : v > hi ? hi : v; }
+
+ function PageFlip(root, opts) {
+ if (!root) throw new Error('PageFlip: root element required');
+ if (root.__pageflip) return root.__pageflip; // idempotent
+ this.root = root;
+ this.o = Object.assign({}, DEFAULTS, opts || {});
+ this.pages = [];
+ this.index = 0; // top face-up leaf
+ this.dragging = false;
+ this.raf = 0;
+ root.__pageflip = this;
+ this._build();
+ this._bind();
+ this._layout();
+ }
+
+ PageFlip.prototype._build = function () {
+ var root = this.root;
+ root.classList.add('pageflip');
+ root.style.setProperty('--pf-persp', this.o.perspective + 'px');
+
+ // Promote each .pf-page child into a two-faced leaf with a curl-shadow layer.
+ var kids = Array.prototype.filter.call(root.children, function (c) {
+ return c.classList && c.classList.contains('pf-page');
+ });
+ var self = this;
+ kids.forEach(function (leaf, i) {
+ // Move author content into a front face (once — re-init safe).
+ if (!leaf.querySelector(':scope > .pf-front')) {
+ var front = document.createElement('div');
+ front.className = 'pf-face pf-front';
+ while (leaf.firstChild) front.appendChild(leaf.firstChild);
+ leaf.appendChild(front);
+
+ var back = document.createElement('div');
+ back.className = 'pf-face pf-back';
+ back.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(back);
+
+ // Curl shadow: a gradient overlay whose opacity we drive from the turn
+ // angle. This is the "many fixes for shadows" layer — see physics.md.
+ var curl = document.createElement('div');
+ curl.className = 'pf-curl';
+ curl.setAttribute('aria-hidden', 'true');
+ leaf.appendChild(curl);
+ }
+ leaf.dataset.pfIndex = String(i);
+ leaf.setAttribute('role', 'group');
+ leaf.setAttribute('aria-roledescription', 'page');
+ self.pages.push(leaf);
+ });
+
+ // Fixed gutter/spine shadow — always present at the binding edge so the
+ // book reads as bound even when no page is turning.
+ if (!root.querySelector(':scope > .pf-gutter')) {
+ var gutter = document.createElement('div');
+ gutter.className = 'pf-gutter';
+ gutter.setAttribute('aria-hidden', 'true');
+ root.appendChild(gutter);
+ root.style.setProperty('--pf-gutter', this.o.gutterShadow);
+ }
+ };
+
+ PageFlip.prototype._layout = function () {
+ // Resting state: leaves before `index` are turned (-180°) and stack on the
+ // left ascending; leaves at/after `index` are flat and stack on the right
+ // with `index` on top.
+ var n = this.pages.length;
+ for (var i = 0; i < n; i++) {
+ var leaf = this.pages[i];
+ if (i < this.index) {
+ this._setLeaf(leaf, -180, 0);
+ leaf.style.zIndex = String(i); // earlier turned pages sink lower
+ leaf.classList.add('pf-turned');
+ } else {
+ this._setLeaf(leaf, 0, 0);
+ leaf.style.zIndex = String(n - i); // current on top, rest descend
+ leaf.classList.remove('pf-turned');
+ }
+ leaf.setAttribute('aria-hidden', i === this.index || i === this.index + 1 ? 'false' : 'true');
+ }
+ this.root.dataset.pfIndex = String(this.index);
+ };
+
+ // Apply a rotation + its matching shadow to one leaf. angleDeg in [-180, 0].
+ PageFlip.prototype._setLeaf = function (leaf, angleDeg, forceShadow) {
+ leaf.style.transform = 'rotateY(' + angleDeg + 'deg)';
+ var curl = leaf.querySelector(':scope > .pf-curl');
+ if (!curl) return;
+ // sin() peaks at 90° (page standing up) and vanishes flat at 0°/180° — the
+ // physically-right shape for ambient occlusion of a curling sheet.
+ var a = Math.abs(angleDeg);
+ var s = (forceShadow != null ? forceShadow : Math.sin(a * Math.PI / 180)) * this.o.curlShadow;
+ curl.style.opacity = String(s);
+ // Past 90° we're looking at the back of the sheet: flip the gradient so the
+ // shading gathers toward the (now leading) spine edge, not the free edge.
+ curl.style.setProperty('--pf-curl-dir', a > 90 ? '1' : '0');
+ };
+
+ PageFlip.prototype._bind = function () {
+ var self = this;
+ this._onDown = function (e) { self._down(e); };
+ this._onMove = function (e) { self._move(e); };
+ this._onUp = function (e) { self._up(e); };
+ this.root.addEventListener('pointerdown', this._onDown);
+ // Keyboard paging for accessibility. Only set tabIndex when the element
+ // has no explicit tabindex attribute; avoids overwriting intentional -1.
+ if (!this.root.hasAttribute('tabindex')) this.root.tabIndex = 0;
+ // Stored (not anonymous) so destroy() can remove it — otherwise re-init on
+ // the same element stacks keydown listeners.
+ this._onKey = function (e) {
+ if (e.key === 'ArrowRight' || e.key === 'PageDown') { self.next(); e.preventDefault(); }
+ else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { self.prev(); e.preventDefault(); }
+ };
+ this.root.addEventListener('keydown', this._onKey);
+ this._onResize = function () { self.width = self.root.clientWidth; };
+ window.addEventListener('resize', this._onResize);
+ this.width = this.root.clientWidth;
+ };
+
+ PageFlip.prototype._down = function (e) {
+ if (this.animating) return;
+ var rect = this.root.getBoundingClientRect();
+ var x = (e.clientX - rect.left) / rect.width; // 0 (spine/left) .. 1 (outer/right)
+ var dir;
+ // Right dragZone turns forward (needs a next page); left turns back.
+ if (x >= 1 - this.o.dragZone && this.index < this.pages.length - 1) dir = 1;
+ else if (x <= this.o.dragZone && this.index > 0) dir = -1;
+ else return;
+
+ this.dragging = true;
+ this.dir = dir;
+ this.startX = e.clientX;
+ this.width = rect.width;
+ this.lastX = e.clientX;
+ this.lastT = e.timeStamp;
+ this.vel = 0;
+
+ // The leaf that visually turns: the current leaf when going forward, the
+ // previous (already-turned) leaf when going back.
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1); // ride on top while turning
+ this.active.classList.add('pf-turning');
+ this.root.classList.add('pf-grabbing');
+
+ try { this.root.setPointerCapture(e.pointerId); } catch (_) {}
+ window.addEventListener('pointermove', this._onMove);
+ window.addEventListener('pointerup', this._onUp);
+ window.addEventListener('pointercancel', this._onUp);
+ e.preventDefault();
+ };
+
+ PageFlip.prototype._move = function (e) {
+ if (!this.dragging) return;
+ var dt = e.timeStamp - this.lastT;
+ if (dt > 0) this.vel = (e.clientX - this.lastX) / dt; // px/ms, signed
+ this.lastX = e.clientX; this.lastT = e.timeStamp;
+
+ var dx = e.clientX - this.startX;
+ // progress 0 (flat/resting) .. 1 (fully turned) for this drag direction.
+ var progress = this.dir === 1
+ ? clamp(-dx / this.width, 0, 1) // forward: drag left (dx<0)
+ : clamp(dx / this.width, 0, 1); // back: drag right (dx>0)
+ // Forward turns the current leaf 0 -> -180; back turns the prev leaf -180 -> 0.
+ var angle = this.dir === 1 ? -progress * 180 : -180 + progress * 180;
+ this._setLeaf(this.active, angle);
+ this.progress = progress;
+ if (this.o.onTurn) this.o.onTurn(progress, this.dir);
+ };
+
+ PageFlip.prototype._up = function () {
+ if (!this.dragging) return;
+ this.dragging = false;
+ this.root.classList.remove('pf-grabbing');
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+
+ // A quick flick completes the flip even if you didn't cross the threshold —
+ // velocity sign must agree with the turn direction (drag left = negative).
+ var flick = (this.dir === 1 && this.vel < -this.o.flickVelocity) ||
+ (this.dir === -1 && this.vel > this.o.flickVelocity);
+ var complete = this.progress >= this.o.flipThreshold || flick;
+ this._settle(complete);
+ };
+
+ // Animate the active leaf to its resting angle, driving the shadow the whole
+ // way so it never "pops" at the seam between drag and snap.
+ PageFlip.prototype._settle = function (complete) {
+ var self = this;
+ this.animating = true;
+ var fromProg = this.progress || 0;
+ var toProg = complete ? 1 : 0;
+ var t0 = null;
+ cancelAnimationFrame(this.raf);
+
+ function frame(t) {
+ if (t0 == null) t0 = t;
+ var k = clamp((t - t0) / self.o.snapMs, 0, 1);
+ var p = fromProg + (toProg - fromProg) * easeInOut(k);
+ var angle = self.dir === 1 ? -p * 180 : -180 + p * 180;
+ self._setLeaf(self.active, angle);
+ if (self.o.onTurn) self.o.onTurn(p, self.dir);
+ if (k < 1) { self.raf = requestAnimationFrame(frame); return; }
+
+ // Landed. Commit the index and re-layout to the clean resting state.
+ self.active.classList.remove('pf-turning');
+ if (complete) self.index += self.dir;
+ self.animating = false;
+ self._layout();
+ if (complete && self.o.onFlip) self.o.onFlip(self.index);
+ }
+ this.raf = requestAnimationFrame(frame);
+ };
+
+ // Programmatic paging animates via the same settle path for a consistent feel.
+ PageFlip.prototype._go = function (dir) {
+ if (this.animating || this.dragging) return false;
+ if (dir === 1 && this.index >= this.pages.length - 1) return false;
+ if (dir === -1 && this.index <= 0) return false;
+ this.dir = dir;
+ this.width = this.root.clientWidth;
+ this.progress = 0;
+ this.active = dir === 1 ? this.pages[this.index] : this.pages[this.index - 1];
+ this.active.style.zIndex = String(this.pages.length + 1);
+ this.active.classList.add('pf-turning');
+ this._settle(true);
+ return true;
+ };
+
+ PageFlip.prototype.next = function () { return this._go(1); };
+ PageFlip.prototype.prev = function () { return this._go(-1); };
+ PageFlip.prototype.goTo = function (i) {
+ i = clamp(i | 0, 0, this.pages.length - 1);
+ if (this.animating || this.dragging) return;
+ this.index = i; this._layout();
+ if (this.o.onFlip) this.o.onFlip(this.index);
+ };
+ PageFlip.prototype.count = function () { return this.pages.length; };
+ PageFlip.prototype.current = function () { return this.index; };
+
+ PageFlip.prototype.destroy = function () {
+ cancelAnimationFrame(this.raf);
+ this.root.removeEventListener('pointerdown', this._onDown);
+ this.root.removeEventListener('keydown', this._onKey);
+ window.removeEventListener('pointermove', this._onMove);
+ window.removeEventListener('pointerup', this._onUp);
+ window.removeEventListener('pointercancel', this._onUp);
+ window.removeEventListener('resize', this._onResize);
+ delete this.root.__pageflip;
+ };
+
+ // Auto-init any [data-pageflip] on DOM ready so the drop-in "just works".
+ function auto() {
+ var els = document.querySelectorAll('[data-pageflip]');
+ Array.prototype.forEach.call(els, function (el) {
+ if (!el.__pageflip) new PageFlip(el);
+ });
+ }
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', auto);
+ } else {
+ auto();
+ }
+
+ global.PageFlip = PageFlip;
+ if (typeof module !== 'undefined' && module.exports) module.exports = PageFlip;
+})(typeof window !== 'undefined' ? window : this);
+</script>
+<script>
+(function(){
+ var root=document.querySelector('.dw-gbook'); if(!root) return;
+ var el=root.querySelector('[data-pageflip]');
+ var audio=root.querySelector('[data-gb=audio]');
+ var playBtn=root.querySelector('[data-gb=play]');
+ var countEl=root.querySelector('[data-gb=count]');
+ var COVER=2.20, INTERVAL=2.113, DUR=124.2, TOTAL=56;
+ // page-flip auto-inits on DOMContentLoaded; init now if not yet (PageFlip is idempotent).
+ var book=el.__pageflip||new PageFlip(el); if(!book){ return; }
+ var auto=false, raf=0, startT=0;
+ function count(){ countEl.textContent=(book.current()+1)+' / '+TOTAL; }
+ book.o.onFlip=count; count();
+ // manual paging (buttons stop auto-play, then turn — animated)
+ root.querySelector('[data-gb=prev]').addEventListener('click',function(){ stop(); book.prev(); });
+ root.querySelector('[data-gb=next]').addEventListener('click',function(){ stop(); book.next(); });
+ // grabbing a page mid-play cancels auto-play (you took the wheel)
+ el.addEventListener('pointerdown',function(){ if(auto) stop(); },true);
+
+ // Clock: prefer the narration's own currentTime (so pages track the VO), but fall
+ // back to a wall-clock timer so PLAY still flips the pages even if audio is blocked.
+ function elapsed(){
+ if(audio && !audio.paused && audio.currentTime>0.05) return audio.currentTime;
+ return (performance.now()-startT)/1000;
+ }
+ function tick(){
+ if(!auto) return;
+ var t=elapsed();
+ var target=t<COVER?0:Math.min(TOTAL-1,1+Math.floor((t-COVER)/INTERVAL));
+ // advance with the ANIMATED page-turn (next/prev), one step per frame as needed
+ if(target>book.current()) book.next();
+ else if(target<book.current()) book.prev();
+ if((audio&&audio.ended) || (t>=DUR && book.current()>=TOTAL-1)){ stop(); return; }
+ raf=requestAnimationFrame(tick);
+ }
+ function play(){
+ auto=true; playBtn.classList.add('is-playing'); playBtn.textContent='⏸ Pause';
+ if(book.current()>=TOTAL-1) book.goTo(0);
+ startT=performance.now();
+ if(audio){ try{ audio.currentTime=0; }catch(e){}
+ audio.play().then(function(){ startT=performance.now()-audio.currentTime*1000; })
+ .catch(function(){ /* audio blocked — pages still flip on the timer */ }); }
+ cancelAnimationFrame(raf); raf=requestAnimationFrame(tick);
+ }
+ function stop(){
+ auto=false; playBtn.classList.remove('is-playing'); playBtn.textContent='▶ Play narrated';
+ if(audio) audio.pause(); cancelAnimationFrame(raf);
+ }
+ playBtn.addEventListener('click',function(){ auto?stop():play(); });
+ if(audio) audio.addEventListener('ended',stop);
+})();
+</script>
+<!-- ==== /Graduate interactive flip book ==== -->
+{%- endif -%}
+
+{%- assign aeo_faq = collection.metafields.custom.faq.value -%}
+<script type="application/ld+json">
+{"@context":"https://schema.org","@type":"CollectionPage","name":{{ collection.title | json }},"description":{{ collection.description | strip_html | truncatewords: 40 | json }},"url":{{ request.origin | append: collection.url | json }},"isPartOf":{"@type":"WebSite","name":"Designer Wallcoverings","url":{{ request.origin | json }}}}
+</script>
+<script type="application/ld+json">
+{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":{{ request.origin | json }}},{"@type":"ListItem","position":2,"name":"Collections","item":{{ request.origin | append: '/collections' | json }}},{"@type":"ListItem","position":3,"name":{{ collection.title | json }},"item":{{ request.origin | append: collection.url | json }}}]}
+</script>
+{%- if aeo_faq != blank and aeo_faq != empty -%}
+<details class="dw-collection-faq" style="max-width:900px;margin:1rem auto .5rem;text-align:center;"><summary style="cursor:pointer;display:inline-block;list-style:none;font:600 .8rem/1.5 inherit;letter-spacing:.08em;text-transform:uppercase;padding:.55rem 1.5rem;border:1px solid currentColor;border-radius:2px;opacity:.9;">Learn about {{ collection.title | remove: ' Collections' | remove: ' Collection' }}</summary><div style="text-align:left;max-width:760px;margin:.9rem auto 0;padding:0 1rem;">{%- for item in aeo_faq -%}<h3 style="font-size:1rem;margin:.75rem 0 .25rem;">{{ item.q }}</h3><p style="margin:0 0 .5rem;opacity:.85;">{{ item.a }}</p>{%- endfor -%}</div></details>
+<script type="application/ld+json">
+{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{%- for item in aeo_faq -%}{"@type":"Question","name":{{ item.q | json }},"acceptedAnswer":{"@type":"Answer","text":{{ item.a | strip_html | json }}}}{% unless forloop.last %},{% endunless %}{%- endfor -%}]}
+</script>
+{%- endif -%}
+<style>
+ .dw-collection-hero{position:relative;min-height:clamp(20px,2.67vw,35px);display:flex;
+ align-items:center;background-size:cover;background-position:center;background-repeat:no-repeat;
+ margin:0 0 1.5rem;overflow:hidden;}
+ .dw-collection-hero--fallback{background:linear-gradient(135deg,#1c1c1c 0%,#3a3a3a 55%,#2a2320 100%);}
+ /* mosaic + gradient variants get a real banner height so the 2x2 has room */
+ .dw-collection-hero--mosaic,
+ .dw-collection-hero--fallback{min-height:clamp(190px,24vw,320px);}
+ /* 2x2 quadrant of product images — each cell ~half page-width, so a low-res
+ (e.g. 500px) source stretches ~1.3x instead of ~5x full-bleed = stays sharp */
+ .dw-collection-hero__mosaic{position:absolute;inset:0;z-index:0;display:grid;
+ grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:2px;background:#211c19;}
+ .dw-collection-hero__cell{background-size:cover;background-position:center;
+ background-repeat:no-repeat;background-color:#211c19;min-height:0;min-width:0;}
+ /* graceful degrade when a small collection yields <4 tiles */
+ .dw-collection-hero__mosaic:has(.dw-collection-hero__cell:nth-child(1):last-child){grid-template-columns:1fr;grid-template-rows:1fr;}
+ .dw-collection-hero__mosaic:has(.dw-collection-hero__cell:nth-child(2):last-child){grid-template-rows:1fr;}
+ .dw-collection-hero__mosaic:has(.dw-collection-hero__cell:nth-child(3):last-child) .dw-collection-hero__cell:first-child{grid-column:1 / -1;}
+ .dw-collection-hero__inner{position:relative;z-index:1;width:100%;padding:0.9rem 2.25rem;}
+ /* Semi-opaque CONTRASTING panel behind the text — dark scrim over the light
+ pattern so title/breadcrumbs/description read clearly without darkening the
+ whole image. Constrained width, left-aligned. */
+ .dw-collection-hero__panel{display:inline-block;max-width:min(640px,92%);
+ background:rgba(22,18,16,0.66);
+ -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
+ border:1px solid rgba(255,255,255,0.14);border-radius:6px;
+ padding:1.4rem 1.75rem;box-shadow:0 6px 30px rgba(0,0,0,.28);}
+ .dw-collection-hero__crumbs{font-size:.78rem;letter-spacing:.04em;text-transform:uppercase;
+ color:#fff;opacity:.92;margin:0 0 .45rem;}
+ .dw-collection-hero__crumbs a,.dw-collection-hero__crumbs span{color:#fff;text-decoration:none;}
+ .dw-collection-hero__crumbs a:hover{text-decoration:underline;}
+ .dw-collection-hero__title{color:#fff;font-size:clamp(1.8rem,3.4vw,3rem);margin:.1rem 0 0;
+ letter-spacing:.5px;line-height:1.05;}
+ .dw-collection-hero__desc{color:#fff;max-width:60ch;margin:.6rem 0 0;opacity:.96;
+ font-size:.95rem;line-height:1.55;}
+
+ /* Hide the duplicate LOWER banner drawn by the Boost AI Search & Filter app
+ (its own collection header/banner) so only this hero shows. */
+ .boost-sd__collection-header,
+ .boost-sd__page-header,
+ .boost-sd__collection-header-image,
+ .boost-sd__collection-header-content,
+ .boost-sd__collection-header-title,
+ .boost-sd__collection-header-description,
+ .boost-sd__collection-title,
+ .boost-sd__collection-description{display:none !important;}
+ /* hero now carries breadcrumbs: hide any legacy theme breadcrumbs on collection pages */
+ .template-collection .breadcrumbs,
+ .template-collection .breadcrumb{display:none;}
+</style>
+
+{% schema %}
+{
+ "name": "DW Collection Hero",
+ "settings": [
+ {
+ "type": "checkbox",
+ "id": "show_description",
+ "label": "Show collection description in hero",
+ "default": true
+ }
+ ],
+ "presets": [
+ { "name": "DW Collection Hero" }
+ ]
+}
+{% endschema %}
← f829c3c auto-data-snapshot: 2026-09-04T07:10:31 (3 data files) — dat
·
back to Dw Marketing Reels
·
auto-data-snapshot: 2026-09-05T07:30:17 (3 data files) — dat 7f0f260 →