Interior — Style Quiz
A warm editorial find-your-style quiz that walks you through five image-choice questions — moods, materials, palettes and silhouettes — while a slim progress rail tracks your journey. Each pick tallies toward one of four interior directions, then a reveal card computes your result with a short manifesto, a swatch palette, a shortlist of signature pieces and a next-step CTA. Keyboard friendly, restartable, and built to feel like a considered design studio consultation.
MCP
Code
:root {
--bg: #f6f2ec;
--paper: #fbf9f5;
--ink: #2c2620;
--ink-2: #5a5147;
--muted: #8a8175;
--clay: #b08968;
--clay-d: #8c6a4f;
--walnut: #5c4433;
--sage: #9caf88;
--line: rgba(44, 38, 32, 0.12);
--white: #fff;
--r-sm: 4px;
--r-md: 8px;
--r-lg: 14px;
--shadow: 0 24px 60px -30px rgba(44, 38, 32, 0.45);
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 32px 18px;
font-family: "Inter", system-ui, sans-serif;
line-height: 1.5;
color: var(--ink);
background:
radial-gradient(120% 80% at 85% -10%, rgba(176, 137, 104, 0.12), transparent 60%),
radial-gradient(120% 80% at -10% 110%, rgba(156, 175, 136, 0.14), transparent 60%),
var(--bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.serif { font-family: "Cormorant Garamond", Georgia, serif; }
/* Shell -------------------------------------------------- */
.quiz {
width: 100%;
max-width: 760px;
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow);
overflow: hidden;
display: flex;
flex-direction: column;
}
.quiz__head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 20px 26px 14px;
border-bottom: 1px solid var(--line);
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand__mark {
width: 26px;
height: 26px;
border-radius: 50%;
background: linear-gradient(140deg, var(--clay), var(--walnut));
box-shadow: inset 0 0 0 3px rgba(251, 249, 245, 0.6);
}
.brand__name {
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
font-size: 13px;
}
.eyebrow {
margin: 0;
font-size: 11px;
letter-spacing: 0.24em;
text-transform: uppercase;
color: var(--muted);
}
/* Rail --------------------------------------------------- */
.rail { padding: 16px 26px 4px; }
.rail__track {
height: 3px;
border-radius: 99px;
background: var(--line);
overflow: hidden;
}
.rail__fill {
height: 100%;
background: linear-gradient(90deg, var(--clay), var(--walnut));
border-radius: 99px;
transition: width 0.5s cubic-bezier(0.4, 0, 0.15, 1);
}
.rail__meta {
display: flex;
justify-content: space-between;
margin-top: 9px;
font-size: 11px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--muted);
}
/* Stage -------------------------------------------------- */
.stage { padding: 10px 26px 22px; }
.slide { animation: rise 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
@keyframes rise {
from { opacity: 0; transform: translateY(14px); }
to { opacity: 1; transform: translateY(0); }
}
/* Intro -------------------------------------------------- */
.intro { text-align: center; padding: 22px 6px 12px; }
.intro__art {
height: 150px;
border-radius: var(--r-md);
margin: 0 auto 22px;
max-width: 460px;
background:
linear-gradient(115deg, rgba(44,38,32,0.06), transparent),
linear-gradient(140deg, var(--clay) 0%, var(--walnut) 55%, var(--sage) 130%);
position: relative;
overflow: hidden;
}
.intro__art::after {
content: "";
position: absolute;
inset: 14px;
border: 1px solid rgba(251, 249, 245, 0.55);
border-radius: var(--r-sm);
}
.intro__title {
margin: 0 0 12px;
font-size: clamp(30px, 6vw, 46px);
font-weight: 500;
line-height: 1.05;
color: var(--walnut);
}
.intro__lead {
margin: 0 auto 22px;
max-width: 420px;
color: var(--ink-2);
font-size: 15px;
}
.tagrow {
display: flex;
gap: 8px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 24px;
}
/* Question ----------------------------------------------- */
.q__kicker {
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--clay-d);
margin: 6px 0 8px;
font-weight: 600;
}
.q__title {
margin: 0 0 18px;
font-size: clamp(24px, 5vw, 32px);
font-weight: 500;
color: var(--ink);
line-height: 1.12;
}
.options {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 14px;
list-style: none;
margin: 0;
padding: 0;
}
.opt {
position: relative;
border: 1px solid var(--line);
background: var(--white);
border-radius: var(--r-md);
padding: 0;
text-align: left;
cursor: pointer;
overflow: hidden;
font: inherit;
color: inherit;
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
display: flex;
flex-direction: column;
}
.opt:hover { transform: translateY(-3px); border-color: var(--clay); box-shadow: 0 16px 30px -22px rgba(44,38,32,0.5); }
.opt:focus-visible { outline: 2px solid var(--walnut); outline-offset: 3px; }
.opt:active { transform: translateY(-1px) scale(0.995); }
.opt__swatch { height: 92px; position: relative; }
.opt__swatch::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(180deg, transparent 55%, rgba(44,38,32,0.14));
}
.opt__body {
padding: 12px 14px 14px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.opt__label { font-weight: 600; font-size: 14.5px; }
.opt__note { font-size: 12px; color: var(--muted); display: block; margin-top: 2px; }
.opt__tick {
width: 22px;
height: 22px;
border-radius: 50%;
border: 1px solid var(--line);
flex: none;
display: grid;
place-items: center;
color: transparent;
transition: all 0.2s ease;
}
.opt[aria-pressed="true"] { border-color: var(--walnut); box-shadow: 0 0 0 1px var(--walnut) inset; }
.opt[aria-pressed="true"] .opt__tick {
background: var(--walnut);
border-color: var(--walnut);
color: var(--paper);
}
/* Badge -------------------------------------------------- */
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 11px;
letter-spacing: 0.1em;
text-transform: uppercase;
font-weight: 600;
color: var(--clay-d);
background: rgba(176, 137, 104, 0.14);
border: 1px solid rgba(176, 137, 104, 0.3);
padding: 5px 11px;
border-radius: 99px;
}
/* Result ------------------------------------------------- */
.result { padding: 6px 0 6px; }
.result__head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.result__match { font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.result__title {
margin: 4px 0 12px;
font-size: clamp(32px, 7vw, 52px);
font-weight: 500;
color: var(--walnut);
line-height: 1.02;
}
.result__desc { margin: 0 0 20px; color: var(--ink-2); font-size: 15px; max-width: 560px; }
.result__grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
border-top: 1px solid var(--line);
padding-top: 20px;
}
.result__sub {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--muted);
margin: 0 0 12px;
}
.palette { display: flex; gap: 0; border-radius: var(--r-sm); overflow: hidden; border: 1px solid var(--line); }
.palette span { flex: 1; height: 54px; position: relative; }
.palette span::after {
content: attr(data-hex);
position: absolute;
bottom: 4px;
left: 0;
right: 0;
text-align: center;
font-size: 9px;
letter-spacing: 0.05em;
color: rgba(251, 249, 245, 0.9);
opacity: 0;
transition: opacity 0.2s ease;
}
.palette:hover span::after { opacity: 1; }
.pieces { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pieces li {
display: flex;
align-items: center;
gap: 10px;
font-size: 14px;
color: var(--ink);
padding: 8px 0;
border-bottom: 1px solid var(--line);
}
.pieces li:last-child { border-bottom: 0; }
.pieces .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--sage); flex: none; }
/* Buttons ------------------------------------------------ */
.quiz__foot {
display: flex;
align-items: center;
gap: 14px;
padding: 16px 26px;
border-top: 1px solid var(--line);
background: rgba(176, 137, 104, 0.05);
}
.foot__hint { margin: 0 auto 0 0; font-size: 12.5px; color: var(--muted); }
.btn {
font: inherit;
font-weight: 600;
font-size: 13px;
letter-spacing: 0.04em;
border-radius: var(--r-sm);
padding: 10px 18px;
cursor: pointer;
border: 1px solid transparent;
transition: transform 0.15s ease, background 0.2s ease, color 0.2s ease, opacity 0.2s ease;
}
.btn:focus-visible { outline: 2px solid var(--walnut); outline-offset: 2px; }
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--walnut); color: var(--paper); }
.btn--primary:hover { background: var(--clay-d); }
.btn--ghost { background: transparent; color: var(--ink-2); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--clay); color: var(--ink); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }
.btn--start {
background: var(--walnut);
color: var(--paper);
padding: 13px 30px;
font-size: 14px;
border-radius: var(--r-sm);
}
.btn--start:hover { background: var(--clay-d); }
/* Toast -------------------------------------------------- */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translate(-50%, 20px);
background: var(--ink);
color: var(--paper);
padding: 11px 20px;
border-radius: 99px;
font-size: 13px;
font-weight: 500;
box-shadow: 0 14px 30px -12px rgba(0,0,0,0.5);
opacity: 0;
pointer-events: none;
transition: transform 0.3s ease, opacity 0.3s ease;
z-index: 40;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* Responsive --------------------------------------------- */
@media (max-width: 520px) {
body { padding: 16px 10px; }
.quiz__head, .rail, .stage, .quiz__foot { padding-left: 16px; padding-right: 16px; }
.options { grid-template-columns: 1fr; gap: 12px; }
.opt__swatch { height: 78px; }
.result__grid { grid-template-columns: 1fr; gap: 22px; }
.eyebrow { display: none; }
.quiz__foot { flex-wrap: wrap; }
.foot__hint { order: 3; width: 100%; text-align: center; margin: 4px 0 0; }
.btn--primary { flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}(function () {
"use strict";
// --- Style definitions ------------------------------------------------
var STYLES = {
japandi: {
name: "Japandi",
match: "Your leading direction",
desc: "A quiet marriage of Japanese restraint and Scandinavian warmth. You gravitate to low, honest silhouettes, hand-finished woods and rooms that breathe. Nothing shouts; everything is chosen. Negative space is treated as a material in its own right.",
palette: [
{ hex: "#e9e3d8", c: "#e9e3d8" },
{ hex: "#c8b8a1", c: "#c8b8a1" },
{ hex: "#7d6b57", c: "#7d6b57" },
{ hex: "#3d352b", c: "#3d352b" },
{ hex: "#8a9a7b", c: "#8a9a7b" }
],
pieces: ["Low oak platform bed", "Handmade ceramic vessels", "Paper pendant lantern", "Linen floor cushions", "A single sculptural branch"]
},
midcentury: {
name: "Mid-century Modern",
match: "Your leading direction",
desc: "Confident lines, tapered legs and a love of walnut. You mix graphic form with easy comfort — a room that nods to the 1950s studio without feeling like a museum. Warm woods meet the occasional bold accent and plenty of organic curve.",
palette: [
{ hex: "#f0e7d6", c: "#f0e7d6" },
{ hex: "#d99c5f", c: "#d99c5f" },
{ hex: "#8c6a4f", c: "#8c6a4f" },
{ hex: "#3a5a48", c: "#3a5a48" },
{ hex: "#2c2620", c: "#2c2620" }
],
pieces: ["Tapered-leg walnut credenza", "Egg-shaped lounge chair", "Globe arc floor lamp", "Geometric wool rug", "Brass starburst mirror"]
},
minimal: {
name: "Warm Minimal",
match: "Your leading direction",
desc: "Pared back but never cold. You edit ruthlessly, then let a few beautiful textures — bouclé, lime plaster, unlacquered brass — carry the room. Tonal, calm and generous with light, your spaces feel expensive precisely because so little is on show.",
palette: [
{ hex: "#fbf9f5", c: "#fbf9f5" },
{ hex: "#ece4d7", c: "#ece4d7" },
{ hex: "#c2b09a", c: "#c2b09a" },
{ hex: "#8a8175", c: "#8a8175" },
{ hex: "#4a443c", c: "#4a443c" }
],
pieces: ["Bouclé curved sofa", "Lime-plaster wall finish", "Monolithic stone coffee table", "Unlacquered brass sconce", "Oversized floor vase"]
},
organic: {
name: "Organic Modern",
match: "Your leading direction",
desc: "Earthy, tactile and alive. You bring the outdoors in with raw timber, rattan, terracotta and layered greenery. Curves soften every corner and natural imperfection is the whole point — a home that feels grounded, sun-warmed and easy to live in.",
palette: [
{ hex: "#f4ede1", c: "#f4ede1" },
{ hex: "#cb8f6a", c: "#cb8f6a" },
{ hex: "#9caf88", c: "#9caf88" },
{ hex: "#6b8f6d", c: "#6b8f6d" },
{ hex: "#5c4433", c: "#5c4433" }
],
pieces: ["Live-edge dining table", "Woven rattan lounge chair", "Terracotta planter cluster", "Jute layered rug", "Trailing pothos & fig"]
}
};
// Gradient helpers for option swatches
function grad(a, b, c) {
return "background:linear-gradient(140deg," + a + " 0%," + b + " 60%," + (c || b) + " 130%)";
}
// --- Questions --------------------------------------------------------
var QUESTIONS = [
{
kicker: "Question 01",
title: "Which room makes you exhale?",
label: "Mood",
options: [
{ label: "Serene & spare", note: "Empty floor, soft light", style: "japandi", css: grad("#e9e3d8", "#c8b8a1", "#7d6b57") },
{ label: "Bold & graphic", note: "Statement shapes", style: "midcentury", css: grad("#d99c5f", "#8c6a4f", "#3a5a48") },
{ label: "Soft & tonal", note: "Quiet luxury", style: "minimal", css: grad("#fbf9f5", "#ece4d7", "#c2b09a") },
{ label: "Lush & earthy", note: "Plants everywhere", style: "organic", css: grad("#cb8f6a", "#9caf88", "#5c4433") }
]
},
{
kicker: "Question 02",
title: "Pick a material to live with.",
label: "Material",
options: [
{ label: "Pale ash & paper", note: "Light, matte grain", style: "japandi", css: grad("#efe7d6", "#d8c7ab", "#a3906f") },
{ label: "Rich walnut", note: "Warm, glossy", style: "midcentury", css: grad("#a9724a", "#8c6a4f", "#4b3626") },
{ label: "Lime plaster", note: "Chalky, tonal", style: "minimal", css: grad("#f0e9dd", "#d9cbb6", "#b6a68f") },
{ label: "Rattan & jute", note: "Woven, tactile", style: "organic", css: grad("#d8b483", "#b98d5c", "#7d6b3f") }
]
},
{
kicker: "Question 03",
title: "Choose your palette.",
label: "Palette",
options: [
{ label: "Oat & charcoal", note: "Muted contrast", style: "japandi", css: grad("#e9e3d8", "#8a8175", "#3d352b") },
{ label: "Mustard & teal", note: "Retro warmth", style: "midcentury", css: grad("#d99c5f", "#3a5a48", "#8c6a4f") },
{ label: "Bone on bone", note: "Whisper tones", style: "minimal", css: grad("#fbf9f5", "#ece4d7", "#c2b09a") },
{ label: "Terracotta & sage", note: "Sun & garden", style: "organic", css: grad("#cb8f6a", "#9caf88", "#6b8f6d") }
]
},
{
kicker: "Question 04",
title: "Your ideal seat.",
label: "Silhouette",
options: [
{ label: "Low floor sofa", note: "Grounded, linen", style: "japandi", css: grad("#ddd2bd", "#b7a488", "#7d6b57") },
{ label: "Tapered armchair", note: "Angular legs", style: "midcentury", css: grad("#c98f5c", "#8c6a4f", "#2c2620") },
{ label: "Bouclé curve", note: "Soft monolith", style: "minimal", css: grad("#f2ece0", "#ddd0bc", "#b0a08b") },
{ label: "Woven lounger", note: "Curved rattan", style: "organic", css: grad("#d5aa78", "#9caf88", "#5c4433") }
]
},
{
kicker: "Question 05",
title: "One finishing touch.",
label: "Accent",
options: [
{ label: "Single branch", note: "In a stone vase", style: "japandi", css: grad("#e4dccb", "#a99a80", "#5c4f3e") },
{ label: "Starburst mirror", note: "Brass, radiant", style: "midcentury", css: grad("#e0b063", "#b0803f", "#4b3626") },
{ label: "Sculptural vessel", note: "Oversized, matte", style: "minimal", css: grad("#f0e9dd", "#cdbfa8", "#8a8175") },
{ label: "Trailing greenery", note: "Layered pots", style: "organic", css: grad("#9caf88", "#6b8f6d", "#3d4f34") }
]
}
];
// --- State ------------------------------------------------------------
var state = { index: -1, answers: [] }; // index -1 = intro; length = result
var TOTAL = QUESTIONS.length;
var stage = document.getElementById("stage");
var railFill = document.getElementById("railFill");
var stepLabel = document.getElementById("stepLabel");
var stepCount = document.getElementById("stepCount");
var backBtn = document.getElementById("backBtn");
var ctaBtn = document.getElementById("ctaBtn");
var footHint = document.getElementById("footHint");
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () { toastEl.classList.remove("show"); }, 2200);
}
// --- Render -----------------------------------------------------------
function render() {
if (state.index === -1) return renderIntro();
if (state.index >= TOTAL) return renderResult();
return renderQuestion(state.index);
}
function updateChrome() {
var answered = state.answers.filter(function (a) { return a != null; }).length;
var pct;
if (state.index === -1) pct = 0;
else if (state.index >= TOTAL) pct = 100;
else pct = Math.round((state.index / TOTAL) * 100);
railFill.style.width = pct + "%";
if (state.index === -1) { stepLabel.textContent = "Intro"; stepCount.textContent = "0 / " + TOTAL; }
else if (state.index >= TOTAL) { stepLabel.textContent = "Result"; stepCount.textContent = TOTAL + " / " + TOTAL; }
else { stepLabel.textContent = QUESTIONS[state.index].label; stepCount.textContent = (state.index + 1) + " / " + TOTAL; }
backBtn.disabled = state.index <= -1;
ctaBtn.hidden = state.index < TOTAL;
footHint.textContent = state.index === -1
? "Five quick picks"
: state.index >= TOTAL
? answered + " answers tallied"
: (state.answers[state.index] != null ? "Great — pick or continue" : "Choose an image to continue");
}
function renderIntro() {
stage.innerHTML =
'<div class="slide intro">' +
'<div class="intro__art"></div>' +
'<h1 class="intro__title serif" id="quiz-title">Find your interior style</h1>' +
'<p class="intro__lead">Five considered questions, one clear direction. Answer with your eye and we’ll name the aesthetic your home is quietly asking for.</p>' +
'<div class="tagrow">' +
'<span class="badge">Japandi</span>' +
'<span class="badge">Mid-century</span>' +
'<span class="badge">Warm Minimal</span>' +
'<span class="badge">Organic Modern</span>' +
'</div>' +
'<button class="btn btn--start" id="startBtn" type="button">Begin the quiz</button>' +
'</div>';
document.getElementById("startBtn").addEventListener("click", function () {
state.index = 0; render();
});
updateChrome();
}
function renderQuestion(i) {
var q = QUESTIONS[i];
var chosen = state.answers[i];
var html = '<div class="slide">' +
'<p class="q__kicker">' + q.kicker + '</p>' +
'<h2 class="q__title serif" id="quiz-title">' + q.title + '</h2>' +
'<ul class="options" role="list">';
q.options.forEach(function (opt, oi) {
var pressed = chosen === oi;
html +=
'<li>' +
'<button class="opt" type="button" data-i="' + oi + '" aria-pressed="' + (pressed ? "true" : "false") + '">' +
'<span class="opt__swatch" style="' + opt.css + '"></span>' +
'<span class="opt__body">' +
'<span><span class="opt__label">' + opt.label + '</span>' +
'<span class="opt__note">' + opt.note + '</span></span>' +
'<span class="opt__tick" aria-hidden="true">✓</span>' +
'</span>' +
'</button>' +
'</li>';
});
html += '</ul></div>';
stage.innerHTML = html;
var buttons = stage.querySelectorAll(".opt");
buttons.forEach(function (b) {
b.addEventListener("click", function () { choose(i, parseInt(b.getAttribute("data-i"), 10)); });
});
updateChrome();
}
function choose(qi, oi) {
state.answers[qi] = oi;
// reflect selection instantly
stage.querySelectorAll(".opt").forEach(function (b) {
b.setAttribute("aria-pressed", parseInt(b.getAttribute("data-i"), 10) === oi ? "true" : "false");
});
updateChrome();
// advance after a beat
setTimeout(function () {
state.index = qi + 1;
render();
}, 340);
}
function tally() {
var scores = { japandi: 0, midcentury: 0, minimal: 0, organic: 0 };
state.answers.forEach(function (oi, qi) {
if (oi == null) return;
var s = QUESTIONS[qi].options[oi].style;
scores[s] += 1;
});
var best = "japandi", bestN = -1;
Object.keys(scores).forEach(function (k) {
if (scores[k] > bestN) { bestN = scores[k]; best = k; }
});
return best;
}
function renderResult() {
var key = tally();
var s = STYLES[key];
var swatches = s.palette.map(function (p) {
return '<span data-hex="' + p.hex + '" style="background:' + p.c + '"></span>';
}).join("");
var pieces = s.pieces.map(function (p) {
return '<li><span class="dot" aria-hidden="true"></span>' + p + '</li>';
}).join("");
stage.innerHTML =
'<div class="slide result">' +
'<div class="result__head">' +
'<span class="badge">Your result</span>' +
'<span class="result__match">' + s.match + '</span>' +
'</div>' +
'<h2 class="result__title serif" id="quiz-title">' + s.name + '</h2>' +
'<p class="result__desc">' + s.desc + '</p>' +
'<div class="result__grid">' +
'<div>' +
'<p class="result__sub">Signature palette</p>' +
'<div class="palette">' + swatches + '</div>' +
'<button class="btn btn--ghost" id="retakeBtn" type="button" style="margin-top:18px">↺ Retake quiz</button>' +
'</div>' +
'<div>' +
'<p class="result__sub">Pieces to look for</p>' +
'<ul class="pieces">' + pieces + '</ul>' +
'</div>' +
'</div>' +
'</div>';
document.getElementById("retakeBtn").addEventListener("click", reset);
updateChrome();
toast("Your style: " + s.name);
}
function reset() {
state = { index: -1, answers: [] };
render();
toast("Quiz reset — start again");
}
// --- Footer controls --------------------------------------------------
backBtn.addEventListener("click", function () {
if (state.index > -1) { state.index -= 1; render(); }
});
ctaBtn.addEventListener("click", function () {
var s = STYLES[tally()];
toast("Opening " + s.name + " pieces…");
});
// Keyboard: number keys 1-4 select on a question
document.addEventListener("keydown", function (e) {
if (state.index < 0 || state.index >= TOTAL) return;
var n = parseInt(e.key, 10);
if (n >= 1 && n <= 4) {
var btn = stage.querySelector('.opt[data-i="' + (n - 1) + '"]');
if (btn) { e.preventDefault(); btn.focus(); choose(state.index, n - 1); }
}
});
render();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Interior — Style Quiz</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:wght@400;500;600&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="quiz" aria-labelledby="quiz-title">
<header class="quiz__head">
<div class="brand">
<span class="brand__mark" aria-hidden="true"></span>
<span class="brand__name">Maison & Grain</span>
</div>
<p class="eyebrow">Interior style finder</p>
</header>
<!-- Progress rail -->
<div class="rail" role="group" aria-label="Quiz progress">
<div class="rail__track">
<div class="rail__fill" id="railFill" style="width:0%"></div>
</div>
<div class="rail__meta">
<span id="stepLabel">Intro</span>
<span id="stepCount" aria-live="polite">0 / 5</span>
</div>
</div>
<!-- Slides get injected here -->
<section class="stage" id="stage" aria-live="polite"></section>
<footer class="quiz__foot">
<button class="btn btn--ghost" id="backBtn" type="button" disabled>← Back</button>
<p class="foot__hint" id="footHint">Answer to continue</p>
<button class="btn btn--primary" id="ctaBtn" type="button" hidden>Explore pieces</button>
</footer>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>The Style Quiz opens on a quiet editorial cover and moves through five image-choice questions. Each question presents a set of tactile option cards — a mood, a material, a palette, a silhouette — and selecting one advances the flow while a thin progress rail and step counter keep the reader oriented. Options are fully keyboard operable, with visible focus rings and clear selected states, so the experience stays accessible without losing its calm, gallery-like tone.
Every answer quietly adds weight to one of four directions: Japandi, Mid-century Modern, Warm Minimal, or Organic Modern. When the last question is answered the quiz tallies the score, resolves the leading style, and animates a reveal card into view. That card carries a short manifesto paragraph, a row of palette swatches drawn from the winning aesthetic, and a shortlist of signature pieces to look for when styling a room.
A persistent footer offers a Back control, a live progress read-out, and — on the result screen — a primary CTA to explore matching pieces plus a Retake option that resets the tally and returns to the cover. A small toast confirms actions like restarting or saving the result, giving the interaction a responsive, polished feel throughout.