{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"velocity-adaptive-seam","type":"registry:block","title":"velocity-adaptive seam","description":"\"seams breathe with 240\" — rush and the transition cuts short; linger and it plays full. Juries score this pacing explicitly.","author":"Motion Menu","categories":["role-seam","seam","pacing"],"dependencies":["gsap"],"registryDependencies":[],"meta":{"number":"240","slug":"velocity-adaptive-seam","framework":"react","docs":"https://motion-menu-two.vercel.app/p/velocity-adaptive-seam.md"},"files":[{"path":"motion-menu/velocity-adaptive-seam.html","type":"registry:file","target":"motion-menu/velocity-adaptive-seam.html","content":"<article class=\"card\">\n        <header><span class=\"num\">240</span><h3>Velocity-adaptive seam</h3><div class=\"tags\"><i>pacing</i></div><a class=\"format-action\" data-format-link data-pattern-slug=\"velocity-adaptive-seam\" href=\"/r/velocity-adaptive-seam.json?framework=react\" title=\"Open the React registry output\">React ↗</a></header>\n        <div class=\"demo\" style=\"flex-direction:column; padding:1rem 1.2rem;\">\n          <div class=\"vs-outer\" id=\"vs-outer\" data-lenis-prevent>\n            <div class=\"vs-track\">\n              <div class=\"vs-stick\">\n                <div class=\"vs-panel vs-a\">ACT I</div>\n                <div class=\"vs-panel vs-b\" id=\"vs-b\">ACT II</div>\n                <div class=\"vs-wipe\" id=\"vs-wipe\"></div>\n              </div>\n            </div>\n          </div>\n          <div class=\"vs-meter\" id=\"vs-meter\">scroll in here — cross the middle slow, then fast</div>\n        </div>\n        <p class=\"order\">Say: <b>\"seams breathe with 240\"</b> — rush and the transition cuts short; linger and it plays full. Juries score this pacing explicitly.</p>\n      </article>"},{"path":"motion-menu/velocity-adaptive-seam.css","type":"registry:file","target":"motion-menu/velocity-adaptive-seam.css","content":".card {\n    border: 1px solid var(--line); border-radius: 14px; background: var(--card);\n    overflow: hidden; display: flex; flex-direction: column;\n  }\n\n.card > header { display: flex; align-items: baseline; gap: .8rem; padding: 1.1rem 1.2rem .9rem; border-bottom: 1px solid var(--line); }\n\n.card .num { font-family: var(--mono); color: var(--acc); font-size: 1.05rem; }\n\n.card h3 { font-size: 1.02rem; font-weight: 600; letter-spacing: -0.01em; flex: 1; }\n\n.tags { display: flex; gap: .35rem; }\n\n.tags i {\n    font: 400 .62rem/1 var(--mono); font-style: normal; color: var(--dim);\n    border: 1px solid var(--line); border-radius: 99px; padding: .28em .6em; white-space: nowrap;\n  }\n\n.demo {\n    min-height: 250px; position: relative; display: flex; align-items: center; justify-content: center;\n    background: var(--bg2); overflow: hidden; flex: 1;\n  }\n\n.order { padding: .85rem 1.2rem; font-family: var(--mono); font-size: .72rem; color: var(--dim); border-top: 1px solid var(--line); }\n\n.order b { color: var(--txt); font-weight: 500; }\n\n.demo .btn.corner { position: absolute; top: 12px; right: 12px; padding: .55em 1em; font-size: .68rem; z-index: 5; }\n\n.ai-card .num { color: var(--acc2) !important; }\n\n.demo:has(.hascheck input:checked) .hasbtn { border-color: var(--acc); color: var(--acc); pointer-events: auto; opacity: 1; }\n\n/* ---------- seams & handoffs · 240–247 ---------- */\n  /* 240 velocity-adaptive seam */\n  .vs-outer { width: 100%; height: 260px; overflow-y: auto; border-radius: 12px; background: #08080d; }\n\n.vs-track { height: 900px; }\n\n.vs-stick { position: sticky; top: 0; height: 260px; overflow: hidden; }\n\n.vs-panel { position: absolute; inset: 0; display: grid; place-items: center; font: 700 1.4rem var(--mono); letter-spacing: .1em; }\n\n.vs-a { background: linear-gradient(150deg, #14212e, #0a0f16); color: #7fd8ff; }\n\n.vs-b { background: linear-gradient(150deg, #1d2a14, #0d1208); color: var(--acc); opacity: 0; }\n\n.vs-wipe { position: absolute; inset: 0; background: #e8e8ee; transform: scaleY(0); transform-origin: top; z-index: 3; }\n\n.vs-meter { margin-top: .6rem; font: 600 .66rem var(--mono); color: var(--dim); text-align: center; min-height: 1.2em; }\n\n.vs-meter b { color: var(--acc); }"},{"path":"components/motion-menu/velocity-adaptive-seam.tsx","type":"registry:component","content":"// @ts-nocheck — generated wrapper; inlined pattern JS is imperative DOM code, not authored TS.\n\"use client\";\n// velocity-adaptive seam — Motion Menu\nimport { useEffect, useRef } from \"react\";\n\nconst MARKUP = \"<article class=\\\"card\\\">\\n        <header><span class=\\\"num\\\">240</span><h3>Velocity-adaptive seam</h3><div class=\\\"tags\\\"><i>pacing</i></div><a class=\\\"format-action\\\" data-format-link data-pattern-slug=\\\"velocity-adaptive-seam\\\" href=\\\"/r/velocity-adaptive-seam.json?framework=react\\\" title=\\\"Open the React registry output\\\">React \\u2197</a></header>\\n        <div class=\\\"demo\\\" style=\\\"flex-direction:column; padding:1rem 1.2rem;\\\">\\n          <div class=\\\"vs-outer\\\" id=\\\"vs-outer\\\" data-lenis-prevent>\\n            <div class=\\\"vs-track\\\">\\n              <div class=\\\"vs-stick\\\">\\n                <div class=\\\"vs-panel vs-a\\\">ACT I</div>\\n                <div class=\\\"vs-panel vs-b\\\" id=\\\"vs-b\\\">ACT II</div>\\n                <div class=\\\"vs-wipe\\\" id=\\\"vs-wipe\\\"></div>\\n              </div>\\n            </div>\\n          </div>\\n          <div class=\\\"vs-meter\\\" id=\\\"vs-meter\\\">scroll in here \\u2014 cross the middle slow, then fast</div>\\n        </div>\\n        <p class=\\\"order\\\">Say: <b>\\\"seams breathe with 240\\\"</b> \\u2014 rush and the transition cuts short; linger and it plays full. Juries score this pacing explicitly.</p>\\n      </article>\";\n\nexport function VelocityAdaptiveSeam() {\n  const hostRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const host = hostRef.current;\n    if (!host) return;\n    const $ = (s: string) => host.querySelector(s) as HTMLElement | null;\n    let disposed = false;\n    const cleanup: Array<() => void> = [];\n\n    (async () => {\n      if (disposed) return;\n      try {\n        /* ---- 240 · velocity-adaptive seam ---- */\n        {\n          const outer = document.getElementById('vs-outer');\n          const wipe = document.getElementById('vs-wipe');\n          const b = document.getElementById('vs-b');\n          const meter = document.getElementById('vs-meter');\n          let lastTop = 0, lastT = 0, vel = 0, sideB = false, animating = false;\n          outer.addEventListener('scroll', () => {\n            const now = performance.now();\n            const dt = Math.max(now - lastT, 1);\n            vel = vel * 0.7 + (Math.abs(outer.scrollTop - lastTop) / dt) * 1000 * 0.3;\n            lastTop = outer.scrollTop; lastT = now;\n            const max = outer.scrollHeight - outer.clientHeight;\n            const p = max ? outer.scrollTop / max : 0;\n            const wantB = p > 0.5;\n            if (wantB !== sideB && !animating) {\n              sideB = wantB;\n              animating = true;\n              const dur = Math.max(0.14, 0.6 - vel * 0.00028);\n              meter.innerHTML = `crossed at ≈${Math.round(vel)} px/s → seam ran <b>${Math.round(dur * 1000)}ms</b>`;\n              wipe.style.transformOrigin = wantB ? 'top' : 'bottom';\n              gsap.timeline({ onComplete: () => { animating = false; } })\n                .fromTo(wipe, { scaleY: 0 }, { scaleY: 1, duration: dur / 2, ease: 'power2.in' })\n                .set(b, { opacity: wantB ? 1 : 0 })\n                .set(wipe, { transformOrigin: wantB ? 'bottom' : 'top' })\n                .to(wipe, { scaleY: 0, duration: dur / 2, ease: 'power2.out' });\n            }\n          }, { passive: true });\n        }\n      } catch (err: any) {\n        console.warn(\"[motion-menu] velocity-adaptive-seam failed to start:\", err);\n      }\n    })();\n\n    return () => {\n      disposed = true;\n      cleanup.forEach((fn) => { try { fn(); } catch (_) {} });\n    };\n  }, []);\n\n  return <div ref={hostRef} dangerouslySetInnerHTML={{ __html: MARKUP }} />;\n}\n\nexport default VelocityAdaptiveSeam;\n"}]}