← back to Model Arena

data/artifacts/18bd2744dce2/grok.html

697 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Terracotta &amp; Sage — Color Story</title>
<style>
:root {
  --bg: #faf8f4;
  --surface: #ffffff;
  --ink: #1c1a17;
  --muted: #9b948a;
  --accent: #b0472e;
  --accent-soft: #c65f38;
  --jewel: #2f4c39;
  --line: rgba(28, 26, 23, 0.12);
  --shadow: 0 12px 40px rgba(28, 26, 23, 0.08);
  --shadow-soft: 0 4px 16px rgba(28, 26, 23, 0.06);
  --ease: cubic-bezier(.22, .9, .24, 1);
  --ease-hero: cubic-bezier(.22, 1, .36, 1);
  --serif: 'Didot', 'Bodoni MT', 'Playfair Display', 'EB Garamond', Georgia, 'Times New Roman', serif;
  --sans: 'Avenir Next', 'Century Gothic', Futura, 'Helvetica Neue', sans-serif;
  --hue-oatmeal: #d4c4a8;
  --hue-celadon: #8fa890;
  --hue-terracotta: #c45c3e;
  --frame: 1080px;
}

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

html, body {
  height: 100%;
  background: #e8e4dc;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Compact wordmark lockup */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  padding: 18px 24px;
  pointer-events: none;
}
.wordmark {
  font-family: var(--serif);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  max-width: 220px;
  line-height: 1.3;
  opacity: 0.85;
}

.app {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 56px 24px 40px;
  gap: 28px;
}

/* Stage */
.stage-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.carousel {
  width: min(92vw, 540px);
  aspect-ratio: 1 / 1;
  position: relative;
  background: var(--bg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  overflow: hidden;
  touch-action: pan-y;
  user-select: none;
  cursor: grab;
}
.carousel:active { cursor: grabbing; }

.track {
  display: flex;
  height: 100%;
  width: 100%;
  transition: transform 0.65s var(--ease-hero);
  will-change: transform;
}

.slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* —— Slide 1: Cover —— */
.slide-cover {
  background: var(--bg);
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 8%;
}
.cover-ornament {
  width: 48px;
  height: 1px;
  background: var(--accent);
  margin: 0 auto 28px;
}
.cover-kicker {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 18px;
}
.cover-title {
  font-family: var(--serif);
  font-size: clamp(36px, 8vw, 52px);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 14px;
}
.cover-title em {
  font-style: italic;
  color: var(--accent);
}
.cover-sub {
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 36px;
}
.cover-swatches {
  display: flex;
  gap: 10px;
  justify-content: center;
  align-items: center;
}
.cover-swatch {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-soft);
}
.cover-season {
  position: absolute;
  bottom: 7%;
  left: 0;
  right: 0;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}

/* —— Hue slides 2–4 —— */
.slide-hue {
  background: var(--bg);
  padding: 0;
}
.hue-panel {
  flex: 1;
  display: grid;
  grid-template-rows: 1.15fr 1fr;
  height: 100%;
}
.swatch-field {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
/* CSS-drawn luxury swatch — layered planes, no letter labels */
.swatch-field::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--swatch);
}
.swatch-field::after {
  content: '';
  position: absolute;
  right: -8%;
  bottom: -18%;
  width: 58%;
  height: 70%;
  background: var(--swatch-deep);
  opacity: 0.55;
  border-radius: 60% 40% 30% 70% / 50% 30% 70% 50%;
  filter: blur(0.5px);
}
.swatch-sheen {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255,255,255,0.18) 0%, transparent 42%, transparent 100%);
  pointer-events: none;
  z-index: 1;
}
.swatch-edge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--line);
  z-index: 2;
}
.hue-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 9% 10% 10%;
  background: var(--bg);
  gap: 14px;
}
.hue-label {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
.hue-name {
  font-family: var(--serif);
  font-size: clamp(32px, 7vw, 44px);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--ink);
}
.hue-rule {
  width: 32px;
  height: 1px;
  background: var(--accent);
  margin: 2px 0 4px;
}
.hue-tip {
  font-family: var(--sans);
  font-size: clamp(13px, 2.4vw, 15px);
  line-height: 1.6;
  color: var(--ink);
  opacity: 0.78;
  max-width: 34ch;
}
.hue-tip strong {
  font-weight: 500;
  color: var(--ink);
  opacity: 1;
}

/* Per-hue tokens */
.slide-oatmeal { --swatch: var(--hue-oatmeal); --swatch-deep: #b8a68a; }
.slide-celadon { --swatch: var(--hue-celadon); --swatch-deep: #6f8a72; }
.slide-terracotta { --swatch: var(--hue-terracotta); --swatch-deep: #9a3f28; }

/* —— Slide 5: CTA —— */
.slide-cta {
  background: var(--ink);
  color: var(--bg);
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 10%;
}
.cta-kicker {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-soft);
  margin-bottom: 22px;
}
.cta-title {
  font-family: var(--serif);
  font-size: clamp(28px, 6.5vw, 40px);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #f5f2ea;
  margin-bottom: 18px;
  max-width: 16ch;
}
.cta-body {
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.65;
  color: rgba(245, 242, 234, 0.62);
  max-width: 28ch;
  margin: 0 auto 32px;
}
.cta-btn {
  display: inline-block;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  background: #f5f2ea;
  border: 1px solid #f5f2ea;
  padding: 14px 28px;
  cursor: pointer;
  transition: background 0.35s var(--ease), color 0.35s var(--ease), border-color 0.35s var(--ease);
  text-decoration: none;
}
.cta-btn:hover {
  background: transparent;
  color: #f5f2ea;
  border-color: rgba(245, 242, 234, 0.45);
}
.cta-palette-row {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-top: 36px;
}
.cta-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid rgba(245, 242, 234, 0.15);
}

/* Dots */
.dots {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
}
.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
  opacity: 0.35;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), background 0.35s var(--ease);
}
.dot[aria-current="true"] {
  opacity: 1;
  background: var(--accent);
  transform: scale(1.35);
}

/* Editable palette strip */
.editor {
  width: min(92vw, 540px);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-soft);
  padding: 18px 20px 16px;
}
.editor-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 14px;
}
.editor-title {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}
.editor-note {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--muted);
  opacity: 0.7;
}
.swatch-controls {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.control {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}
.control label {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.7;
}
.control input[type="color"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 36px;
  border: 1px solid var(--line);
  background: transparent;
  cursor: pointer;
  padding: 0;
  border-radius: 2px;
}
.control input[type="color"]::-webkit-color-swatch-wrapper { padding: 3px; }
.control input[type="color"]::-webkit-color-swatch {
  border: none;
  border-radius: 1px;
}
.control input[type="color"]::-moz-color-swatch {
  border: none;
  border-radius: 1px;
}

.hint {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
  opacity: 0.65;
}

@media (max-width: 480px) {
  .topbar { padding: 14px 16px; }
  .app { padding: 48px 12px 28px; }
  .hue-copy { padding: 8% 8% 9%; }
}
</style>
</head>
<body>
<header class="topbar" aria-label="Brand">
  <div class="wordmark">Designer Wallcoverings</div>
</header>

<main class="app">
  <div class="stage-wrap">
    <div class="carousel" id="carousel" role="region" aria-roledescription="carousel" aria-label="Terracotta and Sage color story">
      <div class="track" id="track">

        <!-- 1 Cover -->
        <section class="slide slide-cover" aria-label="Cover">
          <div class="cover-ornament"></div>
          <p class="cover-kicker">Seasonal Color Story</p>
          <h1 class="cover-title">Terracotta<br>&amp; <em>Sage</em></h1>
          <p class="cover-sub">Autumn Atelier · Vol. IV</p>
          <div class="cover-swatches" aria-hidden="true">
            <span class="cover-swatch" id="cs-oat" style="background: var(--hue-oatmeal)"></span>
            <span class="cover-swatch" id="cs-cel" style="background: var(--hue-celadon)"></span>
            <span class="cover-swatch" id="cs-ter" style="background: var(--hue-terracotta)"></span>
          </div>
          <p class="cover-season">Three hues · Infinite rooms</p>
        </section>

        <!-- 2 Oatmeal -->
        <section class="slide slide-hue slide-oatmeal" aria-label="Oatmeal">
          <div class="hue-panel">
            <div class="swatch-field">
              <div class="swatch-sheen"></div>
              <div class="swatch-edge"></div>
            </div>
            <div class="hue-copy">
              <p class="hue-label">Hue 01 · Ground</p>
              <h2 class="hue-name">Oatmeal</h2>
              <div class="hue-rule"></div>
              <p class="hue-tip"><strong>Room tip:</strong> Anchor a sunlit dining alcove — pair with raw linen drapery and unlacquered brass to let the grain of the paper breathe.</p>
            </div>
          </div>
        </section>

        <!-- 3 Celadon -->
        <section class="slide slide-hue slide-celadon" aria-label="Celadon">
          <div class="hue-panel">
            <div class="swatch-field">
              <div class="swatch-sheen"></div>
              <div class="swatch-edge"></div>
            </div>
            <div class="hue-copy">
              <p class="hue-label">Hue 02 · Breath</p>
              <h2 class="hue-name">Celadon</h2>
              <div class="hue-rule"></div>
              <p class="hue-tip"><strong>Room tip:</strong> Soften a powder room or study — the mineral green steadies terracotta accents and cools warm oak floors.</p>
            </div>
          </div>
        </section>

        <!-- 4 Terracotta -->
        <section class="slide slide-hue slide-terracotta" aria-label="Terracotta">
          <div class="hue-panel">
            <div class="swatch-field">
              <div class="swatch-sheen"></div>
              <div class="swatch-edge"></div>
            </div>
            <div class="hue-copy">
              <p class="hue-label">Hue 03 · Ember</p>
              <h2 class="hue-name">Terracotta</h2>
              <div class="hue-rule"></div>
              <p class="hue-tip"><strong>Room tip:</strong> Commit to a full feature wall behind a bed or banquette — the clay warmth holds candlelight and deepens after dusk.</p>
            </div>
          </div>
        </section>

        <!-- 5 CTA -->
        <section class="slide slide-cta" aria-label="Call to action">
          <p class="cta-kicker">Request the story</p>
          <h2 class="cta-title">Bring the atelier home</h2>
          <p class="cta-body">Sample the Terracotta &amp; Sage collection — hand-finished wallcoverings, cut to order.</p>
          <button type="button" class="cta-btn" id="ctaBtn">Order Samples</button>
          <div class="cta-palette-row" aria-hidden="true">
            <span class="cta-dot" id="cd-oat" style="background: var(--hue-oatmeal)"></span>
            <span class="cta-dot" id="cd-cel" style="background: var(--hue-celadon)"></span>
            <span class="cta-dot" id="cd-ter" style="background: var(--hue-terracotta)"></span>
          </div>
        </section>

      </div>
    </div>

    <div class="dots" id="dots" role="tablist" aria-label="Slides"></div>
    <p class="hint">Swipe or drag · Tap dots</p>
  </div>

  <aside class="editor" aria-label="Editable palette">
    <div class="editor-head">
      <span class="editor-title">Editable Palette</span>
      <span class="editor-note">Live · updates swatches</span>
    </div>
    <div class="swatch-controls">
      <div class="control">
        <label for="c-oatmeal">Oatmeal</label>
        <input type="color" id="c-oatmeal" value="#d4c4a8">
      </div>
      <div class="control">
        <label for="c-celadon">Celadon</label>
        <input type="color" id="c-celadon" value="#8fa890">
      </div>
      <div class="control">
        <label for="c-terracotta">Terracotta</label>
        <input type="color" id="c-terracotta" value="#c45c3e">
      </div>
    </div>
  </aside>
</main>

<script>
(function () {
  const root = document.documentElement;
  const track = document.getElementById('track');
  const carousel = document.getElementById('carousel');
  const dotsWrap = document.getElementById('dots');
  const slides = Array.from(track.children);
  const total = slides.length;
  let index = 0;
  let dragging = false;
  let startX = 0;
  let deltaX = 0;
  let width = 0;

  // Dots
  slides.forEach((_, i) => {
    const b = document.createElement('button');
    b.className = 'dot';
    b.type = 'button';
    b.setAttribute('role', 'tab');
    b.setAttribute('aria-label', 'Slide ' + (i + 1));
    b.addEventListener('click', () => go(i));
    dotsWrap.appendChild(b);
  });
  const dots = Array.from(dotsWrap.children);

  function measure() {
    width = carousel.getBoundingClientRect().width;
  }

  function go(i, animate) {
    index = Math.max(0, Math.min(total - 1, i));
    if (animate === false) track.style.transition = 'none';
    else track.style.transition = '';
    track.style.transform = 'translate3d(' + (-index * 100) + '%, 0, 0)';
    dots.forEach((d, di) => d.setAttribute('aria-current', di === index ? 'true' : 'false'));
    if (animate === false) {
      void track.offsetHeight;
      track.style.transition = '';
    }
  }

  // Pointer / touch
  function onDown(clientX) {
    dragging = true;
    startX = clientX;
    deltaX = 0;
    measure();
    track.style.transition = 'none';
  }
  function onMove(clientX) {
    if (!dragging) return;
    deltaX = clientX - startX;
    const pct = (deltaX / width) * 100;
    track.style.transform = 'translate3d(' + (-index * 100 + pct) + '%, 0, 0)';
  }
  function onUp() {
    if (!dragging) return;
    dragging = false;
    track.style.transition = '';
    const threshold = width * 0.18;
    if (deltaX < -threshold) go(index + 1);
    else if (deltaX > threshold) go(index - 1);
    else go(index);
    deltaX = 0;
  }

  carousel.addEventListener('pointerdown', (e) => {
    if (e.button !== 0) return;
    carousel.setPointerCapture(e.pointerId);
    onDown(e.clientX);
  });
  carousel.addEventListener('pointermove', (e) => onMove(e.clientX));
  carousel.addEventListener('pointerup', onUp);
  carousel.addEventListener('pointercancel', onUp);
  carousel.addEventListener('lostpointercapture', onUp);

  // Keyboard
  carousel.tabIndex = 0;
  carousel.addEventListener('keydown', (e) => {
    if (e.key === 'ArrowRight') go(index + 1);
    if (e.key === 'ArrowLeft') go(index - 1);
  });

  window.addEventListener('resize', () => { measure(); go(index, false); });

  // Editable palette
  function hexToDeep(hex, factor) {
    const h = hex.replace('#', '');
    const n = parseInt(h.length === 3 ? h.split('').map(c => c + c).join('') : h, 16);
    let r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255;
    r = Math.max(0, Math.round(r * factor));
    g = Math.max(0, Math.round(g * factor));
    b = Math.max(0, Math.round(b * factor));
    return '#' + [r, g, b].map(v => v.toString(16).padStart(2, '0')).join('');
  }

  function bindColor(inputId, cssVar, deepSelector) {
    const input = document.getElementById(inputId);
    const apply = () => {
      const v = input.value;
      root.style.setProperty(cssVar, v);
      if (deepSelector) {
        const el = document.querySelector(deepSelector);
        if (el) el.style.setProperty('--swatch-deep', hexToDeep(v, 0.78));
      }
    };
    input.addEventListener('input', apply);
    apply();
  }

  bindColor('c-oatmeal', '--hue-oatmeal', '.slide-oatmeal');
  bindColor('c-celadon', '--hue-celadon', '.slide-celadon');
  bindColor('c-terracotta', '--hue-terracotta', '.slide-terracotta');

  document.getElementById('ctaBtn').addEventListener('click', function () {
    this.textContent = 'Samples Requested';
    this.style.opacity = '0.7';
  });

  measure();
  go(0, false);
})();
</script>
</body>
</html>