JSFiddle - React, Tailwind, and code Playground
HTML
<main class="game-shell">
<header class="hero">
<p class="eyebrow">HALLOWEEN CHALLENGE</p>
<h1>Spot the Difference</h1>
<p class="subtitle">Find 5 differences in each level. You can tap either picture.</p>
</header>
<section class="game-card" aria-live="polite">
<div class="topbar">
<div>
<span class="level-label" id="levelLabel">Level 1 of 4</span>
<h2 id="levelTitle">Midnight Tea Party</h2>
</div>
<div class="stats">
<span>Found <strong id="foundCount">0</strong>/5</span>
<span>Time <strong id="timer">00:00</strong></span>
</div>
</div>
<div class="level-dots" id="levelDots" aria-label="Level progress"></div>
<div class="pictures" id="pictures">
<figure class="picture" data-side="left">
<figcaption>ORIGINAL</figcaption>
<div class="image-stage">
<img id="leftImage" alt="Original picture" draggable="false">
<div class="markers" id="leftMarkers"></div>
</div>
</figure>
<figure class="picture" data-side="right">
<figcaption>CHANGED</figcaption>
<div class="image-stage">
<img id="rightImage" alt="Changed picture" draggable="false">
<div class="markers" id="rightMarkers"></div>
</div>
</figure>
</div>
<p class="message" id="message">Look closely and start searching!</p>
<div class="actions">
<button class="button button-secondary" id="resetButton" type="button">Restart</button>
<button class="button button-secondary" id="hintButton" type="button">Hint <span id="hintCount">3</span></button>
<button class="button button-primary" id="nextButton" type="button" disabled>Next Level</button>
</div>
</section>
</main>
<div class="celebration" id="celebration" hidden>
<div class="confetti"...
CSS
:root {
--ink: #fff7e8;
--muted: #c9b9d7;
--purple: #251638;
--panel: rgba(28, 17, 43, .92);
--orange: #ff7a1a;
--yellow: #ffd85a;
--red: #ff3d45;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
color: var(--ink);
font-family: Inter, "Microsoft YaHei", system-ui, sans-serif;
background:
radial-gradient(circle at 18% 5%, rgba(125, 63, 186, .32), transparent 25rem),
radial-gradient(circle at 88% 28%, rgba(255, 122, 26, .16), transparent 26rem),
#0e0915;
}
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
opacity: .16;
background-image: repeating-linear-gradient(120deg, transparent 0 22px, rgba(255,255,255,.045) 23px 24px);
}
button { font: inherit; }
.game-shell {
width: min(1400px, 96vw);
margin: 0 auto;
padding: 34px 0 50px;
}
.hero { text-align: center; margin-bottom: 24px; }
.eyebrow { margin: 0 0 7px; color: var(--orange); font-weight: 900; letter-spacing: .18em; font-size: .76rem; }
.hero h1 { margin: 0; font-size: clamp(2rem, 5vw, 4rem); line-height: 1; letter-spacing: .04em; }
.subtitle { margin: 12px 0 0; color: var(--muted); }
.game-card {
padding: clamp(16px, 2.8vw, 34px);
border: 1px solid rgba(255, 216, 90, .22);
border-radius: 28px;
background: var(--panel);
box-shadow: 0 30px 80px rgba(0,0,0,.42), inset 0 1px rgba(255,255,255,.05);
backdrop-filter: blur(12px);
}
.topbar { display: flex; align-items: end; justify-content: space-between; gap: 18px; }
.level-label { color: var(--orange); font-weight: 800; font-size: .85rem; }
.topbar h2 { margin: 5px 0 0; font-size: clamp(1.35rem, 3vw, 2rem); }
.stats { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.stats span { padding: 9px 13px; border-radius: 999px; background: rgba(255,255,255,.07); color: var(--muted); white-space: nowrap; }
.stats strong { color: var(--yellow); font-size: 1.05em;...
JavaScript
const EMBEDDED_IMAGES =...