{
  "name": "logo-reveal",
  "type": "registry:block",
  "description": "Logo mark draw-on with wordmark and tagline beats",
  "dependencies": [
    "remotion",
    "@remotion/google-fonts"
  ],
  "registryDependencies": [
    "path-draw",
    "layout",
    "motion-tokens",
    "springs"
  ],
  "files": [
    {
      "path": "registry/bases/default/scenes/logo-reveal/index.tsx",
      "type": "registry:block",
      "content": "import { loadFont } from \"@remotion/google-fonts/Inter\";\nimport { interpolate, spring, useCurrentFrame, useVideoConfig } from \"remotion\";\nimport { PathDraw } from \"@/remotion/primitives/path-draw\";\nimport { getSafeAreaPadding, scaleFont } from \"@/remotion/lib/layout\";\nimport { DELAY, DURATION, EASING, STAGGER } from \"@/remotion/lib/motion-tokens\";\nimport { springSmooth } from \"@/remotion/lib/springs\";\n\nconst { fontFamily } = loadFont(\"normal\", {\n  weights: [\"500\", \"600\"],\n  subsets: [\"latin\"],\n});\n\nexport type LogoRevealProps = {\n  /** One path, or several drawn in sequence for a multi-stroke mark. */\n  pathD: string | string[];\n  /** Omit to frame the mark automatically from its bounding box. */\n  viewBox?: string;\n  /** Mark size in pixels — defaults to a share of the frame's short edge. */\n  size?: number;\n  wordmark?: string;\n  tagline?: string;\n  stroke?: string;\n  strokeWidth?: number;\n  /** Fill flooded into the mark once the stroke closes. */\n  fill?: string;\n  backgroundColor?: string;\n};\n\nconst COLORS = {\n  bg: \"#080810\",\n  stroke: \"#e8b86d\",\n  glow: \"rgba(232,184,109,0.22)\",\n  ink: \"#f4f4f5\",\n  muted: \"rgba(244,244,245,0.6)\",\n} as const;\n\n/** Beats: bloom → mark draws → wordmark → tagline. */\nconst BEATS = {\n  mark: DELAY.short,\n  wordmark: DELAY.short + DURATION.slow,\n  tagline: DELAY.short + DURATION.slow + STAGGER.relaxed,\n} as const;\n\nexport const LogoReveal: React.FC<LogoRevealProps> = ({\n  pathD,\n  viewBox,\n  size,\n  wordmark,\n  tagline,\n  stroke = COLORS.stroke,\n  strokeWidth,\n  fill,\n  backgroundColor = COLORS.bg,\n}) => {\n  const frame = useCurrentFrame();\n  const { width, height, fps } = useVideoConfig();\n  const safeArea = getSafeAreaPadding({ width, height });\n\n  const hasCopy = Boolean(wordmark || tagline);\n  // Without a wordmark the mark carries the whole frame, so it grows to fill\n  // the space the copy would otherwise take.\n  const markSize =\n    size ?? Math.round(Math.min(width, height) * (hasCopy ? 0.4 : 0.56));\n  const lineWidth = strokeWidth ?? Math.max(2, Math.round(markSize * 0.022));\n  const drawFrames = DURATION.slow * 2;\n\n  // The bloom lands first and settles under the mark, so the frame is never\n  // empty while the stroke is still short.\n  const bloom = spring({\n    frame,\n    fps,\n    config: springSmooth,\n    durationInFrames: DURATION.slow,\n  });\n\n  const wordmarkLift = spring({\n    frame: frame - BEATS.wordmark,\n    fps,\n    config: springSmooth,\n    durationInFrames: DURATION.normal,\n  });\n  const taglineIn = interpolate(\n    frame,\n    [BEATS.tagline, BEATS.tagline + DURATION.normal],\n    [0, 1],\n    {\n      extrapolateLeft: \"clamp\",\n      extrapolateRight: \"clamp\",\n      easing: EASING.enter,\n    },\n  );\n\n  return (\n    <div\n      style={{\n        width,\n        height,\n        backgroundColor,\n        paddingLeft: safeArea.paddingLeft,\n        paddingRight: safeArea.paddingRight,\n        paddingTop: safeArea.paddingTop,\n        paddingBottom: safeArea.paddingBottom,\n        display: \"flex\",\n        flexDirection: \"column\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: scaleFont(28, width),\n        position: \"relative\",\n        fontFamily,\n      }}\n    >\n      <div\n        style={{\n          position: \"relative\",\n          display: \"flex\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          scale: 0.92 + bloom * 0.08,\n        }}\n      >\n        <div\n          style={{\n            position: \"absolute\",\n            width: markSize * 1.8,\n            height: markSize * 1.8,\n            borderRadius: \"50%\",\n            background: `radial-gradient(circle, ${COLORS.glow}, transparent 70%)`,\n            filter: `blur(${scaleFont(36, width)}px)`,\n            opacity: bloom * 0.9,\n            scale: 0.8 + bloom * 0.35,\n            pointerEvents: \"none\",\n          }}\n        />\n        <PathDraw\n          d={pathD}\n          viewBox={viewBox}\n          width={markSize}\n          height={markSize}\n          stroke={stroke}\n          strokeWidth={lineWidth}\n          fill={fill}\n          delayInFrames={BEATS.mark}\n          durationInFrames={drawFrames}\n          staggerInFrames={STAGGER.normal}\n        />\n      </div>\n\n      {wordmark ? (\n        <div\n          style={{\n            color: COLORS.ink,\n            fontSize: scaleFont(84, width),\n            fontWeight: 600,\n            lineHeight: 1,\n            letterSpacing: -0.5,\n            textAlign: \"center\",\n            opacity: wordmarkLift,\n            translate: `0 ${(1 - wordmarkLift) * scaleFont(28, width)}px`,\n          }}\n        >\n          {wordmark}\n        </div>\n      ) : null}\n\n      {tagline ? (\n        <div\n          style={{\n            color: COLORS.muted,\n            fontSize: scaleFont(40, width),\n            fontWeight: 500,\n            lineHeight: 1.2,\n            textAlign: \"center\",\n            maxWidth: width * 0.7,\n            opacity: taglineIn,\n            translate: `0 ${(1 - taglineIn) * scaleFont(16, width)}px`,\n          }}\n        >\n          {tagline}\n        </div>\n      ) : null}\n    </div>\n  );\n};\n"
    }
  ],
  "atlas": {
    "lane": "vectors",
    "drive": "time",
    "tier": "advanced"
  }
}