← back to Dw Style Quiz
index.html
958 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>What's Your Wallcovering Style? — Designer Wallcoverings</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="A five-tap editorial quiz to discover your wallcovering style — Traditional Damask, Modern Minimalist, Bohemian Maximalist, or Art Deco Glam. By Designer Wallcoverings." />
<meta property="og:title" content="What's Your Wallcovering Style?" />
<meta property="og:description" content="Five taps to your signature wall. A quiz by Designer Wallcoverings." />
<style>
:root {
--bg: #0d0d0f;
--text: #f5f2ea;
--muted: #8a8578;
--accent: #c9a961;
--radius-lg: 26px;
--radius-md: 18px;
--font-display: "Didot", "Bodoni MT", "Playfair Display", Georgia, serif;
--font-body: -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
--ease-out: cubic-bezier(.22, 1, .36, 1);
}
@keyframes fadeUp {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: none; }
}
@keyframes clipReveal {
from { opacity: 0; transform: scale(.965); filter: blur(6px); }
to { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes shimmer {
from { background-position: 200% 0; }
to { background-position: -200% 0; }
}
* { box-sizing: border-box; }
html, body {
margin: 0;
padding: 0;
background: radial-gradient(circle at top, #1d1d23 0, #050507 55%, #000 100%);
color: var(--text);
font-family: var(--font-body);
-webkit-font-smoothing: antialiased;
min-height: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 24px;
}
/* The 1080x1080 shareable canvas */
.frame {
position: relative;
width: min(92vmin, 1080px);
height: min(92vmin, 1080px);
background: radial-gradient(circle at 10% 0, #252531 0, #0b0b0d 40%, #050507 100%);
border-radius: 40px;
box-shadow: 0 26px 80px rgba(0, 0, 0, 0.65);
border: 1px solid rgba(255, 255, 255, 0.06);
overflow: hidden;
display: flex;
flex-direction: column;
padding: clamp(20px, 3.4vmin, 40px);
}
@media (max-width: 620px) {
body { padding: 0; }
.frame {
width: 100vw;
height: 100vh;
height: 100dvh;
border-radius: 0;
box-shadow: none;
border: none;
}
}
/* Chrome: brand + progress */
.chrome {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex: 0 0 auto;
}
.brand-lockup {
display: flex;
align-items: center;
gap: 10px;
letter-spacing: 0.16em;
text-transform: uppercase;
font-size: clamp(9px, 1.5vmin, 12px);
color: var(--muted);
}
.brand-mark {
width: clamp(16px, 2.4vmin, 22px);
height: clamp(16px, 2.4vmin, 22px);
border-radius: 999px;
border: 1px solid rgba(201, 169, 97, 0.6);
background: conic-gradient(from 210deg, rgba(255,255,255,0.12), rgba(201,169,97,0.65), rgba(125,106,69,0.4), rgba(0,0,0,0.85), rgba(255,255,255,0.12));
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
}
.brand-mark::after {
content: "";
width: 38%;
height: 38%;
border-radius: 999px;
background: radial-gradient(circle at 30% 0, #f5f2ea 0, #e4d4ae 40%, #8d6a2b 100%);
}
.brand-name b { color: var(--text); font-weight: 600; }
.steps {
display: inline-flex;
align-items: center;
gap: 5px;
}
.steps-dot {
width: 4px;
height: clamp(10px, 1.8vmin, 14px);
border-radius: 999px;
background: rgba(255, 255, 255, 0.1);
overflow: hidden;
position: relative;
}
.steps-dot::after {
content: "";
position: absolute;
inset: 0;
transform-origin: bottom;
transform: scaleY(0);
background: linear-gradient(to top, #c9a961, #f5e3b7);
transition: transform 320ms var(--ease-out);
}
.steps-dot.on::after { transform: scaleY(1); }
/* Stage: the part that swaps screens. flex:1 gives it real height. */
.stage {
position: relative;
flex: 1 1 auto;
min-height: 0;
margin: clamp(14px, 2.4vmin, 26px) 0;
}
.screen {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
opacity: 0;
pointer-events: none;
transform: translateY(16px);
transition: opacity 340ms var(--ease-out), transform 340ms var(--ease-out);
}
.screen.active {
opacity: 1;
pointer-events: auto;
transform: none;
}
/* ---- Intro screen ---- */
.intro {
justify-content: center;
text-align: center;
gap: clamp(14px, 2.4vmin, 26px);
align-items: center;
}
.eyebrow {
font-size: clamp(10px, 1.6vmin, 13px);
text-transform: uppercase;
letter-spacing: 0.26em;
color: var(--accent);
}
.intro-title {
font-family: var(--font-display);
font-size: clamp(38px, 8.6vmin, 92px);
line-height: 0.98;
letter-spacing: -0.03em;
text-transform: uppercase;
margin: 0;
}
.intro-title .em { color: var(--accent); font-style: italic; }
.intro-sub {
font-size: clamp(13px, 2.1vmin, 18px);
color: rgba(245, 242, 234, 0.72);
max-width: 30ch;
line-height: 1.55;
margin: 0;
}
.intro-swatches {
display: flex;
gap: clamp(8px, 1.4vmin, 14px);
margin-top: 4px;
}
.intro-swatches .chip {
width: clamp(44px, 8vmin, 92px);
height: clamp(44px, 8vmin, 92px);
border-radius: 14px;
overflow: hidden;
border: 1px solid rgba(255,255,255,0.1);
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.intro-swatches .chip > div { width: 100%; height: 100%; }
/* ---- Question screens ---- */
.q-head {
display: flex;
align-items: center;
gap: 10px;
font-size: clamp(9px, 1.5vmin, 12px);
text-transform: uppercase;
letter-spacing: 0.18em;
color: var(--muted);
margin-bottom: clamp(6px, 1vmin, 10px);
flex: 0 0 auto;
}
.q-head .rule { flex: 1; height: 1px; background: linear-gradient(to right, rgba(201,169,97,0.7), transparent); }
.q-title {
font-family: var(--font-display);
font-size: clamp(22px, 4.2vmin, 44px);
line-height: 1.06;
letter-spacing: -0.02em;
margin: 0 0 clamp(12px, 2vmin, 24px);
flex: 0 0 auto;
}
.answers {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: clamp(8px, 1.5vmin, 16px);
flex: 1 1 auto;
min-height: 0;
}
.answer {
position: relative;
border-radius: var(--radius-md);
padding: clamp(10px, 1.6vmin, 16px);
background: radial-gradient(circle at 0 0, rgba(255,255,255,0.07), transparent 55%), linear-gradient(145deg, #15151b, #101016);
border: 1px solid rgba(255, 255, 255, 0.08);
color: inherit;
font: inherit;
text-align: left;
cursor: pointer;
overflow: hidden;
display: flex;
flex-direction: column;
gap: clamp(6px, 1vmin, 10px);
transition: transform 200ms var(--ease-out), box-shadow 200ms var(--ease-out), border-color 200ms var(--ease-out);
}
.answer:hover, .answer:focus-visible {
transform: translateY(-3px);
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.7);
border-color: rgba(201, 169, 97, 0.7);
outline: none;
}
.answer:active { transform: translateY(-1px) scale(0.99); }
.answer .swatch {
position: relative;
border-radius: 12px;
overflow: hidden;
flex: 1 1 auto;
min-height: clamp(52px, 9vmin, 120px);
border: 1px solid rgba(255, 255, 255, 0.08);
}
.answer .swatch > div { position: absolute; inset: 0; }
.answer .swatch-tag {
position: absolute;
right: 7px;
bottom: 7px;
font-size: clamp(8px, 1.3vmin, 10px);
text-transform: uppercase;
letter-spacing: 0.16em;
padding: 3px 7px;
border-radius: 999px;
background: rgba(10, 10, 14, 0.78);
border: 1px solid rgba(255, 255, 255, 0.22);
}
.answer .a-label {
font-size: clamp(12px, 1.9vmin, 16px);
letter-spacing: 0.02em;
color: rgba(245, 242, 234, 0.92);
font-weight: 500;
}
.answer .a-meta {
font-size: clamp(10px, 1.5vmin, 12.5px);
color: var(--muted);
line-height: 1.4;
}
@media (max-width: 620px) {
.answer .a-meta { display: none; }
}
/* ---- Result screen ---- */
/* Animation only fires when active — otherwise `both` fill-mode would
hold the screen at opacity:1 on load and bleed it over the intro. */
.result.active {
animation: clipReveal 0.7s var(--ease-out) both;
}
.result-inner {
flex: 1 1 auto;
display: grid;
grid-template-rows: auto 1fr auto;
gap: clamp(12px, 2vmin, 22px);
min-height: 0;
}
.result-top {
display: flex;
align-items: center;
justify-content: space-between;
font-size: clamp(9px, 1.5vmin, 12px);
text-transform: uppercase;
letter-spacing: 0.18em;
color: var(--muted);
}
.result-top .tag {
display: inline-flex;
align-items: center;
gap: 7px;
padding: 4px 10px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.16);
background: linear-gradient(135deg, rgba(10,10,14,0.9), rgba(0,0,0,1));
}
.result-top .tag .dot {
width: 8px; height: 8px; border-radius: 50%;
background: conic-gradient(from 160deg, #c9a961, #f7e5bd, #7d6a45, #c9a961);
}
.result-body {
display: grid;
grid-template-columns: 1.05fr 1fr;
gap: clamp(14px, 2.4vmin, 26px);
min-height: 0;
}
@media (max-width: 620px) {
.result-body { grid-template-columns: 1fr; grid-template-rows: minmax(120px, 1fr) auto; }
}
.result-pattern {
position: relative;
border-radius: var(--radius-md);
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.08);
min-height: 0;
}
.result-pattern > div { position: absolute; inset: 0; }
.result-pattern .p-tag {
position: absolute;
left: 10px; top: 10px;
z-index: 2;
font-size: clamp(8px, 1.3vmin, 10px);
text-transform: uppercase;
letter-spacing: 0.16em;
padding: 3px 8px;
border-radius: 999px;
background: rgba(10, 10, 14, 0.78);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.result-info {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 0;
}
.result-cat {
font-size: clamp(10px, 1.6vmin, 13px);
text-transform: uppercase;
letter-spacing: 0.2em;
color: var(--accent);
margin-bottom: 6px;
}
.result-title {
font-family: var(--font-display);
font-size: clamp(26px, 5vmin, 54px);
line-height: 1.02;
letter-spacing: -0.02em;
text-transform: uppercase;
margin: 0 0 clamp(8px, 1.4vmin, 14px);
}
.result-rule {
width: 40px; height: 2px;
background: linear-gradient(to right, var(--accent), transparent);
margin-bottom: clamp(8px, 1.4vmin, 14px);
}
.result-desc {
font-size: clamp(12px, 1.9vmin, 16px);
color: rgba(245, 242, 234, 0.82);
line-height: 1.55;
margin: 0 0 clamp(10px, 1.8vmin, 18px);
}
.result-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.result-tags .t {
font-size: clamp(9px, 1.4vmin, 11px);
text-transform: uppercase;
letter-spacing: 0.14em;
padding: 4px 9px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.16);
background: linear-gradient(135deg, #15151b, #0f0f14);
color: rgba(245, 242, 234, 0.9);
}
/* Buttons */
.actions {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.btn {
border-radius: 999px;
border: 1px solid rgba(255,255,255,0.14);
padding: clamp(9px, 1.5vmin, 14px) clamp(16px, 2.4vmin, 26px);
font-size: clamp(10px, 1.6vmin, 13px);
text-transform: uppercase;
letter-spacing: 0.2em;
background: transparent;
color: var(--text);
cursor: pointer;
font-family: var(--font-body);
transition: transform 180ms var(--ease-out), background 180ms var(--ease-out), border-color 180ms var(--ease-out);
white-space: nowrap;
}
.btn:hover { transform: translateY(-1px); border-color: rgba(255,255,255,0.35); }
.btn:active { transform: translateY(0); }
.btn-primary {
border: none;
color: #111015;
font-weight: 600;
background-image: linear-gradient(120deg, #c9a961, #f9e8bd, #7d6a45);
background-size: 180% 100%;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.55);
}
.btn-primary:hover { background-position: 100% 0; }
.btn-ghost { color: var(--muted); }
.btn-ghost:hover { color: var(--text); }
.begin-btn { margin-top: clamp(6px, 1.2vmin, 12px); }
/* Footer */
.footer {
display: flex;
align-items: center;
gap: 12px;
flex: 0 0 auto;
font-size: clamp(9px, 1.4vmin, 11px);
text-transform: uppercase;
letter-spacing: 0.18em;
color: var(--muted);
}
.progress-rail {
flex: 1;
height: 2px;
background: rgba(255, 255, 255, 0.1);
border-radius: 999px;
overflow: hidden;
}
.progress-bar {
height: 100%;
background: linear-gradient(to right, #c9a961, #f5e3b7);
transform-origin: left;
transform: scaleX(0);
transition: transform 340ms var(--ease-out);
}
.footer-logo { font-family: var(--font-display); letter-spacing: 0.28em; }
.footer-logo b { color: var(--accent); font-weight: 400; }
.hint {
font-size: clamp(9px, 1.4vmin, 12px);
color: var(--muted);
display: flex; align-items: center; gap: 8px;
margin-top: clamp(8px, 1.4vmin, 14px);
flex: 0 0 auto;
}
.hint .rule { width: 24px; height: 1px; background: linear-gradient(to right, rgba(201,169,97,0.7), transparent); }
/* Toast for share fallback */
.toast {
position: absolute;
left: 50%;
bottom: clamp(70px, 12vmin, 120px);
transform: translate(-50%, 12px);
background: rgba(15,15,19,0.96);
border: 1px solid rgba(201,169,97,0.4);
color: var(--text);
padding: 10px 18px;
border-radius: 999px;
font-size: clamp(10px, 1.5vmin, 13px);
letter-spacing: 0.04em;
opacity: 0;
pointer-events: none;
transition: opacity 260ms var(--ease-out), transform 260ms var(--ease-out);
z-index: 20;
box-shadow: 0 16px 40px rgba(0,0,0,0.6);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* ============ CSS PATTERN SWATCHES ============ */
.pat { width: 100%; height: 100%; }
/* Traditional Damask */
.pat-damask {
background:
radial-gradient(circle at 50% 18%, rgba(201,169,97,0.9) 0 2px, transparent 2px 13px),
repeating-radial-gradient(circle at 50% 40%, rgba(201,169,97,0.55) 0 1px, transparent 1px 11px),
repeating-conic-gradient(from 0deg, #17141d 0 15deg, #241f2c 15deg 30deg);
}
.pat-damask::before, .pat-damask::after {
content: ""; position: absolute; border-radius: 50%;
border: 1.5px solid rgba(201,169,97,0.7);
}
.pat-damask { position: relative; }
.pat-damask::before { inset: 14% 24%; }
.pat-damask::after { inset: 30% 38%; border-color: rgba(245,242,234,0.6); box-shadow: 0 0 22px rgba(201,169,97,0.6); }
/* Modern Minimalist */
.pat-minimal {
background:
linear-gradient(135deg, #14141b, #0a0a0e);
background-image:
linear-gradient(to right, rgba(245,242,234,0.09) 1px, transparent 1px),
linear-gradient(to bottom, rgba(245,242,234,0.05) 1px, transparent 1px),
linear-gradient(135deg, rgba(245,242,234,0.06) 25%, transparent 25% 50%, rgba(245,242,234,0.06) 50% 75%, transparent 75%);
background-size: 26px 26px, 26px 26px, 52px 52px;
}
.pat-minimal { position: relative; }
.pat-minimal::before {
content: ""; position: absolute; inset: 22% 20%;
border: 1px solid rgba(245,242,234,0.35);
border-radius: 4px;
}
/* Bohemian Maximalist */
.pat-maximal {
background:
radial-gradient(circle at 22% 26%, #f6d9a8 0 6%, transparent 6% 16%, #f6d9a8 16% 22%, transparent 22%),
radial-gradient(circle at 74% 30%, #d98168 0 6%, transparent 6% 15%, #d98168 15% 21%, transparent 21%),
radial-gradient(circle at 40% 78%, #6fae90 0 6%, transparent 6% 16%, #6fae90 16% 22%, transparent 22%),
radial-gradient(circle at 82% 80%, #b58bc4 0 5%, transparent 5% 14%, #b58bc4 14% 20%, transparent 20%),
conic-gradient(from 45deg, #2a1120, #1d1020, #131322, #182329, #2a1120);
background-size: 74px 74px, 74px 74px, 74px 74px, 74px 74px, 100% 100%;
}
/* Art Deco Glam */
.pat-deco {
background: linear-gradient(135deg, #16131d, #08060c);
}
.pat-deco { position: relative; }
.pat-deco::before {
content: ""; position: absolute; inset: 0;
background:
repeating-linear-gradient(90deg, transparent 0 18px, rgba(201,169,97,0.16) 18px 19px),
repeating-conic-gradient(from 0deg at 50% 100%, rgba(201,169,97,0.5) 0 6deg, transparent 6deg 18deg);
-webkit-mask-image: radial-gradient(circle at 50% 100%, black 0 62%, transparent 62%);
mask-image: radial-gradient(circle at 50% 100%, black 0 62%, transparent 62%);
}
.pat-deco::after {
content: ""; position: absolute; left: 26%; right: 26%; bottom: 8%; height: 46%;
border: 2px solid rgba(201,169,97,0.85);
border-bottom: none;
border-radius: 50% 50% 0 0;
}
</style>
</head>
<body>
<div class="frame" id="frame">
<!-- Chrome -->
<div class="chrome">
<div class="brand-lockup">
<span class="brand-mark"></span>
<span class="brand-name"><b>Designer</b> Wallcoverings</span>
</div>
<div class="steps" id="steps" aria-hidden="true"></div>
</div>
<!-- Stage -->
<div class="stage" id="stage" aria-live="polite">
<!-- Intro -->
<section class="screen intro active" data-screen="intro">
<div class="eyebrow">The Style Quiz</div>
<h1 class="intro-title">What's Your<br /><span class="em">Wallcovering</span><br />Style?</h1>
<p class="intro-sub">Five quick taps to discover the pattern that feels like home. Answer instinctively — your walls will thank you.</p>
<div class="intro-swatches" aria-hidden="true">
<div class="chip"><div class="pat pat-damask"></div></div>
<div class="chip"><div class="pat pat-minimal"></div></div>
<div class="chip"><div class="pat pat-maximal"></div></div>
<div class="chip"><div class="pat pat-deco"></div></div>
</div>
<button class="btn btn-primary begin-btn" id="beginBtn">Begin the Quiz</button>
</section>
<!-- Questions render here -->
<div id="questions"></div>
<!-- Result -->
<section class="screen result" data-screen="result">
<div class="result-inner">
<div class="result-top">
<span>1080 × 1080 · Screenshot & Share</span>
<span class="tag"><span class="dot"></span><span id="resShort">Your Wallcovering DNA</span></span>
</div>
<div class="result-body">
<div class="result-pattern">
<span class="p-tag">Pattern Match</span>
<div class="pat" id="resPattern"></div>
</div>
<div class="result-info">
<div class="result-cat" id="resCat">Modern Minimalist</div>
<h2 class="result-title" id="resTitle">Gallery-Quiet Walls</h2>
<div class="result-rule"></div>
<p class="result-desc" id="resDesc"></p>
<div class="result-tags" id="resTags"></div>
</div>
</div>
<div class="actions">
<a class="btn btn-primary" id="shopBtn" href="#" target="_blank" rel="noopener noreferrer">Shop this Style</a>
<button class="btn" id="shareBtn" type="button">Share</button>
<button class="btn btn-ghost" id="retakeBtn" type="button">Retake</button>
</div>
</div>
</section>
</div>
<!-- Footer -->
<div class="footer">
<div class="progress-rail"><div class="progress-bar" id="progressBar"></div></div>
<div class="footer-logo"><b>Designer</b> Wallcoverings</div>
</div>
<div class="toast" id="toast">Link copied — paste it anywhere.</div>
</div>
<script>
(function () {
"use strict";
// ---------- Data ----------
var QUESTIONS = [
{
kicker: "Q1 — Mood",
title: "How do you want your space to feel?",
options: [
{ score: "damask", pat: "pat-damask", tag: "Opulent Calm", label: "Timeless & grand", meta: "Candlelit dinners, heirloom silver, soft strings." },
{ score: "minimal", pat: "pat-minimal", tag: "Quiet Clarity", label: "Clean & composed", meta: "Sunlight, negative space, one perfect chair." },
{ score: "maximal", pat: "pat-maximal", tag: "Eclectic Joy", label: "Playful & collected", meta: "Layered textiles, travel finds, a story everywhere." },
{ score: "deco", pat: "pat-deco", tag: "Evening Glam", label: "Dramatic & polished", meta: "Velvet banquettes, champagne, city lights." }
]
},
{
kicker: "Q2 — Architecture",
title: "Which backdrop feels most like “home”?",
options: [
{ score: "minimal", pat: "pat-minimal", tag: "Gallery Loft", label: "Airy loft", meta: "Crisp lines, pale oak, soft architectural light." },
{ score: "damask", pat: "pat-damask", tag: "Townhouse", label: "Historic brownstone", meta: "Crown mouldings, marble mantels, library greens." },
{ score: "deco", pat: "pat-deco", tag: "Skyline Suite", label: "City penthouse", meta: "Metallic accents, skyline views, a bar cart." },
{ score: "maximal", pat: "pat-maximal", tag: "Artist Studio", label: "Sun-drenched studio", meta: "Plants, vintage rugs, a curated chaos." }
]
},
{
kicker: "Q3 — Pattern",
title: "Choose the pattern energy that draws you in.",
options: [
{ score: "damask", pat: "pat-damask", tag: "Heritage", label: "Ornate motifs", meta: "Scrolling florals, medallions, old-world romance." },
{ score: "minimal", pat: "pat-minimal", tag: "Precision", label: "Linear & graphic", meta: "Architectural stripes, grids, tonal shifts." },
{ score: "maximal", pat: "pat-maximal", tag: "Botanical", label: "Botanical & wild", meta: "Overscale florals, palms, a lush jungle vibe." },
{ score: "deco", pat: "pat-deco", tag: "Geometry", label: "Geometric glamour", meta: "Fans, arches, sharp metallic repeats." }
]
},
{
kicker: "Q4 — Palette",
title: "Which palette would you wake up to?",
options: [
{ score: "minimal", pat: "pat-minimal", tag: "Bone & Ink", label: "Soft neutrals", meta: "Ivories, warm greys, a hint of charcoal." },
{ score: "deco", pat: "pat-deco", tag: "Champagne", label: "Noir & metallic", meta: "Inky blacks, molten metals, candlelit warmth." },
{ score: "damask", pat: "pat-damask", tag: "Antique Gold", label: "Rich jewel tones", meta: "Sapphire, garnet, deep velvety neutrals." },
{ score: "maximal", pat: "pat-maximal", tag: "Sunset", label: "Sun-soaked brights", meta: "Terracotta, olive, ochre, saturated color." }
]
},
{
kicker: "Q5 — Lifestyle",
title: "Your Friday night at home looks like…",
options: [
{ score: "damask", pat: "pat-damask", tag: "Salon", label: "Slow dinner party", meta: "Linen tablecloths, candles, an endless playlist." },
{ score: "minimal", pat: "pat-minimal", tag: "Reset", label: "Solo reset", meta: "Fresh sheets, a face mask, a plumped pillow." },
{ score: "maximal", pat: "pat-maximal", tag: "Gather", label: "Friends & laughter", meta: "Board games, bold drinks, shuffle on." },
{ score: "deco", pat: "pat-deco", tag: "After Dark", label: "Cocktail hour", meta: "Shaken not stirred, a late-night movie." }
]
}
];
var RESULTS = {
damask: {
cat: "Traditional Damask", title: "Gilded Heritage Walls", pat: "pat-damask", short: "Old World, New Mood",
desc: "You gravitate toward rooms with history and a hint of ceremony. Ornate damask motifs, antique-gold inks, and tactile embossing turn your walls into a modern-day manor — romantic, refined, and endlessly photogenic.",
tags: ["Chandelier-ready", "Silk-inspired sheen", "Heirloom details"],
shop: "https://designerwallcoverings.com/search?q=damask"
},
minimal: {
cat: "Modern Minimalist", title: "Gallery-Quiet Walls", pat: "pat-minimal", short: "Quiet Luxury",
desc: "You breathe easiest in spaces that feel edited and intentional. Understated patterning, tonal shifts, and architectural lines create a soft backdrop that makes everything else in the room shine.",
tags: ["Soft contrast", "Architectural lines", "Museum-grade calm"],
shop: "https://designerwallcoverings.com/search?q=grasscloth"
},
maximal: {
cat: "Bohemian Maximalist", title: "Collected Story Walls", pat: "pat-maximal", short: "More Is More",
desc: "You curate spaces like you collect memories — boldly, joyfully, and without apology. Lush botanicals, layered prints, and rich, sun-warmed color turn every wall into a passport stamp.",
tags: ["Pattern-on-pattern", "Lush botanicals", "Global eclectic"],
shop: "https://designerwallcoverings.com/search?q=floral"
},
deco: {
cat: "Art Deco Glam", title: "Midnight Deco Walls", pat: "pat-deco", short: "Iconic Glamour",
desc: "You live for a little drama. Fan motifs, sharp geometrics, and metallic inks that catch the light just so. Your walls feel like the lobby of a grand hotel — always ready for the next cocktail hour.",
tags: ["Metallic accents", "Geometric glamour", "After-dark glow"],
shop: "https://designerwallcoverings.com/search?q=art+deco"
}
};
var TOTAL = QUESTIONS.length;
// ---------- State ----------
var scores = { damask: 0, minimal: 0, maximal: 0, deco: 0 };
var firstPick = null; // tie-breaker: honor the very first answer
var answered = 0;
// ---------- Elements ----------
var stage = document.getElementById("stage");
var questionsHost = document.getElementById("questions");
var stepsHost = document.getElementById("steps");
var progressBar = document.getElementById("progressBar");
var toast = document.getElementById("toast");
// Build step dots
for (var s = 0; s < TOTAL; s++) {
var d = document.createElement("div");
d.className = "steps-dot";
stepsHost.appendChild(d);
}
var stepDots = Array.prototype.slice.call(stepsHost.children);
// ---------- Build question screens ----------
QUESTIONS.forEach(function (q, qi) {
var sec = document.createElement("section");
sec.className = "screen";
sec.setAttribute("data-screen", "q" + qi);
var head = document.createElement("div");
head.className = "q-head";
head.innerHTML = escapeText(q.kicker) + '<span class="rule"></span>';
sec.appendChild(head);
var title = document.createElement("h2");
title.className = "q-title";
title.textContent = q.title;
sec.appendChild(title);
var grid = document.createElement("div");
grid.className = "answers";
q.options.forEach(function (opt) {
var btn = document.createElement("button");
btn.className = "answer";
btn.type = "button";
btn.setAttribute("data-score", opt.score);
btn.innerHTML =
'<div class="swatch"><div class="pat ' + opt.pat + '"></div>' +
'<span class="swatch-tag">' + escapeText(opt.tag) + '</span></div>' +
'<div class="a-label">' + escapeText(opt.label) + '</div>' +
'<div class="a-meta">' + escapeText(opt.meta) + '</div>';
btn.addEventListener("click", function () { onAnswer(opt.score, qi); });
grid.appendChild(btn);
});
sec.appendChild(grid);
var hint = document.createElement("div");
hint.className = "hint";
hint.innerHTML = '<span class="rule"></span><span>' +
(qi === TOTAL - 1 ? "Last one — tap to reveal your style" : "Tap a tile to continue") +
'</span>';
sec.appendChild(hint);
questionsHost.appendChild(sec);
});
// Cache screens after building
var screens = {};
Array.prototype.slice.call(stage.querySelectorAll(".screen")).forEach(function (el) {
screens[el.getAttribute("data-screen")] = el;
});
// ---------- Flow ----------
function showScreen(id) {
Object.keys(screens).forEach(function (k) { screens[k].classList.remove("active"); });
if (screens[id]) screens[id].classList.add("active");
}
function updateProgress(count) {
var ratio = count / TOTAL;
progressBar.style.transform = "scaleX(" + ratio + ")";
stepDots.forEach(function (dot, i) {
if (i < count) dot.classList.add("on"); else dot.classList.remove("on");
});
}
function onAnswer(score, qIndex) {
if (scores[score] != null) scores[score] += 1;
if (firstPick === null) firstPick = score;
answered = qIndex + 1;
updateProgress(answered);
if (qIndex < TOTAL - 1) {
showScreen("q" + (qIndex + 1));
} else {
renderResult();
showScreen("result");
}
}
function computeResult() {
var best = null, bestVal = -1;
// Iterate in a stable order; tie-break to firstPick, else keep earliest max.
["damask", "minimal", "maximal", "deco"].forEach(function (k) {
if (scores[k] > bestVal) { bestVal = scores[k]; best = k; }
});
// If the first pick is tied for the top, honor it (feels more personal).
if (firstPick && scores[firstPick] === bestVal) best = firstPick;
return best || "minimal";
}
var currentShop = "#";
function renderResult() {
var key = computeResult();
var r = RESULTS[key];
document.getElementById("resPattern").className = "pat " + r.pat;
document.getElementById("resCat").textContent = r.cat;
document.getElementById("resTitle").textContent = r.title;
document.getElementById("resDesc").textContent = r.desc;
document.getElementById("resShort").textContent = r.short;
var tagsHost = document.getElementById("resTags");
tagsHost.innerHTML = "";
r.tags.forEach(function (t) {
var span = document.createElement("span");
span.className = "t";
span.textContent = t;
tagsHost.appendChild(span);
});
var shopBtn = document.getElementById("shopBtn");
shopBtn.setAttribute("href", r.shop);
currentShop = r.shop;
// Reflect result in the URL hash so a shared link re-opens the same result.
try { history.replaceState(null, "", "#result-" + key); } catch (e) {}
window.__result = { key: key, r: r };
}
// ---------- Share ----------
function showToast(msg) {
toast.textContent = msg;
toast.classList.add("show");
setTimeout(function () { toast.classList.remove("show"); }, 2200);
}
document.getElementById("shareBtn").addEventListener("click", function () {
var res = window.__result;
var cat = res ? res.r.cat : "Wallcovering Style";
var shareText = "My wallcovering style is " + cat + " — what's yours?";
var shareUrl = location.href;
if (navigator.share) {
navigator.share({ title: "What's Your Wallcovering Style?", text: shareText, url: shareUrl })
.catch(function () { /* user cancelled — no-op */ });
} else if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(shareText + " " + shareUrl)
.then(function () { showToast("Copied — paste it anywhere."); })
.catch(function () { showToast("Screenshot this card to share."); });
} else {
showToast("Screenshot this card to share — it's sized for the feed.");
}
});
// ---------- Restart ----------
document.getElementById("retakeBtn").addEventListener("click", resetQuiz);
function resetQuiz() {
scores = { damask: 0, minimal: 0, maximal: 0, deco: 0 };
firstPick = null;
answered = 0;
updateProgress(0);
try { history.replaceState(null, "", location.pathname + location.search); } catch (e) {}
showScreen("intro");
}
// ---------- Begin ----------
document.getElementById("beginBtn").addEventListener("click", function () {
showScreen("q0");
});
// ---------- Utils ----------
function escapeText(str) {
return String(str).replace(/[&<>"']/g, function (c) {
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c];
});
}
// ---------- Deep link: open straight to a result if hash present ----------
(function initFromHash() {
var m = /^#result-(damask|minimal|maximal|deco)$/.exec(location.hash || "");
if (m) {
// Seed a minimal score so computeResult returns this key, then show it.
scores[m[1]] = 1;
firstPick = m[1];
updateProgress(TOTAL);
renderResult();
showScreen("result");
}
})();
updateProgress(0);
})();
</script>
</body>
</html>