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 =...