← back to Model Arena

data/artifacts/131728b7aeb6/gpt.html

886 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Designer Wallcoverings — Color of the Season Reel</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<style>
:root {
  /* Design tokens */
  --bg: #0d0d0f;
  --surface: #17171c;
  --ink: #f5f2ea;
  --muted: #8a8578;
  --accent: #c9a961; /* warm metallic gold */
  --accent-soft: #7d6a45;
  --line: rgba(245, 242, 234, 0.12);
  --shadow-soft: 0 22px 40px rgba(0, 0, 0, 0.45);
  --shadow-subtle: 0 1px 0 rgba(255, 255, 255, 0.04), 0 10px 30px rgba(0, 0, 0, 0.6);

  --radius-soft: 18px;
  --radius-pill: 999px;

  --ease-swift: cubic-bezier(.22,.9,.24,1);
  --ease-scene: cubic-bezier(.77,0,.18,1);
  --ease-hero: cubic-bezier(.22,1,.36,1);

  --font-display: 'Playfair Display', 'Cormorant Garamond', 'EB Garamond', 'Didot', 'Bodoni MT', Georgia, serif;
  --font-sans: 'Avenir Next', 'Century Gothic', Futura, 'Segoe UI', sans-serif;

  --fs-caption: 12px;
  --fs-body: 16px;
  --fs-lead: 21px;
  --fs-h3: 28px;
  --fs-h2: 38px;
  --fs-h1: 50px;
  --fs-display: 67px;

  --reel-width: 360px;
  --reel-height: 640px;

  --caption-bg: rgba(13, 13, 15, 0.66);
  --caption-blur: 20px;

  --timeline-height: 3px;
  --timeline-bg: rgba(245, 242, 234, 0.12);
  --timeline-fill: #f5f2ea;

  --scene-duration: 4500ms;
}

/* Entrance keyframes from HyperFrames */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(28px); }
  to { opacity: 1; transform: none; }
}
@keyframes scaleIn {
  from { opacity: 0; transform: scale(.92); }
  to { opacity: 1; transform: none; }
}
@keyframes clipReveal {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0); }
}
@keyframes blurIn {
  from { opacity: 0; filter: blur(12px); }
  to { opacity: 1; filter: blur(0); }
}

/* Global layout */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: radial-gradient(circle at top, #191922 0, #050507 55%, #000 100%);
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Reel frame */
.reel-shell {
  width: min(var(--reel-width), 100vw);
  height: min(var(--reel-height), 100vh);
  background: radial-gradient(circle at top, #191922 0, #050507 70%, #000 100%);
  border-radius: 28px;
  box-shadow: var(--shadow-soft);
  overflow: hidden;
  position: relative;
  color: var(--ink);
  display: flex;
  flex-direction: column;
}

/* Top bar with wordmark */
.reel-header {
  position: relative;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px 8px;
  border-bottom: 1px solid rgba(245, 242, 234, 0.08);
  background: linear-gradient(to bottom, rgba(6,6,8,0.9), rgba(6,6,8,0.3));
  backdrop-filter: blur(14px);
}

.brand-lockup {
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 1.1;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: normal;
  max-width: 200px;
}

.brand-lockup span {
  display: block;
}

/* Header controls */
.header-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.badge-label {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Play / Pause button */
.play-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  border: 1px solid rgba(201,169,97,0.65);
  background: radial-gradient(circle at 30% 0, rgba(255,255,255,0.14), rgba(17,17,20,0.96));
  color: var(--ink);
  cursor: pointer;
  transition: background 160ms var(--ease-swift), transform 160ms var(--ease-swift), box-shadow 160ms var(--ease-swift), border-color 160ms var(--ease-swift);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4), 0 10px 24px rgba(0,0,0,0.9);
}

.play-toggle:hover {
  background: radial-gradient(circle at 30% 0, rgba(255,255,255,0.2), rgba(24,24,28,1));
  transform: translateY(-1px);
  box-shadow: 0 16px 30px rgba(0,0,0,0.85);
}

.play-toggle:active {
  transform: translateY(0);
  box-shadow: 0 6px 14px rgba(0,0,0,0.75);
}

.play-icon,
.pause-icon {
  width: 11px;
  height: 11px;
  display: block;
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.4;
}

.pause-icon {
  display: none;
}

/* Progress bar */
.timeline {
  position: relative;
  width: 100%;
  height: var(--timeline-height);
  background: var(--timeline-bg);
  overflow: hidden;
}

.timeline-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--ink));
  transform-origin: left;
  transition: width 120ms linear;
}

/* Reel content area */
.reel-main {
  position: relative;
  flex: 1;
  overflow: hidden;
  background:
    radial-gradient(circle at 0 0, rgba(201,169,97,0.18), transparent 46%),
    radial-gradient(circle at 100% 40%, rgba(125,106,69,0.28), transparent 55%),
    radial-gradient(circle at 50% 100%, rgba(0,0,0,0.9), #050507 70%);
}

/* Ambient vignette & border */
.reel-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 70px rgba(0,0,0,0.9);
  border-radius: inherit;
  border: 1px solid rgba(255,255,255,0.02);
}

/* Scenes */
.scene {
  position: absolute;
  inset: 0;
  padding: 22px 18px 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  opacity: 0;
  transform: translateX(6%);
  transition:
    opacity 500ms var(--ease-scene),
    transform 500ms var(--ease-scene);
  pointer-events: none;
}

.scene.is-active {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}

.scene.is-exit-left {
  opacity: 0;
  transform: translateX(-6%);
}

/* Caption band */
.caption-band {
  background: rgba(9,9,11,0.78);
  border-radius: 999px;
  padding: 6px 13px 6px 10px;
  border: 1px solid rgba(245,242,234,0.06);
  box-shadow: var(--shadow-subtle);
  backdrop-filter: blur(14px);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  animation: fadeUp 700ms var(--ease-hero) both;
}

.caption-pill {
  font-size: var(--fs-caption);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.caption-text {
  font-size: 14px;
  color: var(--ink);
  opacity: 0.92;
}

/* Scene 1: Hook */
.scene-1-headline {
  margin-top: 40px;
}

.kicker-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}

.kicker-dot {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: radial-gradient(circle at 30% 0, #fdf6e3, #c9a961);
  box-shadow: 0 0 0 1px rgba(201,169,97,0.6), 0 0 14px rgba(201,169,97,0.9);
}

.hook-heading {
  font-family: var(--font-display);
  font-size: 32px;
  line-height: 1.05;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 10px;
}

.hook-subtitle {
  font-size: var(--fs-body);
  color: var(--muted);
  max-width: 20rem;
}

/* Scene 2: Hue Name */
.hue-scene {
  align-items: center;
  text-align: center;
}

.hue-label {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 8px;
}

.hue-name-lockup {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.hue-name {
  font-family: var(--font-display);
  font-size: 52px;
  line-height: 1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 10px 16px;
  border-radius: 999px;
  border: 1px solid rgba(245,242,234,0.12);
  box-shadow:
    inset 0 0 26px rgba(201,169,97,0.12),
    0 26px 60px rgba(0,0,0,0.9);
  background:
    radial-gradient(circle at 0 0, rgba(201,169,97,0.55), rgba(7,12,12,1)),
    radial-gradient(circle at 100% 100%, rgba(39,59,54,0.94), rgba(16,22,21,1));
}

.hue-note {
  font-size: 14px;
  color: var(--muted);
  max-width: 16rem;
}

/* Scene 3: Swatches */
.swatch-scene {
  padding-top: 26px;
  padding-bottom: 24px;
}

.section-label {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
}

.swatch-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: 10px;
  margin-bottom: 14px;
}

.swatch-tile {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 18px 40px rgba(0,0,0,0.9);
  background: #1c2624;
  border: 1px solid rgba(245,242,234,0.08);
}

/* Swatch motifs */
.swatch-base {
  position: absolute;
  inset: 0;
}

/* Swatch 1: Celadon lattice */
.swatch-1 {
  background:
    radial-gradient(circle at 0 0, rgba(201,169,97,0.22), transparent 60%),
    linear-gradient(135deg, #203632, #1a2927);
}
.swatch-1::before,
.swatch-1::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(135deg, rgba(245,242,234,0.06) 0, rgba(245,242,234,0.06) 1px, transparent 0, transparent 18px),
    linear-gradient(225deg, rgba(245,242,234,0.05) 0, rgba(245,242,234,0.05) 1px, transparent 0, transparent 18px);
  background-size: 18px 18px;
  mix-blend-mode: screen;
}
.swatch-1::after {
  transform: translate(9px, 9px);
  opacity: 0.45;
}

/* Swatch 2: Vertical metallic bands */
.swatch-2 {
  background:
    linear-gradient(90deg,
      rgba(16,27,26,1) 0,
      rgba(41,64,58,1) 20%,
      rgba(16,27,26,1) 40%,
      rgba(41,64,58,1) 60%,
      rgba(16,27,26,1) 80%,
      rgba(41,64,58,1) 100%);
}
.swatch-2::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(201,169,97,0.0) 0,
    rgba(201,169,97,0.42) 14%,
    rgba(201,169,97,0.0) 28%,
    rgba(201,169,97,0.45) 44%,
    rgba(201,169,97,0.0) 60%,
    rgba(201,169,97,0.45) 76%,
    rgba(201,169,97,0.0) 100%);
  mix-blend-mode: screen;
}
.swatch-2::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(0,0,0,0.5), transparent 30%, transparent 70%, rgba(0,0,0,0.7));
}

/* Swatch 3: Organic brush */
.swatch-3 {
  background:
    radial-gradient(circle at 10% 0, rgba(201,169,97,0.28), transparent 48%),
    radial-gradient(circle at 100% 100%, rgba(17,35,33,1), rgba(7,14,14,1));
}
.swatch-3::before {
  content: "";
  position: absolute;
  inset: -20%;
  background-image:
    radial-gradient(circle at 10% 20%, rgba(245,242,234,0.08) 0, transparent 40%),
    radial-gradient(circle at 60% 0%, rgba(245,242,234,0.05) 0, transparent 50%),
    radial-gradient(circle at 40% 80%, rgba(245,242,234,0.06) 0, transparent 50%),
    radial-gradient(circle at 110% 60%, rgba(245,242,234,0.08) 0, transparent 45%);
  filter: blur(10px);
  opacity: 0.8;
}

/* Swatch caption */
.swatch-caption {
  font-size: 13px;
  color: var(--muted);
  max-width: 19rem;
}

/* Scene 4: Styling tip & CTA */
.tip-scene {
  padding-top: 26px;
  padding-bottom: 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.tip-main {
  margin-top: 20px;
}

.tip-heading {
  font-family: var(--font-display);
  font-size: 28px;
  line-height: 1.1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 10px;
}

.tip-body {
  font-size: var(--fs-body);
  color: var(--muted);
  max-width: 20rem;
}

/* CTA panel */
.cta-panel {
  margin-top: 26px;
  padding: 12px 14px;
  border-radius: 18px;
  border: 1px solid rgba(245,242,234,0.08);
  background:
    radial-gradient(circle at 0 0, rgba(201,169,97,0.26), rgba(22,26,24,0.96)),
    radial-gradient(circle at 100% 100%, rgba(19,29,27,1), rgba(11,14,14,1));
  box-shadow: var(--shadow-subtle);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cta-copy {
  font-size: 13px;
}

.cta-eyebrow {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(245,242,234,0.78);
  margin-bottom: 3px;
}

.cta-main {
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* CTA button */
.cta-button {
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgba(245,242,234,0.5);
  background: radial-gradient(circle at 0 0, #f5f2ea, #c9a961);
  color: #151515;
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 14px 28px rgba(0,0,0,0.9);
  transition: transform 140ms var(--ease-swift), box-shadow 140ms var(--ease-swift), filter 140ms var(--ease-swift);
}

.cta-button:hover {
  transform: translateY(-1px);
  box-shadow: 0 20px 38px rgba(0,0,0,0.95);
  filter: brightness(1.05);
}

.cta-button:active {
  transform: translateY(0);
  box-shadow: 0 10px 22px rgba(0,0,0,0.9);
}

/* Caption bar at bottom */
.caption-bar {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 16px;
  padding: 8px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  border-radius: 999px;
  background: var(--caption-bg);
  backdrop-filter: blur(var(--caption-blur));
  border: 1px solid rgba(245,242,234,0.06);
  box-shadow: var(--shadow-subtle);
  font-size: 13px;
}

.caption-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 1px rgba(10,10,10,0.8), 0 0 12px rgba(201,169,97,0.9);
}

.caption-content {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Caption marquee animation */
.caption-scroller {
  display: inline-block;
  animation: clipReveal 800ms var(--ease-hero) both;
}

/* State: paused */
.reel-shell.is-paused .timeline-fill {
  transition: none;
}

/* Utility */
.hide-visually {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
</style>
</head>
<body>
<div class="reel-shell" data-playing="true">
  <header class="reel-header">
    <div class="brand-lockup">
      <span>DESIGNER</span>
      <span>WALLCOVERINGS</span>
    </div>
    <div class="header-controls">
      <div class="badge-label">COLOR OF THE SEASON</div>
      <button class="play-toggle" type="button" aria-label="Pause reel" aria-pressed="true">
        <svg class="play-icon" viewBox="0 0 12 12" aria-hidden="true">
          <polygon points="3,2 10,6 3,10" fill="currentColor"></polygon>
        </svg>
        <svg class="pause-icon" viewBox="0 0 12 12" aria-hidden="true">
          <rect x="2.5" y="2" width="2.3" height="8" fill="currentColor"></rect>
          <rect x="7.2" y="2" width="2.3" height="8" fill="currentColor"></rect>
        </svg>
      </button>
    </div>
  </header>

  <div class="timeline" aria-hidden="true">
    <div class="timeline-fill"></div>
  </div>

  <main class="reel-main">
    <div class="reel-vignette"></div>

    <!-- Scene 1: Hook -->
    <section class="scene scene-1 is-active" data-scene-index="0" aria-label="Seasonal color hook">
      <div>
        <div class="scene-1-headline">
          <div class="kicker-label">
            <span class="kicker-dot"></span>
            <span>This season it's all about</span>
          </div>
          <h1 class="hook-heading">
            Quiet luxury<br />
            on your walls
          </h1>
          <p class="hook-subtitle">
            A soft celadon that feels like evening light on hand‑troweled plaster.
          </p>
        </div>
      </div>
      <div>
        <div class="caption-band">
          <div class="caption-pill">Scene 1&nbsp;&mdash;&nbsp;Introduction</div>
          <div class="caption-text">Watch the hue reveal, then explore three celadon wall textures in motion.</div>
        </div>
      </div>
    </section>

    <!-- Scene 2: Hue name -->
    <section class="scene hue-scene scene-2" data-scene-index="1" aria-label="Celadon color reveal">
      <div class="hue-name-lockup">
        <div class="hue-label">Color of the Season</div>
        <div class="hue-name">
          Celadon
        </div>
        <p class="hue-note">
          A luminous green with porcelain softness, grounded by inky trims and warm metallics.
        </p>
      </div>
      <div class="caption-band">
        <div class="caption-pill">Scene 2&nbsp;&mdash;&nbsp;Hue Reveal</div>
        <div class="caption-text">Celadon: serene enough for bedrooms, elevated enough for gallery dining rooms.</div>
      </div>
    </section>

    <!-- Scene 3: Pattern swatches -->
    <section class="scene swatch-scene scene-3" data-scene-index="2" aria-label="Celadon wallcovering swatches">
      <div>
        <div class="section-label">Celadon in three wall textures</div>
        <div class="swatch-row">
          <div class="swatch-tile" aria-hidden="true">
            <div class="swatch-base swatch-1"></div>
          </div>
          <div class="swatch-tile" aria-hidden="true">
            <div class="swatch-base swatch-2"></div>
          </div>
          <div class="swatch-tile" aria-hidden="true">
            <div class="swatch-base swatch-3"></div>
          </div>
        </div>
        <p class="swatch-caption">
          From tailored lattice to brushed metallic bands and painterly clouds of color &mdash; each swatch keeps celadon at the center, never overpowering the room.
        </p>
      </div>
      <div class="caption-band">
        <div class="caption-pill">Scene 3&nbsp;&mdash;&nbsp;Textures</div>
        <div class="caption-text">Pair a single statement wall with quieter coordinates for layered yet restful rooms.</div>
      </div>
    </section>

    <!-- Scene 4: Styling tip & CTA -->
    <section class="scene tip-scene scene-4" data-scene-index="3" aria-label="Styling tips and call to action">
      <div class="tip-main">
        <div class="section-label">Styling tip</div>
        <h2 class="tip-heading">Let celadon breathe</h2>
        <p class="tip-body">
          Balance the softness with deep near‑black woodwork, linen upholstery, and a single brass moment&mdash;a picture light, a tray, a mirror frame.
        </p>
      </div>
      <div class="cta-panel">
        <div class="cta-copy">
          <div class="cta-eyebrow">Discover the collection</div>
          <div class="cta-main">Order a celadon sample set</div>
        </div>
        <button class="cta-button" type="button">
          Request set
        </button>
      </div>
    </section>

    <!-- Live captions at bottom -->
    <div class="caption-bar" aria-live="polite">
      <div class="caption-dot"></div>
      <div class="caption-content">
        <span class="caption-scroller" id="liveCaption">
          This season it's all about quiet luxury on your walls.
        </span>
      </div>
    </div>
  </main>
</div>

<script>
(function() {
  const shell = document.querySelector('.reel-shell');
  const scenes = Array.from(document.querySelectorAll('.scene'));
  const progress = document.querySelector('.timeline-fill');
  const playToggle = document.querySelector('.play-toggle');
  const playIcon = document.querySelector('.play-icon');
  const pauseIcon = document.querySelector('.pause-icon');
  const liveCaption = document.getElementById('liveCaption');

  const sceneDuration = parseInt(getComputedStyle(document.documentElement)
    .getPropertyValue('--scene-duration'), 10) || 4500;

  const captions = [
    'This season it\'s all about quiet luxury on your walls.',
    'Celadon: a porcelain-soft green that flatters every light.',
    'Three distinct celadon wall textures, from lattice to brushed metallic.',
    'Layer celadon with deep trims and one warm metallic accent.'
  ];

  let currentScene = 0;
  let isPlaying = true;
  let timerId = null;
  let progressStart = null;
  let progressRequest = null;

  function setCaption(index) {
    if (!liveCaption) return;
    liveCaption.textContent = captions[index] || '';
    liveCaption.style.animation = 'none';
    // restart clipReveal
    requestAnimationFrame(() => {
      liveCaption.style.animation = '';
      liveCaption.style.animation = 'clipReveal 800ms var(--ease-hero) both';
    });
  }

  function showScene(index, fromIndex) {
    scenes.forEach((scene, i) => {
      scene.classList.remove('is-exit-left', 'is-active');
      if (i === index) {
        scene.classList.add('is-active');
      } else if (typeof fromIndex === 'number' && i === fromIndex && index > fromIndex) {
        scene.classList.add('is-exit-left');
      }
    });
    setCaption(index);
  }

  function animateProgress(timestamp) {
    if (!isPlaying) return;
    if (!progressStart) progressStart = timestamp;
    const elapsed = timestamp - progressStart;
    const pct = Math.min(100, (elapsed / sceneDuration) * 100);
    if (progress) progress.style.width = pct + '%';
    if (elapsed >= sceneDuration) {
      nextScene();
      return;
    }
    progressRequest = requestAnimationFrame(animateProgress);
  }

  function startProgress() {
    cancelAnimationFrame(progressRequest);
    progressStart = null;
    if (progress) progress.style.width = '0%';
    progressRequest = requestAnimationFrame(animateProgress);
  }

  function nextScene() {
    const fromIndex = currentScene;
    currentScene = (currentScene + 1) % scenes.length;
    showScene(currentScene, fromIndex);
    progressStart = null;
    if (isPlaying) {
      startProgress();
    }
  }

  function togglePlayState(forceState) {
    const newState = typeof forceState === 'boolean' ? forceState : !isPlaying;
    isPlaying = newState;
    shell.dataset.playing = String(isPlaying);
    shell.classList.toggle('is-paused', !isPlaying);

    if (isPlaying) {
      playToggle.setAttribute('aria-label', 'Pause reel');
      playToggle.setAttribute('aria-pressed', 'true');
      playIcon.style.display = 'none';
      pauseIcon.style.display = 'block';
      // resume progress from current width
      const currentWidth = parseFloat((progress && progress.style.width) || '0');
      if (!isNaN(currentWidth) && currentWidth > 0) {
        const elapsed = (currentWidth / 100) * sceneDuration;
        progressStart = performance.now() - elapsed;
        cancelAnimationFrame(progressRequest);
        progressRequest = requestAnimationFrame(animateProgress);
      } else {
        startProgress();
      }
    } else {
      playToggle.setAttribute('aria-label', 'Play reel');
      playToggle.setAttribute('aria-pressed', 'false');
      playIcon.style.display = 'block';
      pauseIcon.style.display = 'none';
      cancelAnimationFrame(progressRequest);
      progressRequest = null;
    }
  }

  playToggle.addEventListener('click', () => {
    togglePlayState();
  });

  // Kick things off
  showScene(currentScene, null);
  setCaption(currentScene);
  togglePlayState(true); // ensures icons correct + progress running
})();
</script>
</body>
</html>