Floating Folders CTA
A closing call-to-action: centered headline and primary button, surrounded by colorful glass folders that float gently and shift with a subtle parallax as the pointer moves.
Taken from the page template Nook Mac App Website. Use it on its own, or combine it with the other components from the same template to rebuild the full page.
Plain HTML, CSS and a little vanilla JS, with no framework dependency. Copy the prompt into Claude Code, Cursor, Trae or Codex and the model adds Floating Folders CTA to your project in your colors.
Where to use it
The hero of a product site, SaaS landing page or campaign page: where the headline, subhead and primary button make the first impression.
Install
With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.
Code
Source for Floating Folders CTA. Motion uses only transform and opacity and respects the Reduce motion setting.
<section class="x-ffc"> <div class="x-ffc__bg" aria-hidden="true"></div> <h2><span>Give your files</span><span>a good home.</span></h2> <p>Nook Launch price ¥88, regularly ¥148, one-time purchase.</p> <a class="x-ffc__btn" href="#" role="button">Buy Nook · ¥88</a> </section>
.x-ffc{position:relative;isolation:isolate;overflow:hidden;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(10px,3.4cqi,22px);width:100%;height:100%;min-height:220px;padding:24px;box-sizing:border-box;container-type:size;text-align:center;background:var(--d-bg,#09090d);color:var(--d-fg,#fff);font-family:var(--d-font,system-ui,sans-serif)}
.x-ffc h2{margin:0;font-size:clamp(26px,9cqi,72px);font-weight:700;letter-spacing:-.04em;line-height:1.05}
.x-ffc h2 span{display:inline-block}
.x-ffc p{margin:0;font-size:clamp(12px,2.6cqi,17px);color:var(--d-muted,#9b9ba8)}
.x-ffc__btn{display:inline-flex;align-items:center;height:clamp(38px,8cqi,52px);padding:0 clamp(18px,4.4cqi,30px);border-radius:99px;background:var(--d-accent,#4D74FF);color:#fff;font-size:clamp(13px,2.5cqi,16px);font-weight:600;text-decoration:none;box-shadow:0 8px 24px color-mix(in srgb,var(--d-accent,#4D74FF) 40%,transparent);transition:transform .2s}
.x-ffc__btn:hover{transform:translateY(-1px)}.x-ffc__btn:active{transform:scale(.97)}
.x-ffc__btn:focus-visible{outline:2px solid var(--d-accent,#4D74FF);outline-offset:3px}
.x-ffc__bg{position:absolute;inset:0;z-index:-1;pointer-events:none;transform:translate(var(--px,0),var(--py,0));transition:transform .6s cubic-bezier(.16,1,.3,1)}
.x-ffc__f{position:absolute;width:clamp(48px,13cqi,96px);aspect-ratio:96/80;margin:-6% 0 0 -6%;opacity:.6;animation:x-ffc-fl 9s ease-in-out infinite}
.x-ffc__f svg{position:absolute;inset:0;width:100%;height:100%}
.x-ffc__f svg path{fill:color-mix(in srgb,var(--h) 78%,#000)}
.x-ffc__f i{position:absolute;left:3%;right:3%;bottom:1%;height:65%;border-radius:12%/18%;border:1px solid rgba(255,255,255,.7);background:linear-gradient(149deg,color-mix(in srgb,var(--h) 45%,rgba(255,255,255,.6)),color-mix(in srgb,var(--h) 75%,transparent));box-shadow:inset 0 1px 0 rgba(255,255,255,.55)}
…const init = (root) => {
const sec = root.querySelector('.x-ffc'), bg = sec.querySelector('.x-ffc__bg');
const F = [['9%', '18%', '#3D5BF0', 0], ['86%', '14%', '#CC528A', 1.5], ['13%', '70%', '#E08A1E', 3], ['82%', '66%', '#2E9E5B', 4.5], ['48%', '90%', '#7B61E8', 2], ['94%', '92%', '#2A9BB3', 6]];
bg.innerHTML = F.map(([x, y, c, d]) => `<span class="x-ffc__f" style="left:${x};top:${y};--h:${c};animation-delay:-${d}s"><svg viewBox="0 0 100 80"><path d="M4 10a7 7 0 0 1 7-7h25l8 8h45a7 7 0 0 1 7 7v54a7 7 0 0 1-7 7H11a7 7 0 0 1-7-7z"/></svg><b></b><i></i></span>`).join('');
sec.querySelector('.x-ffc__btn').addEventListener('click', (e) => e.preventDefault());
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const move = (e) => { const r = sec.getBoundingClientRect(); const dx = (e.clientX - r.left) / r.width - .5, dy = (e.clientY - r.top) / r.height - .5;
bg.style.setProperty('--px', (-dx * 16).toFixed(1) + 'px'); bg.style.setProperty('--py', (-dy * 12).toFixed(1) + 'px'); };
const reset = () => { bg.style.setProperty('--px', '0px'); bg.style.setProperty('--py', '0px'); };
sec.addEventListener('pointermove', move); sec.addEventListener('pointerleave', reset);
};