← back to Model Arena

data/artifacts/131728b7aeb6/kimi.html

673 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Color of the Season | Designer Wallcoverings</title>
  <style>
    /* DESIGN TOKENS */
    :root {
      /* Color Palette - Luxury Noir with Celadon Accent */
      --bg: #0d0d0f;
      --surface: #17171c;
      --ink: #f5f2ea;
      --muted: #8a8578;
      --accent: #c9a961;
      --line: rgba(245, 242, 234, 0.15);
      --shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
      
      /* Color of the Season */
      --celadon: #b8c4b8;
      --celadon-deep: #9aab9a;
      --celadon-light: #d5ddd5;
      
      /* Typography */
      --font-display: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
      --font-body: 'Avenir Next', 'Century Gothic', Futura, 'Segoe UI', sans-serif;
      --font-mono: 'SF Mono', 'Cascadia Code', Consolas, Menlo, monospace;
      
      /* Type Scale */
      --text-caption: 12px;
      --text-body: 16px;
      --text-lead: 21px;
      --text-h3: 28px;
      --text-h2: 38px;
      --text-h1: 50px;
      --text-display: clamp(60px, 15vw, 120px);
      
      /* Spacing */
      --space-xs: 8px;
      --space-sm: 16px;
      --space-md: 24px;
      --space-lg: 40px;
      --space-xl: 64px;
      
      /* Easings */
      --ease-swift: cubic-bezier(.22,.9,.24,1);
      --ease-power: cubic-bezier(.77,0,.18,1);
      --ease-overshoot: cubic-bezier(.34,1.56,.64,1);
      --ease-out-quint: cubic-bezier(.22,1,.36,1);
      
      /* Timing */
      --scene-duration: 3000ms;
      --stagger-delay: 150ms;
    }

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: var(--font-body);
      background: var(--bg);
      color: var(--ink);
      overflow: hidden;
      height: 100vh;
      width: 100vw;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    /* Fixed Header */
    .brand-header {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      height: 60px;
      background: var(--bg);
      border-bottom: 1px solid var(--line);
      display: flex;
      align-items: center;
      padding: 0 var(--space-md);
      z-index: 1000;
      box-shadow: var(--shadow);
    }

    .wordmark {
      font-family: var(--font-display);
      font-size: 14px;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--ink);
      font-weight: 400;
      line-height: 1;
      white-space: nowrap;
    }

    /* 9:16 Reel Container */
    .reel-container {
      position: relative;
      width: 100%;
      max-width: 450px;
      aspect-ratio: 9/16;
      background: var(--bg);
      overflow: hidden;
      box-shadow: var(--shadow);
    }

    @media (max-width: 500px) {
      .reel-container {
        max-width: none;
        height: 100vh;
      }
    }

    /* Progress Bar */
    .progress-bar {
      position: absolute;
      top: 0;
      left: 0;
      height: 2px;
      background: var(--accent);
      width: 0%;
      z-index: 100;
      transition: width 100ms linear;
    }

    /* Play/Pause Control */
    .controls {
      position: absolute;
      bottom: var(--space-lg);
      right: var(--space-md);
      z-index: 100;
    }

    .control-btn {
      width: 44px;
      height: 44px;
      border: 1px solid var(--line);
      background: rgba(13, 13, 15, 0.8);
      backdrop-filter: blur(8px);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      transition: all 300ms var(--ease-swift);
    }

    .control-btn:hover {
      border-color: var(--accent);
      transform: scale(1.05);
    }

    .control-btn svg {
      width: 16px;
      height: 16px;
      fill: var(--ink);
    }

    .control-btn.paused .pause-icon,
    .control-btn:not(.paused) .play-icon {
      display: none;
    }

    /* Scene Container */
    .scenes {
      position: relative;
      width: 100%;
      height: 100%;
    }

    .scene {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: var(--space-lg) var(--space-md);
      opacity: 0;
      visibility: hidden;
      transition: opacity 600ms var(--ease-power), visibility 600ms;
    }

    .scene.active {
      opacity: 1;
      visibility: visible;
    }

    /* Scene 1: Hook */
    .hook-text {
      font-family: var(--font-display);
      font-size: var(--text-h2);
      color: var(--ink);
      text-align: center;
      line-height: 1.2;
      letter-spacing: -0.02em;
      opacity: 0;
      transform: translateY(30px);
      transition: all 800ms var(--ease-out-quint);
    }

    .scene.active .hook-text {
      opacity: 1;
      transform: translateY(0);
    }

    /* Scene 2: Color Name */
    .color-hero {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: var(--celadon);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      opacity: 0;
      transform: scale(0.95);
      transition: all 900ms var(--ease-power);
    }

    .scene.active .color-hero {
      opacity: 1;
      transform: scale(1);
    }

    .color-name {
      font-family: var(--font-display);
      font-size: var(--text-display);
      color: var(--bg);
      text-transform: uppercase;
      letter-spacing: 0.05em;
      line-height: 0.9;
      text-align: center;
      opacity: 0;
      transform: translateY(40px);
      transition: all 700ms var(--ease-out-quint) 200ms;
    }

    .color-subtitle {
      font-family: var(--font-body);
      font-size: var(--text-caption);
      text-transform: uppercase;
      letter-spacing: 0.2em;
      color: var(--bg);
      margin-top: var(--space-md);
      opacity: 0;
      transition: opacity 500ms var(--ease-swift) 500ms;
    }

    .scene.active .color-name,
    .scene.active .color-subtitle {
      opacity: 1;
      transform: translateY(0);
    }

    /* Scene 3: Pattern Swatches */
    .swatches-container {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      gap: var(--space-sm);
      padding: var(--space-xl) 0;
    }

    .swatch {
      flex: 1;
      width: 100%;
      background: var(--celadon);
      position: relative;
      overflow: hidden;
      opacity: 0;
      transform: translateX(-30px);
      transition: all 600ms var(--ease-out-quint);
    }

    .scene.active .swatch {
      opacity: 1;
      transform: translateX(0);
    }

    .scene.active .swatch:nth-child(1) { transition-delay: calc(var(--stagger-delay) * 1); }
    .scene.active .swatch:nth-child(2) { transition-delay: calc(var(--stagger-delay) * 2); }
    .scene.active .swatch:nth-child(3) { transition-delay: calc(var(--stagger-delay) * 3); }

    /* Pattern 1: Geometric Lattice */
    .pattern-lattice {
      background-color: var(--celadon);
      background-image: 
        linear-gradient(45deg, transparent 48%, var(--celadon-deep) 49%, var(--celadon-deep) 51%, transparent 52%),
        linear-gradient(-45deg, transparent 48%, var(--celadon-deep) 49%, var(--celadon-deep) 51%, transparent 52%);
      background-size: 40px 40px;
      opacity: 0.6;
    }

    /* Pattern 2: Organic Floral (SVG pattern) */
    .pattern-floral {
      background-color: var(--celadon);
      background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M30 5c5 0 10 5 10 10s-5 8-10 8-10-3-10-8 5-10 10-10zm0 30c5 0 10 5 10 10s-5 8-10 8-10-3-10-8 5-10 10-10z' fill='%239aab9a' fill-opacity='0.4'/%3E%3C/svg%3E");
    }

    /* Pattern 3: Horizontal Stripes with Texture */
    .pattern-stripes {
      background: repeating-linear-gradient(
        0deg,
        var(--celadon),
        var(--celadon) 10px,
        var(--celadon-deep) 10px,
        var(--celadon-deep) 12px
      );
    }

    /* Scene 4: Styling Tip */
    .tip-container {
      text-align: center;
      max-width: 320px;
    }

    .tip-label {
      font-size: var(--text-caption);
      text-transform: uppercase;
      letter-spacing: 0.2em;
      color: var(--accent);
      margin-bottom: var(--space-md);
      opacity: 0;
      transform: translateY(20px);
      transition: all 500ms var(--ease-swift);
    }

    .tip-text {
      font-family: var(--font-display);
      font-size: var(--text-h2);
      color: var(--ink);
      line-height: 1.3;
      letter-spacing: -0.01em;
      opacity: 0;
      transform: translateY(20px);
      transition: all 500ms var(--ease-swift) 150ms;
    }

    .tip-detail {
      font-size: var(--text-body);
      color: var(--muted);
      margin-top: var(--space-md);
      line-height: 1.6;
      opacity: 0;
      transition: opacity 500ms var(--ease-swift) 300ms;
    }

    .scene.active .tip-label,
    .scene.active .tip-text,
    .scene.active .tip-detail {
      opacity: 1;
      transform: translateY(0);
    }

    /* Scene 5: CTA */
    .cta-container {
      text-align: center;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--space-lg);
    }

    .cta-headline {
      font-family: var(--font-display);
      font-size: var(--text-h1);
      color: var(--ink);
      line-height: 1.1;
      letter-spacing: -0.02em;
      opacity: 0;
      transform: scale(0.9);
      transition: all 600ms var(--ease-overshoot);
    }

    .cta-button {
      font-family: var(--font-body);
      font-size: var(--text-caption);
      text-transform: uppercase;
      letter-spacing: 0.15em;
      color: var(--bg);
      background: var(--celadon);
      padding: var(--space-md) var(--space-xl);
      border: none;
      cursor: pointer;
      position: relative;
      overflow: hidden;
      opacity: 0;
      transform: translateY(20px);
      transition: all 400ms var(--ease-swift) 200ms;
    }

    .cta-button::before {
      content: '';
      position: absolute;
      top: 0;
      left: -100%;
      width: 100%;
      height: 100%;
      background: var(--accent);
      transition: left 400ms var(--ease-swift);
      z-index: -1;
    }

    .cta-button:hover::before {
      left: 0;
    }

    .cta-button:hover {
      color: var(--bg);
    }

    .cta-subline {
      font-size: var(--text-caption);
      color: var(--muted);
      letter-spacing: 0.1em;
      text-transform: uppercase;
      opacity: 0;
      transition: opacity 400ms var(--ease-swift) 400ms;
    }

    .scene.active .cta-headline,
    .scene.active .cta-button,
    .scene.active .cta-subline {
      opacity: 1;
      transform: translateY(0) scale(1);
    }

    /* Caption overlay for accessibility */
    .caption-overlay {
      position: absolute;
      bottom: 80px;
      left: var(--space-md);
      right: var(--space-md);
      text-align: center;
      pointer-events: none;
    }

    .caption-text {
      font-size: var(--text-caption);
      text-transform: uppercase;
      letter-spacing: 0.15em;
      color: var(--muted);
      background: rgba(13, 13, 15, 0.8);
      padding: var(--space-xs) var(--space-sm);
      display: inline-block;
      opacity: 0;
      transform: translateY(10px);
      transition: all 300ms var(--ease-swift);
    }

    .scene.active .caption-text {
      opacity: 1;
      transform: translateY(0);
    }

    /* Hairline decorative elements */
    .hairline {
      position: absolute;
      background: var(--line);
    }

    .hairline-top {
      top: 60px;
      left: var(--space-md);
      right: var(--space-md);
      height: 1px;
    }
  </style>
</head>
<body>

  <!-- Fixed Brand Header -->
  <header class="brand-header">
    <div class="wordmark">Designer Wallcoverings</div>
  </header>

  <!-- 9:16 Reel Container -->
  <div class="reel-container" id="reel">
    
    <!-- Progress Bar -->
    <div class="progress-bar" id="progressBar"></div>

    <!-- Decorative Hairline -->
    <div class="hairline hairline-top"></div>

    <!-- Scenes -->
    <div class="scenes">

      <!-- Scene 1: Hook -->
      <div class="scene active" data-scene="0">
        <h1 class="hook-text">This season<br>it's all about…</h1>
        <div class="caption-overlay">
          <span class="caption-text">Color of the Season</span>
        </div>
      </div>

      <!-- Scene 2: Color Name -->
      <div class="scene" data-scene="1">
        <div class="color-hero">
          <h2 class="color-name">Celadon</h2>
          <p class="color-subtitle">The New Neutral</p>
        </div>
        <div class="caption-overlay">
          <span class="caption-text">Introducing Celadon</span>
        </div>
      </div>

      <!-- Scene 3: Pattern Swatches -->
      <div class="scene" data-scene="2">
        <div class="swatches-container">
          <div class="swatch pattern-lattice"></div>
          <div class="swatch pattern-floral"></div>
          <div class="swatch pattern-stripes"></div>
        </div>
        <div class="caption-overlay">
          <span class="caption-text">Three Signature Patterns</span>
        </div>
      </div>

      <!-- Scene 4: Styling Tip -->
      <div class="scene" data-scene="3">
        <div class="tip-container">
          <p class="tip-label">Styling Tip</p>
          <h3 class="tip-text">Pair with warm brass and raw linen for effortless sophistication</h3>
          <p class="tip-detail">Celadon brings quiet energy to both modern minimal and classic interiors.</p>
        </div>
        <div class="caption-overlay">
          <span class="caption-text">How to Style</span>
        </div>
      </div>

      <!-- Scene 5: CTA -->
      <div class="scene" data-scene="4">
        <div class="cta-container">
          <h3 class="cta-headline">Transform<br>Your Space</h3>
          <button class="cta-button">Shop the Collection</button>
          <p class="cta-subline">Exclusive to Designer Wallcoverings</p>
        </div>
        <div class="caption-overlay">
          <span class="caption-text">Shop Now</span>
        </div>
      </div>

    </div>

    <!-- Controls -->
    <div class="controls">
      <button class="control-btn" id="playPauseBtn" aria-label="Pause">
        <svg class="pause-icon" viewBox="0 0 24 24">
          <rect x="6" y="4" width="4" height="16"/>
          <rect x="14" y="4" width="4" height="16"/>
        </svg>
        <svg class="play-icon" viewBox="0 0 24 24">
          <path d="M8 5v14l11-7z"/>
        </svg>
      </button>
    </div>

  </div>

  <script>
    // Reel Controller
    class ReelController {
      constructor() {
        this.scenes = document.querySelectorAll('.scene');
        this.progressBar = document.getElementById('progressBar');
        this.playPauseBtn = document.getElementById('playPauseBtn');
        this.reel = document.getElementById('reel');
        
        this.currentScene = 0;
        this.isPlaying = true;
        this.sceneDuration = 3000; // 3 seconds per scene
        this.lastFrameTime = 0;
        this.elapsedTime = 0;
        this.animationId = null;
        
        this.init();
      }

      init() {
        this.playPauseBtn.addEventListener('click', () => this.togglePlay());
        this.start();
      }

      start() {
        this.lastFrameTime = performance.now();
        this.animationId = requestAnimationFrame((t) => this.loop(t));
      }

      loop(currentTime) {
        if (!this.isPlaying) return;

        const deltaTime = currentTime - this.lastFrameTime;
        this.lastFrameTime = currentTime;
        
        this.elapsedTime += deltaTime;
        
        // Calculate progress within current scene
        const progress = Math.min(this.elapsedTime / this.sceneDuration, 1);
        this.updateProgressBar(progress);

        // Check if scene should advance
        if (this.elapsedTime >= this.sceneDuration) {
          this.nextScene();
        }

        this.animationId = requestAnimationFrame((t) => this.loop(t));
      }

      updateProgressBar(progress) {
        const totalProgress = ((this.currentScene + progress) / this.scenes.length) * 100;
        this.progressBar.style.width = `${totalProgress}%`;
      }

      nextScene() {
        // Remove active class from current scene
        this.scenes[this.currentScene].classList.remove('active');
        
        // Advance to next scene
        this.currentScene = (this.currentScene + 1) % this.scenes.length;
        
        // Add active class to new scene
        this.scenes[this.currentScene].classList.add('active');
        
        // Reset elapsed time
        this.elapsedTime = 0;
      }

      togglePlay() {
        this.isPlaying = !this.isPlaying;
        
        if (this.isPlaying) {
          this.playPauseBtn.classList.remove('paused');
          this.lastFrameTime = performance.now();
          this.animationId = requestAnimationFrame((t) => this.loop(t));
        } else {
          this.playPauseBtn.classList.add('paused');
          cancelAnimationFrame(this.animationId);
        }
      }
    }

    // Initialize when DOM is ready
    document.addEventListener('DOMContentLoaded', () => {
      new ReelController();
    });

    // Handle visibility change to pause when tab is hidden
    document.addEventListener('visibilitychange', () => {
      const btn = document.getElementById('playPauseBtn');
      if (document.hidden) {
        btn.classList.add('paused');
      } else {
        btn.classList.remove('paused');
      }
    });
  </script>

</body>
</html>