{
  "name": "pricing-focus",
  "type": "registry:block",
  "description": "Pricing tier focus animation",
  "dependencies": [
    "remotion"
  ],
  "registryDependencies": [
    "layout",
    "timing"
  ],
  "composition": {
    "id": "PricingFocus",
    "component": "PricingFocus",
    "durationInFrames": 180,
    "fps": 30,
    "width": 1920,
    "height": 1080,
    "importPath": "@/compositions/pricing-focus/index"
  },
  "files": [
    {
      "path": "registry/bases/default/compositions/pricing-focus/index.tsx",
      "type": "registry:block",
      "content": "import { AbsoluteFill, interpolate, useCurrentFrame, useVideoConfig } from \"remotion\";\nimport { getSafeAreaPadding, scaleFont } from \"@/remotion/lib/layout\";\nimport { EASING_ENTER, EASING_EXIT } from \"@/remotion/lib/timing\";\n\nexport type PricingFocusProps = {\n  tiers?: Array<{ name: string; price: string; featured?: boolean }>;\n};\n\nconst DEFAULT_TIERS = [\n  { name: \"Starter\", price: \"$0\" },\n  { name: \"Studio\", price: \"$29\", featured: true },\n  { name: \"Team\", price: \"$99\" },\n];\n\n/** Featured card locks focus over this window — non-featured cards defocus in step. */\nconst FOCUS_START = 30;\nconst FOCUS_END = 50;\n\n/** Exit beat: cards leave staggered, featured card last so it holds the eye longest. */\nconst EXIT_START = 138;\nconst EXIT_STAGGER = 6;\nconst EXIT_DURATION = 30;\n\nexport const PricingFocus: React.FC<PricingFocusProps> = ({\n  tiers = DEFAULT_TIERS,\n}) => {\n  const frame = useCurrentFrame();\n  const { width, height } = useVideoConfig();\n  const safe = getSafeAreaPadding({ width, height });\n  const focusIndex = tiers.findIndex((t) => t.featured);\n\n  // Shared focus progress — drives the defocus of non-featured cards once the\n  // featured card locks in. Computed once (not per-card) so the \"always 0\"\n  // dead-code trap (blur keyed to a per-card value only set for the featured\n  // card) can't recur.\n  const focus = interpolate(frame, [FOCUS_START, FOCUS_END], [0, 1], {\n    easing: EASING_ENTER,\n    extrapolateLeft: \"clamp\",\n    extrapolateRight: \"clamp\",\n  });\n\n  // Gentle breathing on the featured card during the hold, so the still beat\n  // reads as alive rather than frozen.\n  const breathe =\n    frame > FOCUS_END && frame < EXIT_START\n      ? Math.sin((frame - FOCUS_END) / 18) * 0.012\n      : 0;\n\n  return (\n    <AbsoluteFill style={{ background: \"#080810\" }}>\n      <div\n        style={{\n          display: \"flex\",\n          gap: 24,\n          justifyContent: \"center\",\n          alignItems: \"flex-end\",\n          height: \"100%\",\n          padding: `${safe.paddingTop}px ${safe.paddingRight}px ${safe.paddingBottom}px ${safe.paddingLeft}px`,\n        }}\n      >\n        {tiers.map((tier, i) => {\n          const isFeatured = i === focusIndex;\n          const enter = interpolate(frame, [i * 8, i * 8 + 24], [0, 1], {\n            easing: EASING_ENTER,\n            extrapolateLeft: \"clamp\",\n            extrapolateRight: \"clamp\",\n          });\n          const lift = isFeatured ? focus : 0;\n\n          // Featured card exits last so it keeps the eye's attention longest;\n          // non-featured cards fill the ranks before it in original order.\n          const exitRank = isFeatured\n            ? tiers.length - 1\n            : i < focusIndex\n              ? i\n              : i - 1;\n          const exitDelay = EXIT_START + exitRank * EXIT_STAGGER;\n          const exit = interpolate(frame, [exitDelay, exitDelay + EXIT_DURATION], [0, 1], {\n            easing: EASING_EXIT,\n            extrapolateLeft: \"clamp\",\n            extrapolateRight: \"clamp\",\n          });\n\n          const breatheScale = isFeatured ? 1 + breathe : 1;\n\n          return (\n            <div\n              key={tier.name}\n              style={{\n                width: 220,\n                minHeight: 280 + lift * 40,\n                borderRadius: 20,\n                border: `1px solid ${isFeatured ? \"rgba(232,184,109,0.55)\" : \"rgba(148,163,184,0.16)\"}`,\n                background: isFeatured ? \"rgba(232,184,109,0.12)\" : \"rgba(12,16,24,0.92)\",\n                filter: isFeatured ? \"none\" : `blur(${focus * 3}px)`,\n                transform: `translateY(${-lift * 24 + exit * 32}px) scale(${(isFeatured ? 1 + lift * 0.04 : 0.96 - focus * 0.02) * breatheScale})`,\n                padding: 24,\n                display: \"grid\",\n                gap: 12,\n                alignContent: \"start\",\n                opacity: enter * (isFeatured ? 1 : 1 - focus * 0.25) * (1 - exit),\n              }}\n            >\n              <div style={{ color: \"#e2e8f0\", fontSize: scaleFont(24, width), fontWeight: 600 }}>\n                {tier.name}\n              </div>\n              <div style={{ color: \"#e8b86d\", fontSize: scaleFont(40, width), fontWeight: 700 }}>\n                {tier.price}\n              </div>\n            </div>\n          );\n        })}\n      </div>\n    </AbsoluteFill>\n  );\n};\n"
    }
  ],
  "atlas": {
    "lane": "reels",
    "drive": "time",
    "tier": "advanced"
  }
}