Imported library

← Imported library
Free sampleMIT licence

3D ring gallery

carousel

Carousel from codrops/3DCarousel.

From prompt to live site

  1. 01

    Copy the code

    Grab every file as one text, each carrying its licence notice.

  2. 02

    Paste into your AI

    Drop it into Claude, Cursor or v0 — or straight into your own project.

  3. 03

    Launch it live

    Adapt the copy, wire your data, and ship — with the notice kept alongside.

Read the full code
3D ring gallery
codrops/3DCarousel@f354a11d1977 · 4 code file(s)

Licence notice — required by the licence; keep it with this code:

MIT License

Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Modifications (CreativePower): converted on 2026-09-30 from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js) into CreativePower's native pattern format — rewritten as plain HTML, CSS and JavaScript on design tokens, with the source's demo imagery, fonts and copy replaced by slots and token-driven defaults.

--- pattern.html ---
<!DOCTYPE html>
<!--
MIT License

Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Modifications (CreativePower): converted on 2026-09-30 from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js) into CreativePower's native pattern format — rewritten as plain HTML, CSS and JavaScript on design tokens, with the source's demo imagery, fonts and copy replaced by slots and token-driven defaults.
-->
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>3D ring gallery</title>
<style>html,body{margin:0;min-height:100%;background:#07070c}body{-webkit-font-smoothing:antialiased}</style>
<style>/* 3D ring gallery — CreativePower showpiece, converted from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js), by 2009 - 2024 Codrops, under the MIT licence. The full licence notice travels with this pattern (its library item's NOTICE.txt). */
[data-sp="ring-gallery-3d"]{
  --sp-a: var(--color-primary, #7c5cff);
  --sp-b: var(--color-secondary, #ff5c8a);
  --sp-ground: #07070c;
  --sp-ink: #f4f4f8;
  --sp-dim: color-mix(in oklab, var(--sp-ink) 62%, transparent);
  --sp-line: color-mix(in oklab, var(--sp-ink) 14%, transparent);
  --sp-radius: var(--ds-radius, 14px);
  --sp-radius-lg: var(--ds-radius-lg, 24px);
  --sp-font-display: var(--ds-font-display, "Inter", system-ui, sans-serif);
  --sp-font-body: var(--ds-font-body, "Inter", system-ui, sans-serif);
  --sp-font-mono: var(--ds-font-mono, ui-monospace, "SFMono-Regular", monospace);
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 100vh; width: 100%;
  background: radial-gradient(120% 80% at 50% -10%, color-mix(in oklab, var(--sp-a) 22%, transparent), transparent 60%),
    radial-gradient(90% 70% at 100% 110%, color-mix(in oklab, var(--sp-b) 18%, transparent), transparent 60%), var(--sp-ground);
  color: var(--sp-ink); font-family: var(--sp-font-body);
}
@supports (color: oklch(from red l c h)) {
  [data-sp="ring-gallery-3d"]{
    --sp-ground: oklch(from var(--color-on-surface, #0b0b12) min(l, 0.15) min(c, 0.04) h);
    --sp-ink: oklch(from var(--color-surface, #ffffff) max(l, 0.96) min(c, 0.02) h);
  }
}
[data-sp="ring-gallery-3d"] *, [data-sp="ring-gallery-3d"] *::before, [data-sp="ring-gallery-3d"] *::after { box-sizing: border-box; }
[data-sp="ring-gallery-3d"] :focus-visible { outline: 2px solid var(--sp-ink); outline-offset: 3px; }
[data-sp="ring-gallery-3d"] .sp-art { position: relative; margin: 0; overflow: hidden; background-color: var(--sp-ground); }
[data-sp="ring-gallery-3d"] .sp-art > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
[data-sp="ring-gallery-3d"] .sp-art::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .22; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"); }
[data-sp="ring-gallery-3d"] .sp-art:has(> img)::after { display: none; }
[data-sp="ring-gallery-3d"] .sp-art[data-art="1"] { background-image: radial-gradient(120% 90% at 18% 12%, color-mix(in oklab, var(--sp-a) 92%, white 8%), transparent 58%), radial-gradient(90% 80% at 88% 92%, var(--sp-b), transparent 62%), linear-gradient(160deg, color-mix(in oklab, var(--sp-a) 40%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="2"] { background-image: conic-gradient(from 210deg at 70% 30%, var(--sp-b), color-mix(in oklab, var(--sp-a) 70%, var(--sp-b)), var(--sp-a), var(--sp-b)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="3"] { background-image: radial-gradient(60% 60% at 50% 40%, color-mix(in oklab, var(--sp-ink) 55%, var(--sp-a)), transparent 62%), linear-gradient(200deg, var(--sp-a), color-mix(in oklab, var(--sp-a) 30%, var(--sp-ground)) 70%); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="4"] { background-image: radial-gradient(80% 70% at 30% 80%, var(--sp-b), transparent 60%), radial-gradient(70% 60% at 75% 20%, color-mix(in oklab, var(--sp-b) 40%, var(--sp-ink)), transparent 55%), linear-gradient(20deg, color-mix(in oklab, var(--sp-b) 35%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="5"] { background-image: repeating-linear-gradient(115deg, color-mix(in oklab, var(--sp-a) 85%, transparent) 0 14%, color-mix(in oklab, var(--sp-b) 80%, transparent) 14% 26%, transparent 26% 34%), linear-gradient(180deg, color-mix(in oklab, var(--sp-a) 30%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="6"] { background-image: radial-gradient(40% 40% at 50% 55%, color-mix(in oklab, var(--sp-b) 85%, white 15%), transparent 70%), radial-gradient(100% 100% at 50% 100%, var(--sp-a), transparent 70%), linear-gradient(0deg, color-mix(in oklab, var(--sp-a) 30%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="7"] { background-image: linear-gradient(135deg, var(--sp-a) 0%, color-mix(in oklab, var(--sp-a) 50%, var(--sp-b)) 45%, var(--sp-b) 100%); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="8"] { background-image: radial-gradient(90% 60% at 50% 0%, color-mix(in oklab, var(--sp-ink) 35%, var(--sp-b)), transparent 60%), radial-gradient(120% 90% at 0% 100%, var(--sp-a), transparent 60%), linear-gradient(90deg, color-mix(in oklab, var(--sp-b) 40%, var(--sp-ground)), var(--sp-ground)); }
@media (prefers-reduced-motion: reduce) {
  [data-sp="ring-gallery-3d"] *, [data-sp="ring-gallery-3d"] *::before, [data-sp="ring-gallery-3d"] *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}
.rg-head{position:absolute;top:6vh;left:0;right:0;z-index:5;text-align:center;padding:0 24px;pointer-events:none}
.rg-eyebrow{font:500 12px/1 var(--sp-font-mono);letter-spacing:.3em;text-transform:uppercase;color:var(--sp-dim);margin:0 0 14px}
.rg-title{font:var(--ds-display-weight,600) clamp(28px,4.2vw,58px)/1 var(--sp-font-display);letter-spacing:var(--ds-display-tracking,-.025em);margin:0;
  background:linear-gradient(180deg,var(--sp-ink),color-mix(in oklab,var(--sp-ink) 50%,var(--sp-a)));-webkit-background-clip:text;background-clip:text;color:transparent}
.rg{position:absolute;inset:0}
.rg-floor{position:absolute;left:50%;top:60%;width:min(1100px,92vw);height:46vh;transform:translate(-50%,0);pointer-events:none;
  background:radial-gradient(50% 50% at 50% 30%,color-mix(in oklab,var(--sp-a) 30%,transparent),transparent 70%);filter:blur(10px);opacity:.8}
.rg-scene{position:absolute;inset:0;perspective:900px;perspective-origin:50% 22%;cursor:grab;touch-action:pan-y;outline:none}
.rg-scene:focus-visible{outline:2px solid var(--sp-ink);outline-offset:-12px;border-radius:var(--sp-radius-lg)}
.rg.is-dragging .rg-scene{cursor:grabbing}
.rg-ring{position:absolute;left:50%;top:57%;width:0;height:0;transform-style:preserve-3d;will-change:transform}
.rg-cell{position:absolute;left:0;top:0;width:var(--rg-w,220px);aspect-ratio:3/4;margin:calc(var(--rg-w,220px) * -.6667) 0 0 calc(var(--rg-w,220px) * -.5);transform-style:preserve-3d}
.rg-card{position:absolute;inset:0;transform-style:preserve-3d;will-change:transform,filter}
.rg-face{position:absolute;inset:0;border-radius:var(--sp-radius-lg);overflow:hidden;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  box-shadow:0 30px 60px -28px rgb(0 0 0/.8),inset 0 0 0 1px var(--sp-line)}
.rg-face .sp-art{position:absolute;inset:0}
.rg-back{transform:rotateY(180deg)}
.rg-back .sp-art{filter:saturate(.7) brightness(.42)}
.rg-back::before{content:"";position:absolute;inset:0;z-index:1;background:repeating-linear-gradient(90deg,transparent 0 10px,rgb(0 0 0/.18) 10px 11px)}
.rg-cap{position:absolute;left:0;right:0;bottom:0;padding:16px 18px;display:grid;gap:6px;background:linear-gradient(180deg,transparent,rgb(0 0 0/.6))}
.rg-cap span{font:500 11px/1 var(--sp-font-mono);letter-spacing:.2em;color:var(--sp-dim)}
.rg-cap strong{font:600 clamp(15px,1.5vw,20px)/1.1 var(--sp-font-display);color:var(--sp-ink)}
.rg-ui{position:absolute;bottom:5vh;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:16px;z-index:5}
.rg-btn{width:46px;height:46px;border-radius:999px;border:1px solid var(--sp-line);background:color-mix(in oklab,var(--sp-ink) 8%,transparent);
  color:var(--sp-ink);display:grid;place-items:center;cursor:pointer;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:background .2s}
.rg-btn:hover{background:color-mix(in oklab,var(--sp-ink) 18%,transparent)}
.rg-btn svg{width:18px;height:18px}
.rg-count{min-width:92px;text-align:center;font:500 13px/1 var(--sp-font-mono);letter-spacing:.18em;color:var(--sp-dim)}
.rg-count b{color:var(--sp-ink);font-weight:600}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}</style>
</head><body>
<main class="sp-stage" data-sp="ring-gallery-3d">
<header class="rg-head">
  <p class="rg-eyebrow" data-slot="eyebrow">Selected work · 2026</p>
  <h2 class="rg-title" data-slot="title">Ten rooms, one turn</h2>
</header>
<section class="rg" aria-roledescription="carousel" aria-label="Ring gallery">
  <div class="rg-floor"></div>
  <div class="rg-scene" tabindex="0" aria-label="Gallery ring — drag, scroll or use the arrow keys">
    <div class="rg-ring">
      <article class="rg-cell" aria-roledescription="slide" aria-label="1 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="1"></figure>
            <div class="rg-cap"><span data-slot="label">01</span><strong data-slot="title">Quiet harbour</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="1"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="2 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="2"></figure>
            <div class="rg-cap"><span data-slot="label">02</span><strong data-slot="title">Glass orchard</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="2"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="3 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="3"></figure>
            <div class="rg-cap"><span data-slot="label">03</span><strong data-slot="title">Ember road</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="3"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="4 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="4"></figure>
            <div class="rg-cap"><span data-slot="label">04</span><strong data-slot="title">Tidal hall</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="4"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="5 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="5"></figure>
            <div class="rg-cap"><span data-slot="label">05</span><strong data-slot="title">Paper moon</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="5"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="6 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="6"></figure>
            <div class="rg-cap"><span data-slot="label">06</span><strong data-slot="title">Blue hour</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="6"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="7 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="7"></figure>
            <div class="rg-cap"><span data-slot="label">07</span><strong data-slot="title">Stone garden</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="7"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="8 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="8"></figure>
            <div class="rg-cap"><span data-slot="label">08</span><strong data-slot="title">Violet mile</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="8"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="9 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="1"></figure>
            <div class="rg-cap"><span data-slot="label">09</span><strong data-slot="title">Salt flats</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="1"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="10 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="2"></figure>
            <div class="rg-cap"><span data-slot="label">10</span><strong data-slot="title">Late summer</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="2"></figure></div>
        </div>
      </article>
    </div>
  </div>
  <p class="sr-only" aria-live="polite"></p>
  <div class="rg-ui">
    <button class="rg-btn" type="button" data-dir="-1" aria-label="Previous card"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg></button>
    <p class="rg-count" aria-hidden="true"><b>01</b> / 10</p>
    <button class="rg-btn" type="button" data-dir="1" aria-label="Next card"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg></button>
  </div>
</section>
</main>

<script>// 3D ring gallery — CreativePower showpiece, converted from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js), by 2009 - 2024 Codrops, under the MIT licence. The full licence notice travels with this pattern (its library item's NOTICE.txt).
(function(){
  var root = document.querySelector('[data-sp="ring-gallery-3d"]');
  if (!root) return;
  var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  // The source's ring: cell i at rotateY(i * 360/n) translateZ(radius); the ring sits back by its radius.
  // Its scroll timeline (ring rotationY, tilt X/Z 3° -> -3°, card rotationZ 10° -> -10°, brightness falling off)
  // is ported onto the motion itself: the lag between where the ring is and where it is going (the scrub) drives
  // the tilt (up to ±3°) and the card twist (up to ±10°), so the ring leans into a turn and stands upright at rest.
  var wrap = root.querySelector('.rg');
  var scene = root.querySelector('.rg-scene');
  var ring = root.querySelector('.rg-ring');
  var cells = [].slice.call(root.querySelectorAll('.rg-cell'));
  var cards = cells.map(function (c) { return c.querySelector('.rg-card'); });
  var live = root.querySelector('[aria-live]');
  var count = root.querySelector('.rg-count b');
  var n = cells.length, STEP = 360 / n;
  var angle = 0, target = 0, radius = 0, raf = 0, startX = null, startTarget = 0, wheelTimer = 0;
  
  function measure() {
    var w = Math.max(150, Math.min(280, window.innerWidth * 0.2, window.innerHeight * 0.36));
    root.style.setProperty('--rg-w', w + 'px');
    // Cards edge to edge around the circle with a small gap: r = (w/2 + gap) / tan(pi/n).
    radius = (w / 2 + w * 0.09) / Math.tan(Math.PI / n);
    cells.forEach(function (c, i) {
      c.style.transform = 'rotateY(' + (i * STEP) + 'deg) translateZ(' + radius.toFixed(1) + 'px)';
    });
  }
  
  function paint() {
    var lag = Math.max(-1, Math.min(1, (target - angle) / STEP));
    var tilt = 3 * lag, twist = -10 * lag;
    ring.style.transform = 'translateZ(' + (-radius).toFixed(1) + 'px) rotateX(' + tilt.toFixed(2) + 'deg) rotateY(' + (-angle).toFixed(2) + 'deg) rotateZ(' + tilt.toFixed(2) + 'deg)';
    cells.forEach(function (c, i) {
      var facing = Math.cos((i * STEP - angle) * Math.PI / 180); // 1 = facing the viewer
      var bright = 0.62 + 0.5 * Math.pow(Math.max(0, facing), 3);
      cards[i].style.transform = 'rotateZ(' + (twist * (0.35 + 0.65 * Math.max(0, facing))).toFixed(2) + 'deg)';
      cards[i].style.filter = 'brightness(' + bright.toFixed(3) + ')';
    });
  }
  
  function current() { return ((Math.round(target / STEP) % n) + n) % n; }
  
  function announce() {
    var i = current();
    count.textContent = String(i + 1).padStart(2, '0');
    cells.forEach(function (c, k) { c.setAttribute('aria-hidden', k === i ? 'false' : 'true'); });
    var t = cells[i].querySelector('strong');
    live.textContent = 'Card ' + (i + 1) + ' of ' + n + (t ? ': ' + t.textContent : '');
  }
  
  function tick() {
    // ScrollSmoother's catch-up (smooth: 1) as an exponential follower.
    angle += (target - angle) * 0.085;
    if (Math.abs(target - angle) < 0.01) { angle = target; raf = 0; paint(); return; }
    paint();
    raf = requestAnimationFrame(tick);
  }
  function run() {
    if (reduced) { angle = target; paint(); return; }
    if (!raf) raf = requestAnimationFrame(tick);
  }
  function go(i) { target = i * STEP; announce(); run(); }
  function snap() { go(Math.round(target / STEP)); }
  
  root.querySelectorAll('[data-dir]').forEach(function (b) {
    b.addEventListener('click', function () { go(Math.round(target / STEP) + Number(b.getAttribute('data-dir'))); });
  });
  scene.addEventListener('keydown', function (e) {
    var k = Math.round(target / STEP), base = k - current();
    if (e.key === 'ArrowRight') { go(k + 1); e.preventDefault(); }
    else if (e.key === 'ArrowLeft') { go(k - 1); e.preventDefault(); }
    else if (e.key === 'Home') { go(base); e.preventDefault(); }
    else if (e.key === 'End') { go(base + n - 1); e.preventDefault(); }
  });
  scene.addEventListener('pointerdown', function (e) {
    startX = e.clientX; startTarget = target; wrap.classList.add('is-dragging'); scene.setPointerCapture(e.pointerId);
  });
  scene.addEventListener('pointermove', function (e) {
    if (startX === null) return;
    target = startTarget - (e.clientX - startX) * 0.22;
    run();
  });
  function endDrag() {
    if (startX === null) return;
    startX = null; wrap.classList.remove('is-dragging'); snap();
  }
  scene.addEventListener('pointerup', endDrag);
  scene.addEventListener('pointercancel', endDrag);
  if (!reduced) {
    scene.addEventListener('wheel', function (e) {
      e.preventDefault();
      target += (Math.abs(e.deltaY) > Math.abs(e.deltaX) ? e.deltaY : e.deltaX) * 0.12;
      run();
      clearTimeout(wheelTimer);
      wheelTimer = setTimeout(snap, 160);
    }, { passive: false });
  }
  window.addEventListener('resize', function () { measure(); paint(); });
  measure();
  angle = target;
  paint();
  announce();
})();</script>
</body></html>

--- pattern.css ---
/*!
MIT License

Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Modifications (CreativePower): converted on 2026-09-30 from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js) into CreativePower's native pattern format — rewritten as plain HTML, CSS and JavaScript on design tokens, with the source's demo imagery, fonts and copy replaced by slots and token-driven defaults.
*/
/* 3D ring gallery — CreativePower showpiece, converted from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js), by 2009 - 2024 Codrops, under the MIT licence. The full licence notice travels with this pattern (its library item's NOTICE.txt). */
[data-sp="ring-gallery-3d"]{
  --sp-a: var(--color-primary, #7c5cff);
  --sp-b: var(--color-secondary, #ff5c8a);
  --sp-ground: #07070c;
  --sp-ink: #f4f4f8;
  --sp-dim: color-mix(in oklab, var(--sp-ink) 62%, transparent);
  --sp-line: color-mix(in oklab, var(--sp-ink) 14%, transparent);
  --sp-radius: var(--ds-radius, 14px);
  --sp-radius-lg: var(--ds-radius-lg, 24px);
  --sp-font-display: var(--ds-font-display, "Inter", system-ui, sans-serif);
  --sp-font-body: var(--ds-font-body, "Inter", system-ui, sans-serif);
  --sp-font-mono: var(--ds-font-mono, ui-monospace, "SFMono-Regular", monospace);
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 100vh; width: 100%;
  background: radial-gradient(120% 80% at 50% -10%, color-mix(in oklab, var(--sp-a) 22%, transparent), transparent 60%),
    radial-gradient(90% 70% at 100% 110%, color-mix(in oklab, var(--sp-b) 18%, transparent), transparent 60%), var(--sp-ground);
  color: var(--sp-ink); font-family: var(--sp-font-body);
}
@supports (color: oklch(from red l c h)) {
  [data-sp="ring-gallery-3d"]{
    --sp-ground: oklch(from var(--color-on-surface, #0b0b12) min(l, 0.15) min(c, 0.04) h);
    --sp-ink: oklch(from var(--color-surface, #ffffff) max(l, 0.96) min(c, 0.02) h);
  }
}
[data-sp="ring-gallery-3d"] *, [data-sp="ring-gallery-3d"] *::before, [data-sp="ring-gallery-3d"] *::after { box-sizing: border-box; }
[data-sp="ring-gallery-3d"] :focus-visible { outline: 2px solid var(--sp-ink); outline-offset: 3px; }
[data-sp="ring-gallery-3d"] .sp-art { position: relative; margin: 0; overflow: hidden; background-color: var(--sp-ground); }
[data-sp="ring-gallery-3d"] .sp-art > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
[data-sp="ring-gallery-3d"] .sp-art::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .22; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"); }
[data-sp="ring-gallery-3d"] .sp-art:has(> img)::after { display: none; }
[data-sp="ring-gallery-3d"] .sp-art[data-art="1"] { background-image: radial-gradient(120% 90% at 18% 12%, color-mix(in oklab, var(--sp-a) 92%, white 8%), transparent 58%), radial-gradient(90% 80% at 88% 92%, var(--sp-b), transparent 62%), linear-gradient(160deg, color-mix(in oklab, var(--sp-a) 40%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="2"] { background-image: conic-gradient(from 210deg at 70% 30%, var(--sp-b), color-mix(in oklab, var(--sp-a) 70%, var(--sp-b)), var(--sp-a), var(--sp-b)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="3"] { background-image: radial-gradient(60% 60% at 50% 40%, color-mix(in oklab, var(--sp-ink) 55%, var(--sp-a)), transparent 62%), linear-gradient(200deg, var(--sp-a), color-mix(in oklab, var(--sp-a) 30%, var(--sp-ground)) 70%); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="4"] { background-image: radial-gradient(80% 70% at 30% 80%, var(--sp-b), transparent 60%), radial-gradient(70% 60% at 75% 20%, color-mix(in oklab, var(--sp-b) 40%, var(--sp-ink)), transparent 55%), linear-gradient(20deg, color-mix(in oklab, var(--sp-b) 35%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="5"] { background-image: repeating-linear-gradient(115deg, color-mix(in oklab, var(--sp-a) 85%, transparent) 0 14%, color-mix(in oklab, var(--sp-b) 80%, transparent) 14% 26%, transparent 26% 34%), linear-gradient(180deg, color-mix(in oklab, var(--sp-a) 30%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="6"] { background-image: radial-gradient(40% 40% at 50% 55%, color-mix(in oklab, var(--sp-b) 85%, white 15%), transparent 70%), radial-gradient(100% 100% at 50% 100%, var(--sp-a), transparent 70%), linear-gradient(0deg, color-mix(in oklab, var(--sp-a) 30%, var(--sp-ground)), var(--sp-ground)); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="7"] { background-image: linear-gradient(135deg, var(--sp-a) 0%, color-mix(in oklab, var(--sp-a) 50%, var(--sp-b)) 45%, var(--sp-b) 100%); }
[data-sp="ring-gallery-3d"] .sp-art[data-art="8"] { background-image: radial-gradient(90% 60% at 50% 0%, color-mix(in oklab, var(--sp-ink) 35%, var(--sp-b)), transparent 60%), radial-gradient(120% 90% at 0% 100%, var(--sp-a), transparent 60%), linear-gradient(90deg, color-mix(in oklab, var(--sp-b) 40%, var(--sp-ground)), var(--sp-ground)); }
@media (prefers-reduced-motion: reduce) {
  [data-sp="ring-gallery-3d"] *, [data-sp="ring-gallery-3d"] *::before, [data-sp="ring-gallery-3d"] *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}
.rg-head{position:absolute;top:6vh;left:0;right:0;z-index:5;text-align:center;padding:0 24px;pointer-events:none}
.rg-eyebrow{font:500 12px/1 var(--sp-font-mono);letter-spacing:.3em;text-transform:uppercase;color:var(--sp-dim);margin:0 0 14px}
.rg-title{font:var(--ds-display-weight,600) clamp(28px,4.2vw,58px)/1 var(--sp-font-display);letter-spacing:var(--ds-display-tracking,-.025em);margin:0;
  background:linear-gradient(180deg,var(--sp-ink),color-mix(in oklab,var(--sp-ink) 50%,var(--sp-a)));-webkit-background-clip:text;background-clip:text;color:transparent}
.rg{position:absolute;inset:0}
.rg-floor{position:absolute;left:50%;top:60%;width:min(1100px,92vw);height:46vh;transform:translate(-50%,0);pointer-events:none;
  background:radial-gradient(50% 50% at 50% 30%,color-mix(in oklab,var(--sp-a) 30%,transparent),transparent 70%);filter:blur(10px);opacity:.8}
.rg-scene{position:absolute;inset:0;perspective:900px;perspective-origin:50% 22%;cursor:grab;touch-action:pan-y;outline:none}
.rg-scene:focus-visible{outline:2px solid var(--sp-ink);outline-offset:-12px;border-radius:var(--sp-radius-lg)}
.rg.is-dragging .rg-scene{cursor:grabbing}
.rg-ring{position:absolute;left:50%;top:57%;width:0;height:0;transform-style:preserve-3d;will-change:transform}
.rg-cell{position:absolute;left:0;top:0;width:var(--rg-w,220px);aspect-ratio:3/4;margin:calc(var(--rg-w,220px) * -.6667) 0 0 calc(var(--rg-w,220px) * -.5);transform-style:preserve-3d}
.rg-card{position:absolute;inset:0;transform-style:preserve-3d;will-change:transform,filter}
.rg-face{position:absolute;inset:0;border-radius:var(--sp-radius-lg);overflow:hidden;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  box-shadow:0 30px 60px -28px rgb(0 0 0/.8),inset 0 0 0 1px var(--sp-line)}
.rg-face .sp-art{position:absolute;inset:0}
.rg-back{transform:rotateY(180deg)}
.rg-back .sp-art{filter:saturate(.7) brightness(.42)}
.rg-back::before{content:"";position:absolute;inset:0;z-index:1;background:repeating-linear-gradient(90deg,transparent 0 10px,rgb(0 0 0/.18) 10px 11px)}
.rg-cap{position:absolute;left:0;right:0;bottom:0;padding:16px 18px;display:grid;gap:6px;background:linear-gradient(180deg,transparent,rgb(0 0 0/.6))}
.rg-cap span{font:500 11px/1 var(--sp-font-mono);letter-spacing:.2em;color:var(--sp-dim)}
.rg-cap strong{font:600 clamp(15px,1.5vw,20px)/1.1 var(--sp-font-display);color:var(--sp-ink)}
.rg-ui{position:absolute;bottom:5vh;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:16px;z-index:5}
.rg-btn{width:46px;height:46px;border-radius:999px;border:1px solid var(--sp-line);background:color-mix(in oklab,var(--sp-ink) 8%,transparent);
  color:var(--sp-ink);display:grid;place-items:center;cursor:pointer;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:background .2s}
.rg-btn:hover{background:color-mix(in oklab,var(--sp-ink) 18%,transparent)}
.rg-btn svg{width:18px;height:18px}
.rg-count{min-width:92px;text-align:center;font:500 13px/1 var(--sp-font-mono);letter-spacing:.18em;color:var(--sp-dim)}
.rg-count b{color:var(--sp-ink);font-weight:600}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

--- pattern.js ---
/*!
MIT License

Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Modifications (CreativePower): converted on 2026-09-30 from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js) into CreativePower's native pattern format — rewritten as plain HTML, CSS and JavaScript on design tokens, with the source's demo imagery, fonts and copy replaced by slots and token-driven defaults.
*/
// 3D ring gallery — CreativePower showpiece, converted from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js), by 2009 - 2024 Codrops, under the MIT licence. The full licence notice travels with this pattern (its library item's NOTICE.txt).
(function(){
  var root = document.querySelector('[data-sp="ring-gallery-3d"]');
  if (!root) return;
  var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  // The source's ring: cell i at rotateY(i * 360/n) translateZ(radius); the ring sits back by its radius.
  // Its scroll timeline (ring rotationY, tilt X/Z 3° -> -3°, card rotationZ 10° -> -10°, brightness falling off)
  // is ported onto the motion itself: the lag between where the ring is and where it is going (the scrub) drives
  // the tilt (up to ±3°) and the card twist (up to ±10°), so the ring leans into a turn and stands upright at rest.
  var wrap = root.querySelector('.rg');
  var scene = root.querySelector('.rg-scene');
  var ring = root.querySelector('.rg-ring');
  var cells = [].slice.call(root.querySelectorAll('.rg-cell'));
  var cards = cells.map(function (c) { return c.querySelector('.rg-card'); });
  var live = root.querySelector('[aria-live]');
  var count = root.querySelector('.rg-count b');
  var n = cells.length, STEP = 360 / n;
  var angle = 0, target = 0, radius = 0, raf = 0, startX = null, startTarget = 0, wheelTimer = 0;
  
  function measure() {
    var w = Math.max(150, Math.min(280, window.innerWidth * 0.2, window.innerHeight * 0.36));
    root.style.setProperty('--rg-w', w + 'px');
    // Cards edge to edge around the circle with a small gap: r = (w/2 + gap) / tan(pi/n).
    radius = (w / 2 + w * 0.09) / Math.tan(Math.PI / n);
    cells.forEach(function (c, i) {
      c.style.transform = 'rotateY(' + (i * STEP) + 'deg) translateZ(' + radius.toFixed(1) + 'px)';
    });
  }
  
  function paint() {
    var lag = Math.max(-1, Math.min(1, (target - angle) / STEP));
    var tilt = 3 * lag, twist = -10 * lag;
    ring.style.transform = 'translateZ(' + (-radius).toFixed(1) + 'px) rotateX(' + tilt.toFixed(2) + 'deg) rotateY(' + (-angle).toFixed(2) + 'deg) rotateZ(' + tilt.toFixed(2) + 'deg)';
    cells.forEach(function (c, i) {
      var facing = Math.cos((i * STEP - angle) * Math.PI / 180); // 1 = facing the viewer
      var bright = 0.62 + 0.5 * Math.pow(Math.max(0, facing), 3);
      cards[i].style.transform = 'rotateZ(' + (twist * (0.35 + 0.65 * Math.max(0, facing))).toFixed(2) + 'deg)';
      cards[i].style.filter = 'brightness(' + bright.toFixed(3) + ')';
    });
  }
  
  function current() { return ((Math.round(target / STEP) % n) + n) % n; }
  
  function announce() {
    var i = current();
    count.textContent = String(i + 1).padStart(2, '0');
    cells.forEach(function (c, k) { c.setAttribute('aria-hidden', k === i ? 'false' : 'true'); });
    var t = cells[i].querySelector('strong');
    live.textContent = 'Card ' + (i + 1) + ' of ' + n + (t ? ': ' + t.textContent : '');
  }
  
  function tick() {
    // ScrollSmoother's catch-up (smooth: 1) as an exponential follower.
    angle += (target - angle) * 0.085;
    if (Math.abs(target - angle) < 0.01) { angle = target; raf = 0; paint(); return; }
    paint();
    raf = requestAnimationFrame(tick);
  }
  function run() {
    if (reduced) { angle = target; paint(); return; }
    if (!raf) raf = requestAnimationFrame(tick);
  }
  function go(i) { target = i * STEP; announce(); run(); }
  function snap() { go(Math.round(target / STEP)); }
  
  root.querySelectorAll('[data-dir]').forEach(function (b) {
    b.addEventListener('click', function () { go(Math.round(target / STEP) + Number(b.getAttribute('data-dir'))); });
  });
  scene.addEventListener('keydown', function (e) {
    var k = Math.round(target / STEP), base = k - current();
    if (e.key === 'ArrowRight') { go(k + 1); e.preventDefault(); }
    else if (e.key === 'ArrowLeft') { go(k - 1); e.preventDefault(); }
    else if (e.key === 'Home') { go(base); e.preventDefault(); }
    else if (e.key === 'End') { go(base + n - 1); e.preventDefault(); }
  });
  scene.addEventListener('pointerdown', function (e) {
    startX = e.clientX; startTarget = target; wrap.classList.add('is-dragging'); scene.setPointerCapture(e.pointerId);
  });
  scene.addEventListener('pointermove', function (e) {
    if (startX === null) return;
    target = startTarget - (e.clientX - startX) * 0.22;
    run();
  });
  function endDrag() {
    if (startX === null) return;
    startX = null; wrap.classList.remove('is-dragging'); snap();
  }
  scene.addEventListener('pointerup', endDrag);
  scene.addEventListener('pointercancel', endDrag);
  if (!reduced) {
    scene.addEventListener('wheel', function (e) {
      e.preventDefault();
      target += (Math.abs(e.deltaY) > Math.abs(e.deltaX) ? e.deltaY : e.deltaX) * 0.12;
      run();
      clearTimeout(wheelTimer);
      wheelTimer = setTimeout(snap, 160);
    }, { passive: false });
  }
  window.addEventListener('resize', function () { measure(); paint(); });
  measure();
  angle = target;
  paint();
  announce();
})();

--- markup.html ---
<!--
MIT License

Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Modifications (CreativePower): converted on 2026-09-30 from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js) into CreativePower's native pattern format — rewritten as plain HTML, CSS and JavaScript on design tokens, with the source's demo imagery, fonts and copy replaced by slots and token-driven defaults.
-->
<main class="sp-stage" data-sp="ring-gallery-3d">
<header class="rg-head">
  <p class="rg-eyebrow" data-slot="eyebrow">Selected work · 2026</p>
  <h2 class="rg-title" data-slot="title">Ten rooms, one turn</h2>
</header>
<section class="rg" aria-roledescription="carousel" aria-label="Ring gallery">
  <div class="rg-floor"></div>
  <div class="rg-scene" tabindex="0" aria-label="Gallery ring — drag, scroll or use the arrow keys">
    <div class="rg-ring">
      <article class="rg-cell" aria-roledescription="slide" aria-label="1 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="1"></figure>
            <div class="rg-cap"><span data-slot="label">01</span><strong data-slot="title">Quiet harbour</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="1"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="2 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="2"></figure>
            <div class="rg-cap"><span data-slot="label">02</span><strong data-slot="title">Glass orchard</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="2"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="3 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="3"></figure>
            <div class="rg-cap"><span data-slot="label">03</span><strong data-slot="title">Ember road</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="3"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="4 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="4"></figure>
            <div class="rg-cap"><span data-slot="label">04</span><strong data-slot="title">Tidal hall</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="4"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="5 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="5"></figure>
            <div class="rg-cap"><span data-slot="label">05</span><strong data-slot="title">Paper moon</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="5"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="6 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="6"></figure>
            <div class="rg-cap"><span data-slot="label">06</span><strong data-slot="title">Blue hour</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="6"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="7 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="7"></figure>
            <div class="rg-cap"><span data-slot="label">07</span><strong data-slot="title">Stone garden</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="7"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="8 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="8"></figure>
            <div class="rg-cap"><span data-slot="label">08</span><strong data-slot="title">Violet mile</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="8"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="9 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="1"></figure>
            <div class="rg-cap"><span data-slot="label">09</span><strong data-slot="title">Salt flats</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="1"></figure></div>
        </div>
      </article>
      <article class="rg-cell" aria-roledescription="slide" aria-label="10 of 10">
        <div class="rg-card">
          <div class="rg-face rg-front">
            <figure class="sp-art" data-slot="image" data-art="2"></figure>
            <div class="rg-cap"><span data-slot="label">10</span><strong data-slot="title">Late summer</strong></div>
          </div>
          <div class="rg-face rg-back" aria-hidden="true"><figure class="sp-art" data-art="2"></figure></div>
        </div>
      </article>
    </div>
  </div>
  <p class="sr-only" aria-live="polite"></p>
  <div class="rg-ui">
    <button class="rg-btn" type="button" data-dir="-1" aria-label="Previous card"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg></button>
    <p class="rg-count" aria-hidden="true"><b>01</b> / 10</p>
    <button class="rg-btn" type="button" data-dir="1" aria-label="Next card"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg></button>
  </div>
</section>
</main>
Source and licence

Source: codrops/3DCarousel@f354a11d1977

Author: 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Entry: index.html

  • Converted into the native showpiece "ring-gallery-3d" (lib/motion-patterns/showpiece/ring-gallery-3d.ts): plain HTML/CSS/JS on the design tokens, with slots for imagery and text. The shipped files are the conversion; the source files it was converted from (source.paths, at source.commit) are not shipped.
  • Source flags not carried by the conversion: hotlinked-media — https://tympanus.net/favicon/favicon.svg; commercial-font — font kit from use.typekit.net: https://use.typekit.net/ccs0evy.css; commercial-font — per repo review: loads an Adobe Fonts (Typekit) kit from use.typekit.net - commercial fonts, not covered by the MIT licence
  • Passed step 7 on 2026-09-30: render, reduced, keyboard, noTrap, tokens, slots, notice, engines (scripts/ui-blocks/check-showpiece.ts).
MIT License

Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Modifications (CreativePower): converted on 2026-09-30 from codrops/3DCarousel@f354a11d1977 (index.html, css/base.css, js/index.js) into CreativePower's native pattern format — rewritten as plain HTML, CSS and JavaScript on design tokens, with the source's demo imagery, fonts and copy replaced by slots and token-driven defaults.
Files (4)
  • pattern.html (19,965 bytes)
  • pattern.css (8,432 bytes)
  • pattern.js (5,109 bytes)
  • markup.html (6,091 bytes)

Want the whole library?

Every item's prompt, code and instructions, with a CreativePower subscription.

See plans

More carousel templates