← back to Model Arena

data/artifacts/104018fe5adc/kimi.html

528 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Designer Wallcoverings — This or That</title>
  <style>
    :root {
      /* Luxury Palette — Warm Ivory Ground */
      --bg: #f5f2ea;
      --surface: #ffffff;
      --ink: #1c1a17;
      --text: #1c1a17;
      --muted: #8a8578;
      --accent: #c9a961;
      --accent-alpha: rgba(201, 169, 97, 0.35);
      
      /* Story Dark Surface (Inside Phone) */
      --story-bg: #0d0d0f;
      --story-surface: #17171c;
      --story-text: #f5f2ea;
      
      /* Lines & Shadows */
      --line: rgba(28, 26, 23, 0.12);
      --hairline: 1px solid var(--line);
      --shadow-sm: 0 1px 2px rgba(0,0,0,0.06);
      --shadow-md: 0 8px 24px rgba(0,0,0,0.12);
      --shadow-lg: 0 32px 80px rgba(0,0,0,0.28);
      --shadow-glow: 0 0 24px 2px rgba(201, 169, 97, 0.35);
      
      /* Typography */
      --font-display: "Didot", "Bodoni MT", "Playfair Display", "Cormorant Garamond", Georgia, serif;
      --font-sans: "Avenir Next", "Century Gothic", Futura, "Segoe UI", "Helvetica Neue", sans-serif;
      
      /* Motion */
      --ease-swift: cubic-bezier(.22,.9,.24,1);
      --ease-hero: cubic-bezier(.22,1,.36,1);
      --ease-power: cubic-bezier(.77,0,.18,1);
      --ease-overshoot: cubic-bezier(.34,1.56,.64,1);
    }
    
    * { margin: 0; padding: 0; box-sizing: border-box; }
    
    body {
      background: var(--bg);
      font-family: var(--font-sans);
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
      padding-top: 140px;
      padding-bottom: 60px;
    }
    
    /* Fixed Luxury Header */
    header {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      z-index: 1000;
      background: var(--bg);
      padding: 36px 48px;
      border-bottom: var(--hairline);
    }
    
    .wordmark {
      font-family: var(--font-display);
      font-size: 46px;
      font-weight: 400;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--ink);
      line-height: 1.05;
      max-width: 400px;
    }
    
    /* Phone Frame — 9:16 Aspect */
    .phone-frame {
      width: 360px;
      height: 640px;
      background: var(--ink);
      border-radius: 40px;
      border: 14px solid var(--ink);
      position: relative;
      overflow: hidden;
      box-shadow: var(--shadow-lg), 0 0 0 1px rgba(255,255,255,0.1) inset;
    }
    
    .notch {
      position: absolute;
      top: 0;
      left: 50%;
      transform: translateX(-50%);
      width: 120px;
      height: 28px;
      background: var(--ink);
      border-bottom-left-radius: 16px;
      border-bottom-right-radius: 16px;
      z-index: 50;
    }
    
    /* Story Canvas */
    .story {
      width: 100%;
      height: 100%;
      background: var(--story-bg);
      position: relative;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
    
    /* Authentic Story Chrome */
    .story-chrome {
      height: 44px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 20px;
      color: var(--story-text);
      font-size: 14px;
      font-weight: 600;
      font-family: var(--font-sans);
      position: relative;
      z-index: 40;
    }
    
    .signal-dots {
      display: flex;
      gap: 4px;
      align-items: center;
    }
    
    .dot {
      width: 5px;
      height: 5px;
      background: var(--story-text);
      border-radius: 50%;
    }
    
    .battery {
      width: 22px;
      height: 11px;
      border: 1px solid rgba(245,242,234,0.4);
      border-radius: 3px;
      position: relative;
    }
    
    .battery::after {
      content: '';
      position: absolute;
      right: -3px;
      top: 3px;
      width: 2px;
      height: 5px;
      background: rgba(245,242,234,0.4);
      border-radius: 0 1px 1px 0;
    }
    
    /* Poll Layout */
    .poll-stage {
      flex: 1;
      display: flex;
      position: relative;
    }
    
    .option {
      flex: 1;
      position: relative;
      cursor: pointer;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      overflow: hidden;
      transition: filter 0.4s var(--ease-swift);
    }
    
    .option:active {
      filter: brightness(0.9);
    }
    
    .option-left {
      border-right: 1px solid rgba(245,242,234,0.08);
    }
    
    /* Swatch Containers */
    .swatch-wrapper {
      width: 140px;
      height: 200px;
      position: relative;
      border: 1px solid rgba(245,242,234,0.15);
      background: rgba(255,255,255,0.02);
      box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
    }
    
    .pattern-fill {
      position: absolute;
      inset: 0;
    }
    
    /* Editable Style Names — Refined Sans */
    .style-label {
      margin-top: 32px;
      color: var(--story-text);
      font-family: var(--font-sans);
      font-size: 13px;
      font-weight: 500;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      border: none;
      background: transparent;
      text-align: center;
      width: 120px;
      padding: 6px;
      border-bottom: 1px solid transparent;
      transition: border-color 0.3s;
      outline: none;
    }
    
    .style-label:focus {
      border-bottom-color: var(--accent);
    }
    
    /* Vote Bars */
    .vote-meter {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      height: 0;
      background: var(--accent);
      transition: height 1s var(--ease-hero);
      opacity: 0.95;
    }
    
    .vote-meter::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 1px;
      background: rgba(255,255,255,0.4);
      box-shadow: 0 0 12px rgba(201, 169, 97, 0.6);
    }
    
    .percentage {
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      color: var(--ink);
      font-family: var(--font-sans);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.12em;
      opacity: 0;
      transition: opacity 0.5s 0.4s;
      z-index: 10;
    }
    
    .option.voted .percentage {
      opacity: 1;
    }
    
    /* Winner Stamp */
    .winner-seal {
      position: absolute;
      top: 35%;
      left: 50%;
      transform: translate(-50%, -50%) scale(0) rotate(-12deg);
      width: 90px;
      height: 90px;
      border: 1.5px solid var(--accent);
      border-radius: 50%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: var(--accent);
      font-family: var(--font-sans);
      font-size: 10px;
      font-weight: 600;
      letter-spacing: 0.2em;
      text-transform: uppercase;
      opacity: 0;
      transition: all 0.6s var(--ease-overshoot);
      pointer-events: none;
      background: rgba(13,13,15,0.85);
      backdrop-filter: blur(8px);
      box-shadow: var(--shadow-glow), 0 4px 20px rgba(0,0,0,0.4);
    }
    
    .winner-seal::before {
      content: '★';
      font-size: 16px;
      margin-bottom: 4px;
      color: var(--accent);
    }
    
    .option.winner .winner-seal {
      transform: translate(-50%, -50%) scale(1) rotate(-12deg);
      opacity: 1;
    }
    
    /* VS Divider */
    .vs-divider {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 40px;
      height: 40px;
      background: var(--story-bg);
      border: 1px solid rgba(245,242,234,0.2);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--muted);
      font-family: var(--font-sans);
      font-size: 10px;
      font-weight: 600;
      letter-spacing: 0.15em;
      z-index: 20;
      box-shadow: 0 4px 12px rgba(0,0,0,0.5);
    }
    
    /* Instruction overlay */
    .tap-hint {
      position: absolute;
      bottom: 100px;
      left: 50%;
      transform: translateX(-50%);
      color: var(--muted);
      font-family: var(--font-sans);
      font-size: 11px;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      opacity: 0.7;
      pointer-events: none;
      transition: opacity 0.4s;
    }
    
    .voted .tap-hint {
      opacity: 0;
    }
    
    /* Animations */
    @keyframes fadeUp {
      from { opacity: 0; transform: translateY(20px); }
      to { opacity: 1; transform: translateY(0); }
    }
    
    @keyframes scaleIn {
      from { opacity: 0; transform: scale(0.9); }
      to { opacity: 1; transform: scale(1); }
    }
    
    .animate-enter {
      animation: fadeUp 0.8s var(--ease-hero) both;
    }
    
    .animate-enter-delay-1 { animation-delay: 0.1s; }
    .animate-enter-delay-2 { animation-delay: 0.2s; }
  </style>
</head>
<body>
  <header>
    <div class="wordmark">Designer Wallcoverings</div>
  </header>
  
  <div class="phone-frame">
    <div class="notch"></div>
    <div class="story" id="story">
      <div class="story-chrome">
        <span>9:41</span>
        <div class="signal-dots">
          <div class="dot"></div>
          <div class="dot"></div>
          <div class="dot"></div>
          <div class="dot" style="opacity:0.4"></div>
        </div>
        <div class="battery"></div>
      </div>
      
      <div class="poll-stage" id="pollStage">
        <div class="option option-left animate-enter" onclick="vote('left')">
          <div class="swatch-wrapper">
            <svg class="pattern-fill" viewBox="0 0 140 200" xmlns="http://www.w3.org/2000/svg">
              <defs>
                <pattern id="damask" x="0" y="0" width="70" height="100" patternUnits="userSpaceOnUse">
                  <!-- Ornamental Damask Motif -->
                  <path d="M35 10 C25 10, 15 20, 15 35 C15 45, 20 50, 25 55 C20 60, 10 65, 10 80 C10 95, 25 100, 35 100 C45 100, 60 95, 60 80 C60 65, 50 60, 45 55 C50 50, 55 45, 55 35 C55 20, 45 10, 35 10 Z" 
                        fill="none" stroke="#c9a961" stroke-width="0.8" opacity="0.6"/>
                  <path d="M35 25 C30 25, 25 30, 25 38 C25 45, 30 48, 35 52 C40 48, 45 45, 45 38 C45 30, 40 25, 35 25 Z" 
                        fill="none" stroke="#c9a961" stroke-width="0.5" opacity="0.4"/>
                  <path d="M35 65 C28 65, 22 72, 22 82 C22 88, 28 92, 35 95 C42 92, 48 88, 48 82 C48 72, 42 65, 35 65 Z" 
                        fill="none" stroke="#c9a961" stroke-width="0.5" opacity="0.4"/>
                  <!-- Scrollwork flourishes -->
                  <path d="M35 0 Q20 0, 10 15 M35 0 Q50 0, 60 15" 
                        fill="none" stroke="#c9a961" stroke-width="0.6" opacity="0.5"/>
                  <circle cx="35" cy="35" r="2" fill="#c9a961" opacity="0.3"/>
                </pattern>
              </defs>
              <rect width="140" height="200" fill="url(#damask)" opacity="0.9"/>
              <!-- Central medallion overlay -->
              <path d="M70 60 C50 60, 35 80, 35 100 C35 120, 50 140, 70 140 C90 140, 105 120, 105 100 C105 80, 90 60, 70 60 Z M70 75 C60 75, 50 85, 50 100 C50 115, 60 125, 70 125 C80 125, 90 115, 90 100 C90 85, 80 75, 70 75 Z" 
                    fill="none" stroke="#c9a961" stroke-width="1.2" opacity="0.8"/>
              <path d="M70 85 C65 85, 60 92, 60 100 C60 108, 65 115, 70 115 C75 115, 80 108, 80 100 C80 92, 75 85, 70 85" 
                    fill="none" stroke="#c9a961" stroke-width="0.6" opacity="0.5"/>
            </svg>
          </div>
          <input type="text" class="style-label" value="Damask" spellcheck="false">
          <div class="vote-meter" id="bar-left"></div>
          <div class="percentage" id="pct-left">0%</div>
          <div class="winner-seal">Winner</div>
        </div>
        
        <div class="vs-divider">VS</div>
        
        <div class="option option-right animate-enter animate-enter-delay-1" onclick="vote('right')">
          <div class="swatch-wrapper">
            <svg class="pattern-fill" viewBox="0 0 140 200" xmlns="http://www.w3.org/2000/svg">
              <defs>
                <pattern id="geometric" x="0" y="0" width="40" height="69.28" patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
                  <!-- Hexagonal Geometric Lattice -->
                  <polygon points="20,0 40,11.55 40,34.64 20,46.19 0,34.64 0,11.55" 
                           fill="none" stroke="#c9a961" stroke-width="0.7" opacity="0.5"/>
                  <polygon points="20,11.55 30,17.32 30,28.87 20,34.64 10,28.87 10,17.32" 
                           fill="none" stroke="#c9a961" stroke-width="0.4" opacity="0.3"/>
                  <!-- Connecting lines -->
                  <line x1="20" y1="0" x2="20" y2="11.55" stroke="#c9a961" stroke-width="0.5" opacity="0.4"/>
                  <line x1="40" y1="11.55" x2="40" y2="34.64" stroke="#c9a961" stroke-width="0.5" opacity="0.4"/>
                  <line x1="0" y1="11.55" x2="0" y2="34.64" stroke="#c9a961" stroke-width="0.5" opacity="0.4"/>
                  <!-- Accent points -->
                  <circle cx="20" cy="23.09" r="1.5" fill="#c9a961" opacity="0.4"/>
                </pattern>
              </defs>
              <rect width="140" height="200" fill="url(#geometric)" opacity="0.9"/>
              <!-- Bold geometric overlay -->
              <polygon points="70,50 100,75 100,125 70,150 40,125 40,75" 
                       fill="none" stroke="#c9a961" stroke-width="1.5" opacity="0.9"/>
              <line x1="70" y1="50" x2="70" y2="150" stroke="#c9a961" stroke-width="0.8" opacity="0.6"/>
              <line x1="40" y1="75" x2="100" y2="125" stroke="#c9a961" stroke-width="0.8" opacity="0.6"/>
              <line x1="100" y1="75" x2="40" y2="125" stroke="#c9a961" stroke-width="0.8" opacity="0.6"/>
              <circle cx="70" cy="100" r="4" fill="none" stroke="#c9a961" stroke-width="1" opacity="0.8"/>
            </svg>
          </div>
          <input type="text" class="style-label" value="Geometric" spellcheck="false">
          <div class="vote-meter" id="bar-right"></div>
          <div class="percentage" id="pct-right">0%</div>
          <div class="winner-seal">Winner</div>
        </div>
      </div>
      
      <div class="tap-hint" id="tapHint">Tap to vote</div>
    </div>
  </div>
  
  <script>
    let hasVoted = false;
    
    function vote(side) {
      if (hasVoted) return;
      hasVoted = true;
      
      const stage = document.getElementById('pollStage');
      const hint = document.getElementById('tapHint');
      stage.classList.add('voted');
      
      // Generate realistic poll results
      const leftPercent = side === 'left' ? 68 : 32;
      const rightPercent = side === 'right' ? 72 : 28;
      
      const barLeft = document.getElementById('bar-left');
      const barRight = document.getElementById('bar-right');
      const pctLeft = document.getElementById('pct-left');
      const pctRight = document.getElementById('pct-right');
      const optionLeft = document.querySelector('.option-left');
      const optionRight = document.querySelector('.option-right');
      
      // Animate bars
      setTimeout(() => {
        barLeft.style.height = (leftPercent * 1.8) + 'px';
        barRight.style.height = (rightPercent * 1.8) + 'px';
        
        // Count up animation
        animateValue(pctLeft, 0, leftPercent, 1000);
        animateValue(pctRight, 0, rightPercent, 1000);
        
        // Mark winner
        if (leftPercent > rightPercent) {
          optionLeft.classList.add('winner');
          optionRight.style.opacity = '0.6';
        } else {
          optionRight.classList.add('winner');
          optionLeft.style.opacity = '0.6';
        }
      }, 100);
    }
    
    function animateValue(obj, start, end, duration) {
      let startTimestamp = null;
      const step = (timestamp) => {
        if (!startTimestamp) startTimestamp = timestamp;
        const progress = Math.min((timestamp - startTimestamp) / duration, 1);
        obj.innerHTML = Math.floor(progress * (end - start) + start) + '%';
        if (progress < 1) {
          window.requestAnimationFrame(step);
        }
      };
      window.requestAnimationFrame(step);
    }
    
    // Allow editing labels without triggering vote
    document.querySelectorAll('.style-label').forEach(input => {
      input.addEventListener('click', (e) => {
        e.stopPropagation();
        input.focus();
      });
    });
  </script>
</body>
</html>