{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "orbit-lock",
  "title": "Orbit Lock",
  "description": "Three moons ride tilted, shrinking orbits into a red core that bursts into a ring flash and springs the logo into place.",
  "dependencies": ["remotion"],
  "files": [
    {
      "path": "registry/remocn/orbit-lock/index.tsx",
      "content": "\"use client\";\n\nimport type React from \"react\";\nimport { useId } from \"react\";\nimport {\n  AbsoluteFill,\n  Easing,\n  interpolate,\n  interpolateColors,\n  spring,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\n\nexport type OrbitLockProps = {\n  /** Lockup revealed after the moons collide with the core. Falls back to a placeholder \"remocn\" lockup. */\n  children?: React.ReactNode;\n  /** Number of moons orbiting the core. */\n  moons?: number;\n  backgroundColor?: string;\n  coreColor?: string;\n  moonColor?: string;\n  /** Ring flash released on impact. */\n  flashColor?: string;\n  /** Orbit tilt in degrees: 0 is a flat circle, 80 is nearly edge-on. */\n  tilt?: number;\n  speed?: number;\n};\n\nexport const orbitLockDefaults = {\n  moons: 3,\n  backgroundColor: \"#111111\",\n  coreColor: \"#E5322D\",\n  moonColor: \"#FFFFFF\",\n  flashColor: \"#FFFFFF\",\n  tilt: 64,\n  speed: 1,\n};\n\nconst IMPACT = 30;\nconst TURNS = 1.9;\nconst TRAIL = 10;\nconst TRAIL_STEP = 0.4;\nconst clamp = {\n  extrapolateLeft: \"clamp\" as const,\n  extrapolateRight: \"clamp\" as const,\n};\n\ntype Moon = { x: number; y: number; z: number };\n\nfunction moonAt(\n  t: number,\n  index: number,\n  count: number,\n  outer: number,\n  inner: number,\n  tilt: number,\n): Moon {\n  const p = Math.min(1, Math.max(0, t / IMPACT));\n  // Orbit radius collapses late; angular speed ramps up as it tightens.\n  const r = inner + (outer - inner) * (1 - Easing.in(Easing.cubic)(p));\n  const theta =\n    (index / count) * Math.PI * 2 +\n    Math.PI * 2 * TURNS * Easing.in(Easing.quad)(p);\n  const plane = (index / count) * Math.PI + Math.PI / 9;\n  const lx = r * Math.cos(theta);\n  const ly = r * Math.sin(theta) * Math.cos(tilt);\n  return {\n    x: lx * Math.cos(plane) - ly * Math.sin(plane),\n    y: lx * Math.sin(plane) + ly * Math.cos(plane),\n    z: r * Math.sin(theta) * Math.sin(tilt),\n  };\n}\n\nconst PLACEHOLDER_FONT =\n  \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Helvetica, Arial, sans-serif\";\n\n// Neutral lockup shown when no children are passed.\nfunction PlaceholderLockup({\n  mark,\n  dot,\n  text,\n  scale = 1,\n}: {\n  mark: string;\n  dot: string;\n  text: string;\n  scale?: number;\n}) {\n  return (\n    <div style={{ display: \"flex\", alignItems: \"center\", gap: 28 * scale }}>\n      <div\n        style={{\n          width: 120 * scale,\n          height: 120 * scale,\n          borderRadius: 32 * scale,\n          backgroundColor: mark,\n          display: \"flex\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n        }}\n      >\n        <div\n          style={{\n            width: 36 * scale,\n            height: 36 * scale,\n            borderRadius: \"50%\",\n            backgroundColor: dot,\n          }}\n        />\n      </div>\n      <span\n        style={{\n          fontFamily: PLACEHOLDER_FONT,\n          fontSize: 104 * scale,\n          fontWeight: 800,\n          letterSpacing: \"-0.04em\",\n          color: text,\n        }}\n      >\n        remocn\n      </span>\n    </div>\n  );\n}\n\nexport function OrbitLock(props: OrbitLockProps) {\n  const {\n    children,\n    moons,\n    backgroundColor,\n    coreColor,\n    moonColor,\n    flashColor,\n    tilt,\n    speed,\n  } = { ...orbitLockDefaults, ...props };\n  const uid = `orbit-lock-${useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n  const frame = useCurrentFrame();\n  const { width, height, fps } = useVideoConfig();\n  const t = frame * Math.max(0, speed);\n  const s = Math.min(width, height);\n  const cx = width / 2;\n  const cy = height / 2;\n  const count = Math.max(1, Math.round(moons));\n  const tiltRad = (Math.min(85, Math.max(0, tilt)) * Math.PI) / 180;\n\n  const core = s * 0.055;\n  const outer = s * 0.36;\n  const moonR = s * 0.02;\n  const p = Math.min(1, t / IMPACT);\n\n  const corePulse = 1 + 0.3 * p ** 4;\n  const burst = interpolate(t, [IMPACT, IMPACT + 2, IMPACT + 6], [1, 1.6, 0], {\n    ...clamp,\n    easing: Easing.out(Easing.cubic),\n  });\n  const coreScale = t < IMPACT ? corePulse : corePulse * burst;\n  const coreFill = interpolateColors(\n    t,\n    [IMPACT - 2, IMPACT + 1],\n    [coreColor, flashColor],\n  );\n\n  const ring = interpolate(t, [IMPACT, IMPACT + 16], [0, 1], {\n    ...clamp,\n    easing: Easing.out(Easing.cubic),\n  });\n  const ringVisible = t >= IMPACT && ring < 1;\n  const orbitOpacity = interpolate(\n    t,\n    [0, 6, IMPACT - 4, IMPACT],\n    [0, 0.16, 0.1, 0],\n    clamp,\n  );\n  const orbitR = core + (outer - core) * (1 - Easing.in(Easing.cubic)(p));\n\n  const pop = spring({\n    frame: t - IMPACT - 3,\n    fps,\n    config: { damping: 11, stiffness: 170, mass: 0.7 },\n  });\n\n  const bodies = Array.from({ length: count }, (_, i) => {\n    const head = moonAt(t, i, count, outer, core, tiltRad);\n    const trail = Array.from({ length: TRAIL }, (_, k) =>\n      moonAt(t - (k + 1) * TRAIL_STEP, i, count, outer, core, tiltRad),\n    );\n    return { i, head, trail };\n  });\n  const showMoons = t < IMPACT && t >= 0;\n  const appear = interpolate(t, [0, 5], [0, 1], clamp);\n\n  const renderMoon = ({ i, head, trail }: (typeof bodies)[number]) => {\n    const depth = 1 + (0.18 * head.z) / outer;\n    const points = [head, ...trail];\n    // Tapered ribbon through the recent positions, fading toward the tail.\n    const left: string[] = [];\n    const right: string[] = [];\n    points.forEach((pt, k) => {\n      const prev = points[Math.max(0, k - 1)];\n      const next = points[Math.min(points.length - 1, k + 1)];\n      const dx = prev.x - next.x;\n      const dy = prev.y - next.y;\n      const len = Math.hypot(dx, dy) || 1;\n      const half = moonR * depth * 0.9 * (1 - k / points.length);\n      const nx = (-dy / len) * half;\n      const ny = (dx / len) * half;\n      left.push(`${cx + pt.x + nx},${cy + pt.y + ny}`);\n      right.unshift(`${cx + pt.x - nx},${cy + pt.y - ny}`);\n    });\n    const tail = points[points.length - 1];\n    const gradId = `${uid}-trail-${i}`;\n    return (\n      <g key={i} opacity={appear}>\n        <defs>\n          <linearGradient\n            id={gradId}\n            gradientUnits=\"userSpaceOnUse\"\n            x1={cx + head.x}\n            y1={cy + head.y}\n            x2={cx + tail.x}\n            y2={cy + tail.y}\n          >\n            <stop offset=\"0\" stopColor={moonColor} stopOpacity={0.6} />\n            <stop offset=\"1\" stopColor={moonColor} stopOpacity={0} />\n          </linearGradient>\n        </defs>\n        <polygon\n          points={[...left, ...right].join(\" \")}\n          fill={`url(#${gradId})`}\n        />\n        <circle\n          cx={cx + head.x}\n          cy={cy + head.y}\n          r={moonR * depth}\n          fill={moonColor}\n        />\n      </g>\n    );\n  };\n\n  return (\n    <AbsoluteFill style={{ backgroundColor }}>\n      <svg\n        width={width}\n        height={height}\n        viewBox={`0 0 ${width} ${height}`}\n        style={{ position: \"absolute\", inset: 0 }}\n      >\n        {Array.from({ length: count }, (_, i) => (\n          <ellipse\n            key={i}\n            cx={cx}\n            cy={cy}\n            rx={orbitR}\n            ry={orbitR * Math.cos(tiltRad)}\n            transform={`rotate(${(i / count) * 180 + 20} ${cx} ${cy})`}\n            fill=\"none\"\n            stroke={moonColor}\n            strokeOpacity={orbitOpacity}\n            strokeWidth={1.5}\n          />\n        ))}\n        {showMoons && bodies.filter((b) => b.head.z < 0).map(renderMoon)}\n        {coreScale > 0 && (\n          <circle\n            cx={cx}\n            cy={cy}\n            r={core * coreScale * appear}\n            fill={coreFill}\n          />\n        )}\n        {showMoons && bodies.filter((b) => b.head.z >= 0).map(renderMoon)}\n        {ringVisible && (\n          <circle\n            cx={cx}\n            cy={cy}\n            r={core + ring * s * 0.62}\n            fill=\"none\"\n            stroke={flashColor}\n            strokeWidth={Math.max(1, s * 0.03 * (1 - ring))}\n            opacity={1 - ring}\n          />\n        )}\n      </svg>\n      <AbsoluteFill\n        style={{\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          opacity: interpolate(t, [IMPACT + 3, IMPACT + 6], [0, 1], clamp),\n          transform: `scale(${0.55 + 0.45 * pop})`,\n        }}\n      >\n        {children ?? (\n          <PlaceholderLockup\n            mark={coreColor}\n            dot={backgroundColor}\n            text={moonColor}\n          />\n        )}\n      </AbsoluteFill>\n    </AbsoluteFill>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/orbit-lock.tsx"
    }
  ],
  "type": "registry:component"
}
