← back to Model Arena
Agent-driven editorial: DW The Lookbook (frontend-developer) — 6 swipeable style spreads, SVG heroes, inert TOC. Registered.
ef2e59b2eb6e5ddfc658cf25cacf7839e501430e · 2026-07-25 11:44:01 -0700 · Steve Abrams
Files touched
M data/arcade-games.jsonA public/games/dw-lookbook.html
Diff
commit ef2e59b2eb6e5ddfc658cf25cacf7839e501430e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Jul 25 11:44:01 2026 -0700
Agent-driven editorial: DW The Lookbook (frontend-developer) — 6 swipeable style spreads, SVG heroes, inert TOC. Registered.
---
data/arcade-games.json | 6 +
public/games/dw-lookbook.html | 1020 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 1026 insertions(+)
diff --git a/data/arcade-games.json b/data/arcade-games.json
index 730ca7d..28c8f76 100644
--- a/data/arcade-games.json
+++ b/data/arcade-games.json
@@ -65,6 +65,12 @@
"title": "DW Pattern Match",
"credit": "frontend-developer",
"note": "Agent-built match-3 game \u2014 swap luxury swatch tiles, cascading combos, 6 textures"
+ },
+ {
+ "slug": "dw-lookbook",
+ "title": "DW The Lookbook",
+ "credit": "frontend-developer",
+ "note": "Agent-built editorial \u2014 6 swipeable style spreads (Grandmillennial\u2192Modern Minimal), each with SVG hero + palette"
}
]
}
\ No newline at end of file
diff --git a/public/games/dw-lookbook.html b/public/games/dw-lookbook.html
new file mode 100644
index 0000000..b2168bd
--- /dev/null
+++ b/public/games/dw-lookbook.html
@@ -0,0 +1,1020 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — The Lookbook</title>
+<style>
+/* ── TOKENS ── */
+:root {
+ --bg: #0d0b09;
+ --ink: #1c1a17;
+ --cream: #f4f1ea;
+ --mid: #8a8070;
+ --accent: #c9a961;
+ --accent-dim: #9a7d42;
+ --serif: 'Cormorant Garamond','Playfair Display','EB Garamond',Georgia,serif;
+ --sans: 'Optima','Gill Sans','Trebuchet MS',sans-serif;
+ --ease: cubic-bezier(.4,0,.2,1);
+ --ease-out: cubic-bezier(0,0,.2,1);
+ --ease-spring: cubic-bezier(.34,1.56,.64,1);
+ --r: 2px;
+}
+
+/* ── RESET ── */
+*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
+html,body{width:100%;height:100%;overflow:hidden;background:var(--bg)}
+body{font-family:var(--sans);color:var(--cream);-webkit-font-smoothing:antialiased}
+
+/* ── HEADER ── */
+header{
+ position:fixed;top:0;left:0;right:0;z-index:100;
+ display:flex;align-items:center;justify-content:space-between;
+ padding:18px 36px 16px;
+ background:linear-gradient(180deg,rgba(13,11,9,.92) 0%,rgba(13,11,9,0) 100%);
+ pointer-events:none;
+}
+.wordmark{
+ font-family:var(--serif);font-size:clamp(15px,1.6vw,22px);
+ font-weight:400;letter-spacing:.18em;text-transform:uppercase;
+ color:var(--ink); /* darkest ink, never white-on-cream */
+ color:var(--cream); /* on dark bg: lightest token */
+ line-height:1;pointer-events:auto;
+}
+.wordmark span{color:var(--accent);letter-spacing:.22em}
+.hdr-right{display:flex;align-items:center;gap:20px;pointer-events:auto}
+.toc-btn{
+ font-family:var(--sans);font-size:11px;letter-spacing:.16em;text-transform:uppercase;
+ color:var(--cream);opacity:.7;background:none;border:none;cursor:pointer;
+ transition:opacity .2s var(--ease);
+}
+.toc-btn:hover{opacity:1}
+
+/* ── PROGRESS BAR ── */
+.progress-bar{
+ position:fixed;top:0;left:0;height:2px;z-index:200;
+ background:var(--accent);width:0%;transition:width .5s var(--ease-out);
+}
+
+/* ── SLIDES VIEWPORT ── */
+.viewport{
+ width:100%;height:100vh;position:relative;overflow:hidden;
+}
+.slides-track{
+ display:flex;width:600%;height:100%;
+ transition:transform .75s var(--ease-out);
+ will-change:transform;
+}
+.slide{
+ width:calc(100%/6);flex-shrink:0;height:100%;
+ position:relative;overflow:hidden;
+}
+
+/* ── DOT NAV ── */
+.dots{
+ position:fixed;bottom:32px;left:50%;transform:translateX(-50%);
+ display:flex;gap:10px;z-index:100;
+}
+.dot{
+ width:6px;height:6px;border-radius:50%;
+ background:rgba(249,241,234,.3);border:1px solid rgba(249,241,234,.4);
+ cursor:pointer;transition:all .3s var(--ease);
+}
+.dot.active{
+ background:var(--accent);border-color:var(--accent);
+ transform:scale(1.4);
+}
+
+/* ── ARROW NAV ── */
+.arrow{
+ position:fixed;top:50%;transform:translateY(-50%);z-index:100;
+ background:none;border:1px solid rgba(201,169,97,.3);
+ color:var(--accent);font-size:18px;width:44px;height:44px;
+ border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;
+ transition:all .25s var(--ease);opacity:.6;
+}
+.arrow:hover{opacity:1;background:rgba(201,169,97,.12);border-color:var(--accent)}
+.arrow-prev{left:24px}
+.arrow-next{right:24px}
+
+/* ── SPREAD LABEL ── */
+.spread-num{
+ position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
+ font-family:var(--serif);font-size:clamp(100px,18vw,240px);
+ font-weight:300;letter-spacing:-.02em;color:rgba(255,255,255,.03);
+ pointer-events:none;user-select:none;z-index:1;line-height:1;
+}
+
+/* ── PALETTE STRIP ── */
+.palette-strip{
+ display:flex;gap:0;overflow:hidden;border-radius:var(--r);
+}
+.swatch{
+ height:28px;flex:1;cursor:pointer;position:relative;
+ transition:flex .3s var(--ease);
+}
+.swatch:hover{flex:2.4}
+.swatch::after{
+ content:attr(data-name);
+ position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);
+ font-family:var(--sans);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
+ color:var(--cream);opacity:0;white-space:nowrap;
+ transition:opacity .2s var(--ease);pointer-events:none;
+}
+.swatch:hover::after{opacity:.8}
+
+/* ── PATTERN SWATCH ── */
+.pattern-frame{
+ position:relative;overflow:hidden;border-radius:var(--r);
+}
+.pattern-label{
+ margin-top:10px;font-family:var(--sans);font-size:10px;
+ letter-spacing:.15em;text-transform:uppercase;color:var(--accent);
+ opacity:.85;
+}
+
+/* ── EDITORIAL TEXT ── */
+.headline{
+ font-family:var(--serif);font-weight:300;line-height:1.08;
+ letter-spacing:-.01em;
+}
+.tagline{
+ font-family:var(--sans);font-size:10.5px;letter-spacing:.22em;
+ text-transform:uppercase;color:var(--accent);margin-bottom:14px;
+}
+.body-copy{
+ font-family:var(--serif);font-size:clamp(14px,1.2vw,17px);
+ line-height:1.72;font-weight:300;opacity:.82;
+ font-style:italic;
+}
+.rule{
+ display:block;width:48px;height:1px;
+ background:var(--accent);margin:20px 0;opacity:.6;
+}
+
+/* ── REVEAL ANIMATION ── */
+.reveal{
+ opacity:0;transform:translateY(22px);
+ transition:opacity .7s var(--ease-out),transform .7s var(--ease-out);
+}
+.reveal.in{opacity:1;transform:none}
+.reveal.d1{transition-delay:.1s}
+.reveal.d2{transition-delay:.25s}
+.reveal.d3{transition-delay:.42s}
+.reveal.d4{transition-delay:.58s}
+.reveal.d5{transition-delay:.72s}
+
+/* ── PARALLAX HERO ── */
+.parallax-hero{
+ position:absolute;inset:0;will-change:transform;
+ transition:transform .05s linear;
+}
+
+/* ── TOC OVERLAY ── */
+.toc-overlay{
+ position:fixed;inset:0;z-index:500;
+ background:rgba(13,11,9,.96);
+ display:flex;align-items:center;justify-content:center;
+ visibility:hidden;opacity:0;
+ transition:opacity .35s var(--ease),visibility 0s .35s;
+}
+.toc-overlay.open{visibility:visible;opacity:1;transition:opacity .35s var(--ease)}
+.toc-inner{text-align:center;max-width:520px;width:90%}
+.toc-title{
+ font-family:var(--serif);font-size:clamp(11px,1vw,13px);
+ letter-spacing:.28em;text-transform:uppercase;color:var(--accent);
+ margin-bottom:44px;
+}
+.toc-list{list-style:none;display:flex;flex-direction:column;gap:0}
+.toc-item{
+ padding:18px 0;border-bottom:1px solid rgba(201,169,97,.15);
+ cursor:pointer;display:flex;align-items:baseline;gap:18px;
+ transition:opacity .2s var(--ease);
+}
+.toc-item:first-child{border-top:1px solid rgba(201,169,97,.15)}
+.toc-item:hover .toc-item-title{color:var(--accent)}
+.toc-n{
+ font-family:var(--serif);font-size:12px;color:var(--accent);
+ opacity:.6;min-width:24px;
+}
+.toc-item-title{
+ font-family:var(--serif);font-size:clamp(22px,2.8vw,34px);
+ font-weight:300;letter-spacing:.04em;color:var(--cream);
+ transition:color .2s var(--ease);
+}
+.toc-sub{
+ font-family:var(--sans);font-size:10px;letter-spacing:.14em;
+ text-transform:uppercase;color:var(--mid);margin-left:auto;
+}
+.toc-close{
+ margin-top:40px;font-family:var(--sans);font-size:10px;
+ letter-spacing:.2em;text-transform:uppercase;color:var(--mid);
+ background:none;border:none;cursor:pointer;
+ transition:color .2s var(--ease);
+}
+.toc-close:hover{color:var(--cream)}
+
+/* ═══════════════════════════════════════
+ SPREAD 1 — GRANDMILLENNIAL
+═══════════════════════════════════════ */
+.s1{background:#f0ece4}
+.s1 .headline,.s1 .tagline,.s1 .body-copy,.s1 .pattern-label{
+ /* override for light spread */
+}
+.s1-layout{
+ display:grid;grid-template-columns:1fr 1fr;height:100%;
+}
+.s1-hero{position:relative;overflow:hidden}
+.s1-content{
+ display:flex;flex-direction:column;justify-content:center;
+ padding:clamp(36px,6vw,80px) clamp(36px,5vw,72px);
+ background:#f0ece4;
+ color:var(--ink);
+}
+.s1-content .headline{font-size:clamp(38px,5.5vw,80px);color:#1c1a17}
+.s1-content .tagline{color:#8a6d3a}
+.s1-content .body-copy{color:#3a3630}
+.s1-content .rule{background:#8a6d3a}
+.s1-content .pattern-label{color:#8a6d3a}
+
+/* ═══════════════════════════════════════
+ SPREAD 2 — COASTAL
+═══════════════════════════════════════ */
+.s2{background:#e8eff5}
+.s2-layout{
+ display:grid;grid-template-rows:1fr auto;height:100%;
+}
+.s2-hero{flex:1;position:relative;overflow:hidden}
+.s2-content{
+ padding:clamp(28px,4vw,52px) clamp(48px,7vw,120px);
+ background:rgba(20,36,52,.88);
+ color:#e8f0f7;
+}
+.s2-content .headline{font-size:clamp(32px,5vw,70px);color:#e8f0f7;line-height:1.04}
+.s2-content .tagline{color:#7fb5d5}
+.s2-content .body-copy{color:rgba(232,240,247,.75)}
+.s2-content .rule{background:#7fb5d5}
+.s2-content .pattern-label{color:#7fb5d5}
+.s2-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,80px);align-items:end}
+
+/* ═══════════════════════════════════════
+ SPREAD 3 — MOODY MAXIMALIST
+═══════════════════════════════════════ */
+.s3{background:#1a1210}
+.s3-layout{
+ display:grid;grid-template-columns:1.1fr .9fr;height:100%;
+}
+.s3-hero{position:relative;overflow:hidden}
+.s3-content{
+ display:flex;flex-direction:column;justify-content:center;
+ padding:clamp(36px,5vw,72px);background:#1a1210;
+ color:#e8dccf;
+}
+.s3-content .headline{font-size:clamp(36px,5vw,76px);color:#e8dccf}
+.s3-content .tagline{color:#c9a961}
+.s3-content .body-copy{color:rgba(232,220,207,.65)}
+.s3-content .rule{background:#c9a961}
+.s3-content .pattern-label{color:#c9a961}
+
+/* ═══════════════════════════════════════
+ SPREAD 4 — ART DECO
+═══════════════════════════════════════ */
+.s4{background:#0e0c08}
+.s4-layout{
+ display:flex;flex-direction:column;align-items:center;
+ justify-content:center;height:100%;
+ padding:clamp(60px,8vh,110px) clamp(36px,8vw,160px);
+ text-align:center;position:relative;
+}
+.s4 .headline{font-size:clamp(40px,6vw,96px);color:#e8dfc8;letter-spacing:.06em}
+.s4 .tagline{color:#c9a961;justify-content:center;display:flex}
+.s4 .body-copy{color:rgba(232,223,200,.7);max-width:480px;margin:0 auto;font-style:normal;font-size:clamp(13px,1.1vw,16px);letter-spacing:.04em;line-height:1.8}
+.s4 .rule{margin:20px auto}
+.s4 .pattern-label{color:#c9a961;text-align:center}
+.s4-frame{
+ position:absolute;inset:30px;border:1px solid rgba(201,169,97,.15);
+ pointer-events:none;
+}
+.s4-frame::before,.s4-frame::after{
+ content:'';position:absolute;width:24px;height:24px;
+ border-color:var(--accent);border-style:solid;opacity:.5;
+}
+.s4-frame::before{top:-1px;left:-1px;border-width:1px 0 0 1px}
+.s4-frame::after{bottom:-1px;right:-1px;border-width:0 1px 1px 0}
+
+/* ═══════════════════════════════════════
+ SPREAD 5 — CHINOISERIE
+═══════════════════════════════════════ */
+.s5{background:#f7f3eb}
+.s5-layout{
+ display:grid;grid-template-columns:.9fr 1.1fr;height:100%;
+}
+.s5-content{
+ display:flex;flex-direction:column;justify-content:center;
+ padding:clamp(36px,5vw,72px);background:#f7f3eb;color:#1c2218;
+}
+.s5-content .headline{font-size:clamp(34px,5vw,72px);color:#1c2218;line-height:1.06}
+.s5-content .tagline{color:#5c7a4a}
+.s5-content .body-copy{color:rgba(28,34,24,.72)}
+.s5-content .rule{background:#5c7a4a}
+.s5-content .pattern-label{color:#5c7a4a}
+.s5-hero{position:relative;overflow:hidden}
+
+/* ═══════════════════════════════════════
+ SPREAD 6 — MODERN MINIMAL
+═══════════════════════════════════════ */
+.s6{background:#f9f8f6}
+.s6-layout{
+ display:grid;grid-template-columns:1fr 1fr;height:100%;
+}
+.s6-content{
+ display:flex;flex-direction:column;justify-content:flex-end;
+ padding:clamp(48px,6vw,90px);background:#f9f8f6;color:#1c1a17;
+}
+.s6-content .headline{font-size:clamp(34px,4.8vw,72px);color:#1c1a17}
+.s6-content .tagline{color:#636058}
+.s6-content .body-copy{color:rgba(28,26,23,.68)}
+.s6-content .rule{background:#1c1a17;opacity:.25}
+.s6-content .pattern-label{color:#636058}
+.s6-hero{position:relative;overflow:hidden;background:#e8e5e0}
+.s6-accent-line{
+ position:absolute;left:0;top:50%;width:100%;height:1px;
+ background:rgba(28,26,23,.12);transform:translateY(-50%);
+}
+
+/* ── RESPONSIVE ── */
+@media(max-width:680px){
+ .s1-layout,.s3-layout,.s5-layout,.s6-layout{grid-template-columns:1fr}
+ .s1-hero,.s5-hero,.s6-hero,.s3-hero{display:none}
+ .s2-grid{grid-template-columns:1fr}
+ .s4-layout{padding:40px 24px}
+ header{padding:14px 20px}
+ .wordmark{font-size:13px}
+ .arrow{display:none}
+}
+</style>
+</head>
+<body>
+
+<!-- PROGRESS -->
+<div class="progress-bar" id="progressBar"></div>
+
+<!-- HEADER -->
+<header>
+ <div class="wordmark">Designer <span>Wallcoverings</span></div>
+ <div class="hdr-right">
+ <button class="toc-btn" onclick="openToc()">Contents</button>
+ </div>
+</header>
+
+<!-- ARROW NAV -->
+<button class="arrow arrow-prev" id="arrowPrev" aria-label="Previous spread" onclick="goTo(current-1)">←</button>
+<button class="arrow arrow-next" id="arrowNext" aria-label="Next spread" onclick="goTo(current+1)">→</button>
+
+<!-- DOT NAV -->
+<div class="dots" id="dots"></div>
+
+<!-- TOC OVERLAY -->
+<div class="toc-overlay" id="tocOverlay" role="dialog" aria-modal="true" aria-label="Table of Contents">
+ <div class="toc-inner">
+ <div class="toc-title">The Lookbook — 2026</div>
+ <ul class="toc-list" id="tocList"></ul>
+ <button class="toc-close" onclick="closeToc()">Close ×</button>
+ </div>
+</div>
+
+<!-- SLIDES -->
+<div class="viewport">
+ <div class="slides-track" id="track">
+
+ <!-- ══ SPREAD 1: GRANDMILLENNIAL ══ -->
+ <div class="slide s1" data-index="0">
+ <div class="spread-num">01</div>
+ <div class="s1-layout" style="height:100%">
+ <div class="s1-hero parallax-hero" data-speed=".04">
+ <svg viewBox="0 0 600 900" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position:absolute;inset:0">
+ <rect width="600" height="900" fill="#e6e0d5"/>
+ <!-- toile-style botanical background wash -->
+ <rect width="600" height="900" fill="url(#toileWash)" opacity=".18"/>
+ <!-- trellis grid -->
+ <defs>
+ <pattern id="toileWash" x="0" y="0" width="60" height="60" patternUnits="userSpaceOnUse">
+ <circle cx="30" cy="30" r="26" fill="none" stroke="#8a6d3a" stroke-width=".5"/>
+ <circle cx="0" cy="0" r="26" fill="none" stroke="#8a6d3a" stroke-width=".5"/>
+ <circle cx="60" cy="0" r="26" fill="none" stroke="#8a6d3a" stroke-width=".5"/>
+ <circle cx="0" cy="60" r="26" fill="none" stroke="#8a6d3a" stroke-width=".5"/>
+ <circle cx="60" cy="60" r="26" fill="none" stroke="#8a6d3a" stroke-width=".5"/>
+ </pattern>
+ <pattern id="toileFloral" x="0" y="0" width="120" height="160" patternUnits="userSpaceOnUse">
+ <!-- stem -->
+ <path d="M60 150 Q58 110 55 90 Q50 65 60 40" fill="none" stroke="#7a6040" stroke-width="1.2"/>
+ <!-- leaves -->
+ <ellipse cx="46" cy="100" rx="14" ry="7" fill="#8a7050" opacity=".55" transform="rotate(-30,46,100)"/>
+ <ellipse cx="74" cy="80" rx="14" ry="7" fill="#8a7050" opacity=".55" transform="rotate(30,74,80)"/>
+ <!-- bloom -->
+ <circle cx="60" cy="36" r="18" fill="none" stroke="#7a6040" stroke-width="1"/>
+ <circle cx="60" cy="36" r="10" fill="#c0a878" opacity=".4"/>
+ <circle cx="60" cy="36" r="4" fill="#8a6d3a" opacity=".6"/>
+ <!-- petals -->
+ <ellipse cx="60" cy="20" rx="5" ry="9" fill="#b09060" opacity=".45"/>
+ <ellipse cx="60" cy="52" rx="5" ry="9" fill="#b09060" opacity=".45"/>
+ <ellipse cx="44" cy="36" rx="9" ry="5" fill="#b09060" opacity=".45"/>
+ <ellipse cx="76" cy="36" rx="9" ry="5" fill="#b09060" opacity=".45"/>
+ <ellipse cx="48" cy="24" rx="5" ry="9" fill="#b09060" opacity=".35" transform="rotate(-45,48,24)"/>
+ <ellipse cx="72" cy="24" rx="5" ry="9" fill="#b09060" opacity=".35" transform="rotate(45,72,24)"/>
+ <ellipse cx="48" cy="48" rx="5" ry="9" fill="#b09060" opacity=".35" transform="rotate(45,48,48)"/>
+ <ellipse cx="72" cy="48" rx="5" ry="9" fill="#b09060" opacity=".35" transform="rotate(-45,72,48)"/>
+ </pattern>
+ </defs>
+ <rect width="600" height="900" fill="url(#toileFloral)" opacity=".55"/>
+ <!-- aged paper overlay -->
+ <rect width="600" height="900" fill="#f0e8d0" opacity=".28"/>
+ <!-- vignette -->
+ <radialGradient id="vigS1" cx="50%" cy="50%" r="70%">
+ <stop offset="0%" stop-color="transparent"/>
+ <stop offset="100%" stop-color="#a89060" stop-opacity=".35"/>
+ </radialGradient>
+ <rect width="600" height="900" fill="url(#vigS1)"/>
+ </svg>
+ </div>
+ <div class="s1-content">
+ <div class="tagline reveal d1">Story One</div>
+ <h2 class="headline reveal d2">Grand­millennial</h2>
+ <span class="rule reveal d3"></span>
+ <p class="body-copy reveal d4">Heirloom florals reborn for the contemporary interior. English toile, blush moiré, and gilded chintz converge in rooms that honour ancestry without apology — spaces that feel inherited, not merely decorated.</p>
+ <span class="rule reveal d4" style="opacity:.2"></span>
+ <div class="palette-strip reveal d4" style="margin-top:8px;border-radius:2px;overflow:hidden">
+ <div class="swatch" style="background:#d4c4a8" data-name="Parchment"></div>
+ <div class="swatch" style="background:#b09060" data-name="Old Gold"></div>
+ <div class="swatch" style="background:#8a6d3a" data-name="Tobacco"></div>
+ <div class="swatch" style="background:#c8b4a0" data-name="Blush Moiré"></div>
+ <div class="swatch" style="background:#6a5840" data-name="Walnut"></div>
+ </div>
+ <div class="pattern-frame reveal d5" style="margin-top:18px;width:88px;height:88px">
+ <svg viewBox="0 0 88 88" width="88" height="88" xmlns="http://www.w3.org/2000/svg">
+ <rect width="88" height="88" fill="#e6e0d5"/>
+ <rect width="88" height="88" fill="url(#toileFloral)" opacity=".7"/>
+ <rect width="88" height="88" fill="none" stroke="#8a6d3a" stroke-width=".5" opacity=".5"/>
+ </svg>
+ </div>
+ <div class="pattern-label reveal d5">Heirloom Botanical — No. 12</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- ══ SPREAD 2: COASTAL ══ -->
+ <div class="slide s2" data-index="1">
+ <div class="spread-num">02</div>
+ <div class="s2-layout" style="height:100%">
+ <div class="s2-hero" style="position:relative;overflow:hidden;flex:1">
+ <svg viewBox="0 0 1400 700" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position:absolute;inset:0">
+ <defs>
+ <linearGradient id="coastSky" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="#c8dff0"/>
+ <stop offset="55%" stop-color="#e8f0f7"/>
+ <stop offset="100%" stop-color="#d0e5f0"/>
+ </linearGradient>
+ <pattern id="wavePattern" x="0" y="0" width="200" height="40" patternUnits="userSpaceOnUse">
+ <path d="M0 20 Q25 5 50 20 Q75 35 100 20 Q125 5 150 20 Q175 35 200 20" fill="none" stroke="#7fb5d5" stroke-width="1.5" opacity=".4"/>
+ <path d="M0 28 Q25 13 50 28 Q75 43 100 28 Q125 13 150 28 Q175 43 200 28" fill="none" stroke="#5c9abd" stroke-width=".8" opacity=".3"/>
+ </pattern>
+ <pattern id="seagrassWeave" x="0" y="0" width="16" height="16" patternUnits="userSpaceOnUse">
+ <rect width="16" height="16" fill="#c8d8b8"/>
+ <line x1="0" y1="0" x2="16" y2="0" stroke="#a8b898" stroke-width="2"/>
+ <line x1="0" y1="4" x2="16" y2="4" stroke="#b8c8a8" stroke-width="1.5"/>
+ <line x1="0" y1="8" x2="16" y2="8" stroke="#a8b898" stroke-width="2"/>
+ <line x1="0" y1="12" x2="16" y2="12" stroke="#b8c8a8" stroke-width="1.5"/>
+ <line x1="0" y1="0" x2="0" y2="16" stroke="#98a888" stroke-width="1.5"/>
+ <line x1="4" y1="0" x2="4" y2="16" stroke="#a8b898" stroke-width="1"/>
+ <line x1="8" y1="0" x2="8" y2="16" stroke="#98a888" stroke-width="1.5"/>
+ <line x1="12" y1="0" x2="12" y2="16" stroke="#a8b898" stroke-width="1"/>
+ </pattern>
+ </defs>
+ <!-- sky -->
+ <rect width="1400" height="700" fill="url(#coastSky)"/>
+ <!-- horizon water -->
+ <rect x="0" y="460" width="1400" height="240" fill="#b8d8ec"/>
+ <!-- wave texture -->
+ <rect x="0" y="470" width="1400" height="220" fill="url(#wavePattern)"/>
+ <!-- beach / sand band -->
+ <ellipse cx="700" cy="520" rx="900" ry="80" fill="#ddd0a8" opacity=".6"/>
+ <!-- dunes / seagrass suggestion -->
+ <ellipse cx="200" cy="580" rx="260" ry="100" fill="#c8c0a0" opacity=".4"/>
+ <ellipse cx="1200" cy="570" rx="240" ry="90" fill="#c8c0a0" opacity=".35"/>
+ <!-- seagrass texture patch -->
+ <rect x="0" y="540" width="400" height="160" fill="url(#seagrassWeave)" opacity=".35"/>
+ <rect x="1000" y="530" width="400" height="170" fill="url(#seagrassWeave)" opacity=".3"/>
+ <!-- light overlay -->
+ <rect width="1400" height="700" fill="#e8f4f8" opacity=".18"/>
+ <!-- vignette top -->
+ <linearGradient id="coastVig" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="#c0d8e8" stop-opacity=".5"/>
+ <stop offset="40%" stop-color="transparent"/>
+ </linearGradient>
+ <rect width="1400" height="700" fill="url(#coastVig)"/>
+ </svg>
+ </div>
+ <div class="s2-content">
+ <div class="s2-grid">
+ <div>
+ <div class="tagline reveal d1">Story Two</div>
+ <h2 class="headline reveal d2">Coastal</h2>
+ <span class="rule reveal d3"></span>
+ <p class="body-copy reveal d4">Sea-bleached linens, seagrass weaves, and the unhurried blue of open water. Coastal living reimagined as quiet sophistication — salt air rendered in texture, light, and the gentle rhythm of natural fibre.</p>
+ </div>
+ <div>
+ <div class="palette-strip reveal d4" style="border-radius:2px;overflow:hidden;margin-bottom:16px">
+ <div class="swatch" style="background:#7fb5d5" data-name="Horizon"></div>
+ <div class="swatch" style="background:#c8d8b8" data-name="Seagrass"></div>
+ <div class="swatch" style="background:#ddd0a8" data-name="Driftwood"></div>
+ <div class="swatch" style="background:#5c9abd" data-name="Tidal"></div>
+ <div class="swatch" style="background:#e8f0f7" data-name="Sea Mist"></div>
+ </div>
+ <div class="pattern-frame reveal d5" style="width:72px;height:72px">
+ <svg viewBox="0 0 72 72" width="72" height="72" xmlns="http://www.w3.org/2000/svg">
+ <rect width="72" height="72" fill="url(#seagrassWeave)"/>
+ <rect width="72" height="72" fill="none" stroke="#5c9abd" stroke-width=".5" opacity=".6"/>
+ </svg>
+ </div>
+ <div class="pattern-label reveal d5">Coastal Seagrass — No. 07</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- ══ SPREAD 3: MOODY MAXIMALIST ══ -->
+ <div class="slide s3" data-index="2">
+ <div class="spread-num">03</div>
+ <div class="s3-layout" style="height:100%">
+ <div class="s3-hero">
+ <svg viewBox="0 0 700 900" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position:absolute;inset:0">
+ <defs>
+ <pattern id="damaskUnit" x="0" y="0" width="120" height="160" patternUnits="userSpaceOnUse">
+ <!-- large medallion -->
+ <ellipse cx="60" cy="80" rx="44" ry="58" fill="none" stroke="#6a3020" stroke-width="1.2"/>
+ <ellipse cx="60" cy="80" rx="34" ry="46" fill="#3a1810" opacity=".6"/>
+ <ellipse cx="60" cy="80" rx="24" ry="32" fill="none" stroke="#8a4030" stroke-width=".8"/>
+ <!-- central motif -->
+ <path d="M60 48 L66 68 L84 68 L70 80 L76 100 L60 88 L44 100 L50 80 L36 68 L54 68 Z" fill="#6a3020" opacity=".7"/>
+ <!-- diamond corners -->
+ <rect x="52" y="10" width="16" height="16" fill="#4a2018" transform="rotate(45,60,18)" opacity=".5"/>
+ <rect x="52" y="134" width="16" height="16" fill="#4a2018" transform="rotate(45,60,142)" opacity=".5"/>
+ <rect x="-8" y="72" width="16" height="16" fill="#4a2018" transform="rotate(45,0,80)" opacity=".5"/>
+ <rect x="112" y="72" width="16" height="16" fill="#4a2018" transform="rotate(45,120,80)" opacity=".5"/>
+ <!-- acanthus leaves suggestion -->
+ <path d="M60 26 Q68 40 60 54 Q52 40 60 26" fill="#6a3020" opacity=".45"/>
+ <path d="M60 106 Q68 120 60 134 Q52 120 60 106" fill="#6a3020" opacity=".45"/>
+ <path d="M16 80 Q30 72 44 80 Q30 88 16 80" fill="#6a3020" opacity=".45"/>
+ <path d="M76 80 Q90 72 104 80 Q90 88 76 80" fill="#6a3020" opacity=".45"/>
+ </pattern>
+ <linearGradient id="moodVig" x1="0" y1="0" x2="1" y2="1">
+ <stop offset="0%" stop-color="#2a1208" stop-opacity=".9"/>
+ <stop offset="100%" stop-color="#1a0c06" stop-opacity=".5"/>
+ </linearGradient>
+ </defs>
+ <rect width="700" height="900" fill="#1e0e08"/>
+ <rect width="700" height="900" fill="url(#damaskUnit)" opacity=".8"/>
+ <!-- deep jewel overlay -->
+ <rect width="700" height="900" fill="#3a1a10" opacity=".3"/>
+ <!-- gold shimmer glaze -->
+ <rect width="700" height="900" fill="#c9a961" opacity=".06"/>
+ <!-- edge vignette -->
+ <radialGradient id="moodRadial" cx="50%" cy="50%" r="60%">
+ <stop offset="0%" stop-color="transparent"/>
+ <stop offset="100%" stop-color="#0a0604" stop-opacity=".75"/>
+ </radialGradient>
+ <rect width="700" height="900" fill="url(#moodRadial)"/>
+ </svg>
+ </div>
+ <div class="s3-content">
+ <div class="tagline reveal d1">Story Three</div>
+ <h2 class="headline reveal d2">Moody<br>Maximalist</h2>
+ <span class="rule reveal d3"></span>
+ <p class="body-copy reveal d4">In darkness, pattern reveals its full power. Oxblood damask, smoked jewel velvets, and gilded acanthus scrollwork — for rooms that command absolute attention and refuse to whisper.</p>
+ <span class="rule reveal d4" style="opacity:.15"></span>
+ <div class="palette-strip reveal d4" style="margin-top:8px;border-radius:2px;overflow:hidden">
+ <div class="swatch" style="background:#6a1a10" data-name="Oxblood"></div>
+ <div class="swatch" style="background:#1e0e08" data-name="Ebony"></div>
+ <div class="swatch" style="background:#c9a961" data-name="Gilt"></div>
+ <div class="swatch" style="background:#3a2040" data-name="Aubergine"></div>
+ <div class="swatch" style="background:#4a2818" data-name="Tobacco"></div>
+ </div>
+ <div class="pattern-frame reveal d5" style="margin-top:18px;width:88px;height:88px">
+ <svg viewBox="0 0 88 88" width="88" height="88" xmlns="http://www.w3.org/2000/svg">
+ <rect width="88" height="88" fill="#1e0e08"/>
+ <rect width="88" height="88" fill="url(#damaskUnit)" opacity=".9"/>
+ <rect width="88" height="88" fill="none" stroke="#c9a961" stroke-width=".5" opacity=".5"/>
+ </svg>
+ </div>
+ <div class="pattern-label reveal d5">Midnight Damask — No. 33</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- ══ SPREAD 4: ART DECO ══ -->
+ <div class="slide s4" data-index="3">
+ <div class="spread-num">04</div>
+ <div class="s4-frame"></div>
+ <!-- Full-bleed deco geometry bg -->
+ <svg viewBox="0 0 1400 900" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position:absolute;inset:0;z-index:0">
+ <defs>
+ <pattern id="decoGrid" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
+ <!-- radiating fan lines -->
+ <line x1="50" y1="50" x2="0" y2="0" stroke="#c9a961" stroke-width=".4" opacity=".3"/>
+ <line x1="50" y1="50" x2="100" y2="0" stroke="#c9a961" stroke-width=".4" opacity=".3"/>
+ <line x1="50" y1="50" x2="0" y2="100" stroke="#c9a961" stroke-width=".4" opacity=".2"/>
+ <line x1="50" y1="50" x2="100" y2="100" stroke="#c9a961" stroke-width=".4" opacity=".2"/>
+ <circle cx="50" cy="50" r="30" fill="none" stroke="#c9a961" stroke-width=".3" opacity=".2"/>
+ <circle cx="50" cy="50" r="18" fill="none" stroke="#c9a961" stroke-width=".25" opacity=".18"/>
+ <rect x="35" y="35" width="30" height="30" fill="none" stroke="#c9a961" stroke-width=".25" opacity=".15" transform="rotate(45,50,50)"/>
+ </pattern>
+ <linearGradient id="decoFade" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="#0e0c08"/>
+ <stop offset="50%" stop-color="#1a1408"/>
+ <stop offset="100%" stop-color="#0e0c08"/>
+ </linearGradient>
+ </defs>
+ <rect width="1400" height="900" fill="url(#decoFade)"/>
+ <rect width="1400" height="900" fill="url(#decoGrid)"/>
+ <!-- sunburst at center -->
+ <g transform="translate(700,450)" opacity=".12">
+ <line x1="0" y1="-320" x2="0" y2="320" stroke="#c9a961" stroke-width="1"/>
+ <line x1="-320" y1="0" x2="320" y2="0" stroke="#c9a961" stroke-width="1"/>
+ <line x1="-226" y1="-226" x2="226" y2="226" stroke="#c9a961" stroke-width=".7"/>
+ <line x1="226" y1="-226" x2="-226" y2="226" stroke="#c9a961" stroke-width=".7"/>
+ <circle r="120" fill="none" stroke="#c9a961" stroke-width="1.5"/>
+ <circle r="180" fill="none" stroke="#c9a961" stroke-width=".8"/>
+ <circle r="260" fill="none" stroke="#c9a961" stroke-width=".5"/>
+ </g>
+ <!-- stepped arch at top/bottom -->
+ <rect x="0" y="0" width="1400" height="3" fill="#c9a961" opacity=".4"/>
+ <rect x="0" y="897" width="1400" height="3" fill="#c9a961" opacity=".4"/>
+ <rect x="0" y="8" width="1400" height="1" fill="#c9a961" opacity=".2"/>
+ <rect x="0" y="890" width="1400" height="1" fill="#c9a961" opacity=".2"/>
+ </svg>
+ <!-- Editorial content on top -->
+ <div class="s4-layout" style="position:relative;z-index:2">
+ <div class="tagline reveal d1">Story Four</div>
+ <h2 class="headline reveal d2">Art Deco</h2>
+ <span class="rule reveal d3"></span>
+ <p class="body-copy reveal d4">The geometry of ambition. Sunburst veneers, lacquered chevrons, and the cool authority of gilded exactitude — a style that enshrines the machine age in beauty, and refuses to age itself.</p>
+ <div class="palette-strip reveal d4" style="margin-top:24px;border-radius:2px;overflow:hidden;max-width:360px;margin-left:auto;margin-right:auto">
+ <div class="swatch" style="background:#c9a961" data-name="Gilt"></div>
+ <div class="swatch" style="background:#0e0c08" data-name="Lacquer"></div>
+ <div class="swatch" style="background:#e8dfc8" data-name="Ivory"></div>
+ <div class="swatch" style="background:#2a2010" data-name="Ebonised"></div>
+ <div class="swatch" style="background:#8a7840" data-name="Bronze"></div>
+ </div>
+ <div style="display:flex;flex-direction:column;align-items:center;margin-top:22px">
+ <div class="pattern-frame reveal d5" style="width:80px;height:80px">
+ <svg viewBox="0 0 80 80" width="80" height="80" xmlns="http://www.w3.org/2000/svg">
+ <rect width="80" height="80" fill="#12100a"/>
+ <rect width="80" height="80" fill="url(#decoGrid)"/>
+ <!-- central small motif -->
+ <rect x="28" y="28" width="24" height="24" fill="none" stroke="#c9a961" stroke-width="1" transform="rotate(45,40,40)" opacity=".7"/>
+ <circle cx="40" cy="40" r="8" fill="none" stroke="#c9a961" stroke-width=".8" opacity=".6"/>
+ <rect width="80" height="80" fill="none" stroke="#c9a961" stroke-width=".5" opacity=".4"/>
+ </svg>
+ </div>
+ <div class="pattern-label reveal d5">Sunburst Geo — No. 44</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- ══ SPREAD 5: CHINOISERIE ══ -->
+ <div class="slide s5" data-index="4">
+ <div class="spread-num">05</div>
+ <div class="s5-layout" style="height:100%">
+ <div class="s5-content">
+ <div class="tagline reveal d1">Story Five</div>
+ <h2 class="headline reveal d2">Chin­oiserie</h2>
+ <span class="rule reveal d3"></span>
+ <p class="body-copy reveal d4">Hand-painted reverie — the imagined Orient of European romanticism. Jade pagodas in willow mist, silk-thin branches bearing blossom, and mandarin birds frozen mid-flight on rice-paper grounds.</p>
+ <span class="rule reveal d4" style="opacity:.2"></span>
+ <div class="palette-strip reveal d4" style="margin-top:8px;border-radius:2px;overflow:hidden">
+ <div class="swatch" style="background:#f0ebe0" data-name="Rice Paper"></div>
+ <div class="swatch" style="background:#5c7a4a" data-name="Jade"></div>
+ <div class="swatch" style="background:#8a4830" data-name="Cinnabar"></div>
+ <div class="swatch" style="background:#7a9098" data-name="Celadon"></div>
+ <div class="swatch" style="background:#c8a040" data-name="Saffron"></div>
+ </div>
+ <div class="pattern-frame reveal d5" style="margin-top:18px;width:88px;height:88px">
+ <svg viewBox="0 0 88 88" width="88" height="88" xmlns="http://www.w3.org/2000/svg">
+ <rect width="88" height="88" fill="#f0ebe0"/>
+ <!-- branch -->
+ <path d="M10 80 Q30 60 44 40 Q55 24 60 10" fill="none" stroke="#5c7a4a" stroke-width="1.8"/>
+ <path d="M44 40 Q55 38 65 30" fill="none" stroke="#5c7a4a" stroke-width="1.2"/>
+ <path d="M30 60 Q20 55 12 48" fill="none" stroke="#5c7a4a" stroke-width="1.2"/>
+ <!-- blossoms -->
+ <circle cx="62" cy="10" r="5" fill="#e88878" opacity=".8"/>
+ <circle cx="60" cy="10" r="3" fill="none" stroke="#8a4830" stroke-width=".8"/>
+ <circle cx="68" cy="28" r="4" fill="#e88878" opacity=".7"/>
+ <circle cx="58" cy="22" r="3" fill="#f0c0b0" opacity=".6"/>
+ <!-- bird suggestion -->
+ <ellipse cx="22" cy="44" rx="10" ry="5" fill="#5c7a4a" opacity=".5" transform="rotate(-15,22,44)"/>
+ <ellipse cx="30" cy="42" rx="4" ry="2.5" fill="#c8a040" opacity=".6" transform="rotate(-15,30,42)"/>
+ <!-- pagoda distant -->
+ <rect x="70" y="55" width="14" height="20" fill="#7a9098" opacity=".25"/>
+ <polygon points="70,55 84,55 77,48" fill="#7a9098" opacity=".25"/>
+ <rect width="88" height="88" fill="none" stroke="#5c7a4a" stroke-width=".5" opacity=".3"/>
+ </svg>
+ </div>
+ <div class="pattern-label reveal d5">Willow Mist — No. 21</div>
+ </div>
+ <div class="s5-hero">
+ <svg viewBox="0 0 700 900" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position:absolute;inset:0">
+ <defs>
+ <linearGradient id="chinoGrad" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="#e8f0e8"/>
+ <stop offset="100%" stop-color="#f0ebe0"/>
+ </linearGradient>
+ </defs>
+ <rect width="700" height="900" fill="url(#chinoGrad)"/>
+ <!-- large repeating branches -->
+ <path d="M80 900 Q160 700 220 500 Q260 360 300 200 Q330 80 350 0" fill="none" stroke="#5c7a4a" stroke-width="2.5" opacity=".55"/>
+ <path d="M220 500 Q280 480 340 440" fill="none" stroke="#5c7a4a" stroke-width="1.8" opacity=".5"/>
+ <path d="M160 700 Q110 680 70 640" fill="none" stroke="#5c7a4a" stroke-width="1.5" opacity=".45"/>
+ <path d="M300 200 Q360 190 420 160" fill="none" stroke="#5c7a4a" stroke-width="1.5" opacity=".45"/>
+ <!-- second branch tree -->
+ <path d="M550 900 Q530 750 510 580 Q490 420 520 260 Q540 140 560 0" fill="none" stroke="#5c7a4a" stroke-width="2" opacity=".4"/>
+ <path d="M510 580 Q450 560 400 540" fill="none" stroke="#5c7a4a" stroke-width="1.3" opacity=".35"/>
+ <!-- blossoms scattered -->
+ <circle cx="220" cy="500" r="9" fill="#e88878" opacity=".7"/>
+ <circle cx="218" cy="500" r="5" fill="none" stroke="#8a4830" stroke-width=".8"/>
+ <circle cx="340" cy="440" r="7" fill="#f0c0b0" opacity=".65"/>
+ <circle cx="300" cy="200" r="10" fill="#e88878" opacity=".75"/>
+ <circle cx="298" cy="200" r="6" fill="none" stroke="#8a4830" stroke-width=".8"/>
+ <circle cx="420" cy="160" r="7" fill="#f0c0b0" opacity=".6"/>
+ <circle cx="510" cy="580" r="8" fill="#e88878" opacity=".6"/>
+ <circle cx="520" cy="260" r="9" fill="#e88878" opacity=".65"/>
+ <!-- birds in flight -->
+ <g opacity=".6" transform="translate(380,320)">
+ <ellipse cx="0" cy="0" rx="16" ry="7" fill="#5c7a4a" transform="rotate(-20)"/>
+ <ellipse cx="20" cy="-2" rx="6" ry="3" fill="#c8a040" transform="rotate(-20)"/>
+ <path d="M-16,0 Q-26,-10 -34,-6" fill="none" stroke="#5c7a4a" stroke-width="1.5"/>
+ <path d="M-16,0 Q-20,10 -12,14" fill="none" stroke="#5c7a4a" stroke-width="1.5"/>
+ </g>
+ <g opacity=".4" transform="translate(460,420)">
+ <ellipse cx="0" cy="0" rx="12" ry="5" fill="#5c7a4a" transform="rotate(-15)"/>
+ <ellipse cx="14" cy="-1" rx="4" ry="2" fill="#8a4830" transform="rotate(-15)"/>
+ </g>
+ <!-- pagoda distant -->
+ <g opacity=".25" transform="translate(580,600)">
+ <rect x="-24" y="-60" width="48" height="60" fill="#7a9098"/>
+ <rect x="-30" y="-70" width="60" height="12" fill="#5c7a4a"/>
+ <rect x="-36" y="-80" width="72" height="12" fill="#7a9098"/>
+ <polygon points="-20,-80 20,-80 0,-100" fill="#5c7a4a"/>
+ </g>
+ <!-- rice-paper texture overlay -->
+ <rect width="700" height="900" fill="#f4ede0" opacity=".12"/>
+ </svg>
+ </div>
+ </div>
+ </div>
+
+ <!-- ══ SPREAD 6: MODERN MINIMAL ══ -->
+ <div class="slide s6" data-index="5">
+ <div class="spread-num">06</div>
+ <div class="s6-layout" style="height:100%">
+ <div class="s6-content">
+ <div style="flex:1"></div>
+ <div>
+ <div class="tagline reveal d1">Story Six</div>
+ <h2 class="headline reveal d2">Modern<br>Minimal</h2>
+ <span class="rule reveal d3"></span>
+ <p class="body-copy reveal d4">Restraint as the highest form of luxury. Textured linen grounds, micro-stripe grasscloths, and the precise breath of negative space — interiors that speak in whispers and are heard across any room.</p>
+ </div>
+ <div style="padding-bottom:clamp(48px,6vh,88px)">
+ <div class="palette-strip reveal d4" style="margin-top:28px;border-radius:2px;overflow:hidden">
+ <div class="swatch" style="background:#f9f8f6" data-name="Chalk"></div>
+ <div class="swatch" style="background:#d8d4cc" data-name="Linen"></div>
+ <div class="swatch" style="background:#a8a098" data-name="Stone"></div>
+ <div class="swatch" style="background:#636058" data-name="Graphite"></div>
+ <div class="swatch" style="background:#1c1a17" data-name="Onyx"></div>
+ </div>
+ <div class="pattern-frame reveal d5" style="margin-top:16px;width:88px;height:88px">
+ <svg viewBox="0 0 88 88" width="88" height="88" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <pattern id="linenWeave" x="0" y="0" width="8" height="8" patternUnits="userSpaceOnUse">
+ <rect width="8" height="8" fill="#e8e4de"/>
+ <line x1="0" y1="0" x2="8" y2="0" stroke="#d0ccc4" stroke-width="1.2"/>
+ <line x1="0" y1="4" x2="8" y2="4" stroke="#dedad4" stroke-width=".8"/>
+ <line x1="0" y1="0" x2="0" y2="8" stroke="#ccc8c0" stroke-width="1"/>
+ <line x1="4" y1="0" x2="4" y2="8" stroke="#d8d4cc" stroke-width=".6"/>
+ </pattern>
+ </defs>
+ <rect width="88" height="88" fill="url(#linenWeave)"/>
+ <rect width="88" height="88" fill="none" stroke="#a8a098" stroke-width=".5" opacity=".5"/>
+ </svg>
+ </div>
+ <div class="pattern-label reveal d5">Natural Linen — No. 02</div>
+ </div>
+ </div>
+ <div class="s6-hero">
+ <svg viewBox="0 0 700 900" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position:absolute;inset:0">
+ <defs>
+ <pattern id="minStripe" x="0" y="0" width="1" height="20" patternUnits="userSpaceOnUse">
+ <rect width="1" height="20" fill="#e0dcd4"/>
+ <rect width="1" height="1" y="10" fill="#ccc8c0"/>
+ </pattern>
+ <pattern id="minGrid" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse">
+ <rect width="40" height="40" fill="#ebebea" />
+ <line x1="0" y1="0" x2="40" y2="0" stroke="#d8d4cc" stroke-width=".5"/>
+ <line x1="0" y1="0" x2="0" y2="40" stroke="#d8d4cc" stroke-width=".5"/>
+ </pattern>
+ </defs>
+ <rect width="700" height="900" fill="#e8e5e0"/>
+ <!-- vertical micro-stripe texture -->
+ <rect width="700" height="900" fill="url(#minStripe)" opacity=".5"/>
+ <!-- horizontal bands — architectural rhythm -->
+ <rect x="0" y="200" width="700" height="1" fill="#ccc8c0" opacity=".6"/>
+ <rect x="0" y="400" width="700" height="1" fill="#ccc8c0" opacity=".5"/>
+ <rect x="0" y="600" width="700" height="1" fill="#ccc8c0" opacity=".4"/>
+ <rect x="0" y="240" width="700" height=".5" fill="#d8d4cc" opacity=".35"/>
+ <rect x="0" y="440" width="700" height=".5" fill="#d8d4cc" opacity=".3"/>
+ <!-- floating rectangular forms -->
+ <rect x="80" y="180" width="180" height="260" fill="#f0ede8" opacity=".5"/>
+ <rect x="420" y="340" width="200" height="300" fill="#dedad4" opacity=".45"/>
+ <rect x="160" y="580" width="280" height="160" fill="#e8e4de" opacity=".4"/>
+ <!-- accent line -->
+ <rect x="0" y="450" width="700" height="2" fill="#c9a961" opacity=".18"/>
+ <!-- grid overlay subtle -->
+ <rect width="700" height="900" fill="url(#minGrid)" opacity=".12"/>
+ <!-- light gradient top -->
+ <linearGradient id="minLight" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="#fff" stop-opacity=".25"/>
+ <stop offset="50%" stop-color="transparent"/>
+ </linearGradient>
+ <rect width="700" height="900" fill="url(#minLight)"/>
+ </svg>
+ <div class="s6-accent-line"></div>
+ </div>
+ </div>
+ </div>
+
+ </div><!-- /slides-track -->
+</div><!-- /viewport -->
+
+<script>
+(function(){
+ 'use strict';
+
+ const TOTAL = 6;
+ const STORIES = [
+ {title:'Grandmillennial', sub:'Story One'},
+ {title:'Coastal', sub:'Story Two'},
+ {title:'Moody Maximalist',sub:'Story Three'},
+ {title:'Art Deco', sub:'Story Four'},
+ {title:'Chinoiserie', sub:'Story Five'},
+ {title:'Modern Minimal', sub:'Story Six'},
+ ];
+
+ let current = 0;
+ let isAnimating = false;
+ let touchStartX = 0, touchStartY = 0;
+
+ const track = document.getElementById('track');
+ const dotsEl = document.getElementById('dots');
+ const bar = document.getElementById('progressBar');
+ const tocOverlay = document.getElementById('tocOverlay');
+ const tocList = document.getElementById('tocList');
+ const prevBtn = document.getElementById('arrowPrev');
+ const nextBtn = document.getElementById('arrowNext');
+
+ // ── BUILD DOTS ──
+ for(let i=0;i<TOTAL;i++){
+ const d=document.createElement('div');
+ d.className='dot'+(i===0?' active':'');
+ d.setAttribute('aria-label','Go to spread '+(i+1));
+ d.setAttribute('role','button');
+ d.setAttribute('tabindex','0');
+ d.onclick=()=>goTo(i);
+ d.onkeydown=e=>{if(e.key==='Enter'||e.key===' ')goTo(i)};
+ dotsEl.appendChild(d);
+ }
+
+ // ── BUILD TOC ──
+ STORIES.forEach((s,i)=>{
+ const li=document.createElement('li');
+ li.className='toc-item';
+ li.innerHTML=`<span class="toc-n">0${i+1}</span><span class="toc-item-title">${s.title}</span><span class="toc-sub">${s.sub}</span>`;
+ li.onclick=()=>{goTo(i);closeToc()};
+ li.setAttribute('tabindex','0');
+ li.onkeydown=e=>{if(e.key==='Enter')li.click()};
+ tocList.appendChild(li);
+ });
+
+ // ── GO TO SLIDE ──
+ window.goTo=function(idx){
+ if(isAnimating) return;
+ if(idx<0||idx>=TOTAL) return;
+ isAnimating=true;
+ clearReveals(current);
+ current=idx;
+ track.style.transform=`translateX(-${(100/6)*current}%)`;
+ updateUI();
+ // Trigger reveals after transition starts
+ setTimeout(()=>{triggerReveals(current)},120);
+ setTimeout(()=>{isAnimating=false},820);
+ };
+
+ function updateUI(){
+ // dots
+ dotsEl.querySelectorAll('.dot').forEach((d,i)=>d.classList.toggle('active',i===current));
+ // progress bar
+ bar.style.width=((current+1)/TOTAL*100)+'%';
+ // arrows
+ prevBtn.style.opacity=current===0?'0.2':'0.6';
+ nextBtn.style.opacity=current===TOTAL-1?'0.2':'0.6';
+ prevBtn.style.pointerEvents=current===0?'none':'auto';
+ nextBtn.style.pointerEvents=current===TOTAL-1?'none':'auto';
+ }
+
+ function clearReveals(idx){
+ const slide=track.children[idx];
+ slide.querySelectorAll('.reveal').forEach(el=>{
+ el.classList.remove('in');
+ });
+ }
+
+ function triggerReveals(idx){
+ const slide=track.children[idx];
+ slide.querySelectorAll('.reveal').forEach(el=>{
+ // force reflow
+ void el.offsetWidth;
+ el.classList.add('in');
+ });
+ }
+
+ // ── PARALLAX ──
+ function applyParallax(e){
+ const slide=track.children[current];
+ const hero=slide.querySelector('.parallax-hero');
+ if(!hero) return;
+ const speed=parseFloat(hero.dataset.speed||'.03');
+ const cx=window.innerWidth/2, cy=window.innerHeight/2;
+ const dx=(e.clientX-cx)*speed*60;
+ const dy=(e.clientY-cy)*speed*40;
+ hero.style.transform=`translate(${dx}px,${dy}px) scale(1.06)`;
+ }
+ document.addEventListener('mousemove',applyParallax,{passive:true});
+
+ // ── KEYBOARD ──
+ document.addEventListener('keydown',e=>{
+ if(tocOverlay.classList.contains('open')){
+ if(e.key==='Escape') closeToc();
+ return;
+ }
+ if(e.key==='ArrowRight'||e.key==='ArrowDown') goTo(current+1);
+ else if(e.key==='ArrowLeft'||e.key==='ArrowUp') goTo(current-1);
+ else if(e.key==='Home') goTo(0);
+ else if(e.key==='End') goTo(TOTAL-1);
+ });
+
+ // ── TOUCH ──
+ document.addEventListener('touchstart',e=>{
+ touchStartX=e.touches[0].clientX;
+ touchStartY=e.touches[0].clientY;
+ },{passive:true});
+ document.addEventListener('touchend',e=>{
+ const dx=e.changedTouches[0].clientX-touchStartX;
+ const dy=e.changedTouches[0].clientY-touchStartY;
+ if(Math.abs(dx)>Math.abs(dy)&&Math.abs(dx)>40){
+ goTo(dx<0?current+1:current-1);
+ }
+ },{passive:true});
+
+ // ── TOC ──
+ window.openToc=function(){
+ tocOverlay.classList.add('open');
+ tocOverlay.querySelector('.toc-close').focus();
+ };
+ window.closeToc=function(){
+ tocOverlay.classList.remove('open');
+ };
+ tocOverlay.addEventListener('click',e=>{
+ if(e.target===tocOverlay) closeToc();
+ });
+
+ // ── WHEEL ──
+ let wheelCooldown=false;
+ document.addEventListener('wheel',e=>{
+ if(wheelCooldown||tocOverlay.classList.contains('open')) return;
+ if(Math.abs(e.deltaX)>Math.abs(e.deltaY)){
+ goTo(e.deltaX>30?current+1:e.deltaX<-30?current-1:current);
+ } else if(Math.abs(e.deltaY)>40){
+ goTo(e.deltaY>0?current+1:current-1);
+ }
+ wheelCooldown=true;
+ setTimeout(()=>{wheelCooldown=false},900);
+ },{passive:true});
+
+ // ── INIT ──
+ updateUI();
+ setTimeout(()=>triggerReveals(0),200);
+
+})();
+</script>
+</body>
+</html>
← a0f576c Agent-driven game: DW Pattern Match (frontend-developer) — 8
·
back to Model Arena
·
Agent-driven art toy: DW Damask Kaleidoscope (frontend-devel 71faf27 →