{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "skill-changelog",
  "title": "Changelog — The remocn agent skill, rebuilt",
  "description": "remocn demo composition \"Changelog — The remocn agent skill, rebuilt\" — installs the full Remotion composition. Generated with AI from the prompt in demos/skill-changelog/prompt.md.",
  "dependencies": [
    "@remotion/google-fonts",
    "@remotion/transitions",
    "culori",
    "remotion"
  ],
  "registryDependencies": [
    "https://remocn.dev/r/dynamic-grid.json",
    "https://remocn.dev/r/remocn-ui.json",
    "https://remocn.dev/r/rolling-number.json"
  ],
  "files": [
    {
      "path": "src/demos/skill-changelog/index.tsx",
      "content": "import React, { type CSSProperties, type ReactNode } from \"react\";\nimport {\n  AbsoluteFill,\n  Easing,\n  interpolate,\n  spring,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\nimport {\n  TransitionSeries,\n  linearTiming,\n  type TransitionPresentation,\n  type TransitionPresentationComponentProps,\n} from \"@remotion/transitions\";\nimport { loadFont as loadSans } from \"@remotion/google-fonts/Manrope\";\nimport { loadFont as loadMono } from \"@remotion/google-fonts/GeistMono\";\n\nimport { RemocnUIProvider } from \"@/lib/remocn-ui\";\nimport { DynamicGrid } from \"@/components/remocn/dynamic-grid\";\nimport { RollingNumber } from \"@/components/remocn/rolling-number\";\n\n// ---------------------------------------------------------------------------\n// Fonts — bind to the CSS variables the remocn components read.\n// ---------------------------------------------------------------------------\nconst { fontFamily: SANS_FAMILY } = loadSans(\"normal\", {\n  subsets: [\"latin\"],\n  weights: [\"400\", \"500\", \"600\", \"700\", \"800\"],\n});\nconst { fontFamily: MONO_FAMILY } = loadMono(\"normal\", {\n  subsets: [\"latin\"],\n  weights: [\"400\", \"500\", \"700\"],\n});\n\nconst SANS =\n  \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\";\nconst MONO = \"var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace\";\n\n// ---------------------------------------------------------------------------\n// Palette — one warm accent (Claude/agent) on a flat near-black doc surface.\n// ---------------------------------------------------------------------------\nconst BG = \"#0a0a0a\";\nconst INK = \"#fafafa\";\nconst FAINT = \"rgba(250,250,250,0.50)\";\nconst DIM = \"rgba(250,250,250,0.32)\";\nconst HAIR = \"rgba(250,250,250,0.10)\";\nconst SURFACE = \"#141414\";\nconst ACCENT = \"#D97757\"; // warm — the agent accent\nconst GREEN = \"#5fcf80\"; // muted semantic — Added\nconst BLUE = \"#6aa8f5\"; //  muted semantic — Changed\n\n// ---------------------------------------------------------------------------\n// Scene timings (frames @ 30fps). Transitions overlap adjacent scenes.\n// ---------------------------------------------------------------------------\nconst S_OPEN = 78; //    positioning — \"the skill, rebuilt\"\nconst S_BEFORE = 82; //  problem — one monolithic file\nconst S_TREE = 168; //   hero — the new structure builds as a file tree\nconst S_CHANGES = 132; // change list — what got added\nconst S_STATS = 120; //  proof — rolling numbers\nconst S_OUTRO = 120; //  CTA — wordmark + tagline\n\nconst T_X = 14; //    neutral crossfade\nconst T_ZOOM = 16; // push deeper into the structure\nconst T_OUT = 18; //  settle into the outro\n\nexport const SKILL_CHANGELOG_DURATION =\n  S_OPEN +\n  S_BEFORE +\n  S_TREE +\n  S_CHANGES +\n  S_STATS +\n  S_OUTRO -\n  (T_X + T_ZOOM + T_X + T_X + T_OUT);\n\n// ---------------------------------------------------------------------------\n// Reveal — frame-driven fade + offset + blur clear. Deterministic.\n// ---------------------------------------------------------------------------\nconst Reveal: React.FC<{\n  children: ReactNode;\n  delay?: number;\n  duration?: number;\n  y?: number;\n  x?: number;\n  blur?: number;\n  display?: CSSProperties[\"display\"];\n}> = ({\n  children,\n  delay = 0,\n  duration = 20,\n  y = 16,\n  x = 0,\n  blur = 8,\n  display = \"block\",\n}) => {\n  const frame = useCurrentFrame();\n  const p = interpolate(frame, [delay, delay + duration], [0, 1], {\n    extrapolateLeft: \"clamp\",\n    extrapolateRight: \"clamp\",\n    easing: Easing.out(Easing.cubic),\n  });\n  return (\n    <div\n      style={{\n        display,\n        opacity: p,\n        transform: `translate(${(1 - p) * x}px, ${(1 - p) * y}px)`,\n        filter: p < 1 ? `blur(${(1 - p) * blur}px)` : undefined,\n      }}\n    >\n      {children}\n    </div>\n  );\n};\n\n// ---------------------------------------------------------------------------\n// Eyebrow — a small accent-dotted label chip.\n// ---------------------------------------------------------------------------\nconst Eyebrow: React.FC<{ children: string; delay?: number }> = ({\n  children,\n  delay = 0,\n}) => (\n  <Reveal delay={delay} y={10} blur={6} duration={16} display=\"inline-block\">\n    <div\n      style={{\n        display: \"inline-flex\",\n        alignItems: \"center\",\n        gap: 9,\n        padding: \"7px 15px 7px 12px\",\n        borderRadius: 999,\n        border: `1px solid ${HAIR}`,\n        background: \"rgba(255,255,255,0.03)\",\n        fontFamily: SANS,\n        fontSize: 16,\n        fontWeight: 600,\n        color: FAINT,\n      }}\n    >\n      <span\n        style={{\n          width: 8,\n          height: 8,\n          borderRadius: \"50%\",\n          background: ACCENT,\n        }}\n      />\n      {children}\n    </div>\n  </Reveal>\n);\n\n// ===========================================================================\n// Scene 1 — Positioning. State what this is.\n// ===========================================================================\nconst OpenScene: React.FC = () => (\n  <AbsoluteFill\n    style={{\n      alignItems: \"center\",\n      justifyContent: \"center\",\n      flexDirection: \"column\",\n      gap: 22,\n    }}\n  >\n    <Eyebrow delay={2}>Skill update · remocn</Eyebrow>\n    <Reveal delay={12} y={20} blur={12} duration={24}>\n      <h1\n        style={{\n          margin: 0,\n          fontFamily: SANS,\n          fontWeight: 700,\n          fontSize: 68,\n          letterSpacing: \"-0.02em\",\n          color: INK,\n          textAlign: \"center\",\n          lineHeight: 1.05,\n        }}\n      >\n        The agent skill,\n        <br />\n        <span style={{ color: ACCENT }}>rebuilt.</span>\n      </h1>\n    </Reveal>\n    <Reveal delay={26} y={14} blur={8} duration={20}>\n      <p\n        style={{\n          margin: 0,\n          fontFamily: SANS,\n          fontWeight: 500,\n          fontSize: 24,\n          color: FAINT,\n          textAlign: \"center\",\n        }}\n      >\n        Restructured, and a lot more detailed.\n      </p>\n    </Reveal>\n  </AbsoluteFill>\n);\n\n// ===========================================================================\n// Scene 2 — Problem. It used to be one monolithic file.\n// ===========================================================================\n// Deterministic line widths for the \"crammed\" monolith doc (no randomness).\nconst MONO_LINES = [\n  96, 72, 88, 54, 91, 67, 83, 60, 94, 49, 79, 86, 58, 90, 64, 81, 71, 95, 52,\n  87, 75, 62, 92, 56,\n];\n\nconst BeforeScene: React.FC = () => (\n  <AbsoluteFill\n    style={{\n      alignItems: \"center\",\n      justifyContent: \"center\",\n      flexDirection: \"column\",\n      gap: 30,\n    }}\n  >\n    <Reveal delay={2} y={14} blur={8} duration={18}>\n      <h2\n        style={{\n          margin: 0,\n          fontFamily: SANS,\n          fontWeight: 600,\n          fontSize: 34,\n          color: INK,\n          textAlign: \"center\",\n        }}\n      >\n        It used to live in <span style={{ color: ACCENT }}>one file</span>.\n      </h2>\n    </Reveal>\n    <Reveal delay={10} y={30} blur={12} duration={22}>\n      <div\n        style={{\n          width: 420,\n          height: 300,\n          borderRadius: 16,\n          background: SURFACE,\n          border: `1px solid ${HAIR}`,\n          overflow: \"hidden\",\n          boxShadow: \"0 24px 60px rgba(0,0,0,0.45)\",\n        }}\n      >\n        {/* file header */}\n        <div\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n            gap: 9,\n            padding: \"13px 18px\",\n            borderBottom: `1px solid ${HAIR}`,\n          }}\n        >\n          <span\n            style={{ width: 8, height: 8, borderRadius: \"50%\", background: ACCENT }}\n          />\n          <span style={{ fontFamily: MONO, fontSize: 15, color: FAINT }}>\n            SKILL.md\n          </span>\n          <span\n            style={{\n              marginLeft: \"auto\",\n              fontFamily: MONO,\n              fontSize: 12,\n              color: DIM,\n            }}\n          >\n            everything\n          </span>\n        </div>\n        {/* crammed lines */}\n        <div\n          style={{\n            padding: \"14px 18px\",\n            display: \"flex\",\n            flexDirection: \"column\",\n            gap: 7,\n          }}\n        >\n          {MONO_LINES.map((w, i) => (\n            <div\n              key={i}\n              style={{\n                height: 5,\n                width: `${w}%`,\n                borderRadius: 3,\n                background: \"rgba(250,250,250,0.13)\",\n              }}\n            />\n          ))}\n        </div>\n      </div>\n    </Reveal>\n  </AbsoluteFill>\n);\n\n// ===========================================================================\n// Scene 3 — Hero. The new structure builds itself as a file tree.\n// ===========================================================================\ntype Row = {\n  prefix: string;\n  name: string;\n  dir?: boolean;\n  note?: string;\n  fresh?: boolean; // newly added → accent\n};\n\nconst TREE: Row[] = [\n  { prefix: \"\", name: \"skills/remocn/\", dir: true },\n  { prefix: \"├─ \", name: \"SKILL.md\" },\n  { prefix: \"└─ \", name: \"references/\", dir: true },\n  { prefix: \"   ├─ \", name: \"anatomy.md\", note: \"strategy · beats · quality bar\", fresh: true },\n  { prefix: \"   ├─ \", name: \"design.md\" },\n  { prefix: \"   ├─ \", name: \"motion-principles.md\" },\n  { prefix: \"   ├─ \", name: \"anti-patterns.md\" },\n  { prefix: \"   ├─ \", name: \"archetypes/\", dir: true, note: \"9 recipes\", fresh: true },\n  { prefix: \"   └─ \", name: \"components/\", dir: true, note: \"one file each\", fresh: true },\n];\n\nconst TreeRow: React.FC<{ row: Row; delay: number }> = ({ row, delay }) => {\n  const frame = useCurrentFrame();\n  const p = interpolate(frame, [delay, delay + 16], [0, 1], {\n    extrapolateLeft: \"clamp\",\n    extrapolateRight: \"clamp\",\n    easing: Easing.out(Easing.cubic),\n  });\n  const nameColor = row.fresh ? ACCENT : row.dir ? INK : FAINT;\n  return (\n    <div\n      style={{\n        display: \"flex\",\n        alignItems: \"center\",\n        height: 34,\n        opacity: p,\n        transform: `translateX(${(1 - p) * -12}px)`,\n        filter: p < 1 ? `blur(${(1 - p) * 5}px)` : undefined,\n      }}\n    >\n      <span\n        style={{\n          fontFamily: MONO,\n          fontSize: 21,\n          color: DIM,\n          whiteSpace: \"pre\",\n        }}\n      >\n        {row.prefix}\n      </span>\n      <span\n        style={{\n          fontFamily: MONO,\n          fontSize: 21,\n          fontWeight: row.dir ? 600 : 400,\n          color: nameColor,\n        }}\n      >\n        {row.name}\n      </span>\n      {row.note && (\n        <span\n          style={{\n            marginLeft: 14,\n            fontFamily: SANS,\n            fontSize: 13.5,\n            fontWeight: 500,\n            color: row.fresh ? \"rgba(217,119,87,0.85)\" : DIM,\n            padding: \"3px 10px\",\n            borderRadius: 999,\n            background: row.fresh ? \"rgba(217,119,87,0.12)\" : \"transparent\",\n            border: row.fresh ? \"1px solid rgba(217,119,87,0.25)\" : \"none\",\n          }}\n        >\n          {row.note}\n        </span>\n      )}\n    </div>\n  );\n};\n\nconst TreeScene: React.FC = () => (\n  <AbsoluteFill\n    style={{\n      alignItems: \"center\",\n      justifyContent: \"center\",\n      flexDirection: \"column\",\n      gap: 34,\n    }}\n  >\n    <Reveal delay={2} y={14} blur={8} duration={18}>\n      <h2\n        style={{\n          margin: 0,\n          fontFamily: SANS,\n          fontWeight: 600,\n          fontSize: 34,\n          color: INK,\n          textAlign: \"center\",\n        }}\n      >\n        Now it has a <span style={{ color: ACCENT }}>structure</span>.\n      </h2>\n    </Reveal>\n    <div\n      style={{\n        width: 660,\n        padding: \"26px 32px\",\n        borderRadius: 18,\n        background: SURFACE,\n        border: `1px solid ${HAIR}`,\n        boxShadow: \"0 24px 70px rgba(0,0,0,0.5)\",\n      }}\n    >\n      {TREE.map((row, i) => (\n        <TreeRow key={row.name} row={row} delay={16 + i * 9} />\n      ))}\n    </div>\n  </AbsoluteFill>\n);\n\n// ===========================================================================\n// Scene 4 — Change list. What got added, changelog-style.\n// ===========================================================================\ntype Change = { tag: \"Added\" | \"Changed\"; color: string; text: ReactNode };\n\nconst CHANGES: Change[] = [\n  {\n    tag: \"Added\",\n    color: GREEN,\n    text: (\n      <>\n        <b style={{ fontWeight: 600 }}>anatomy</b> — how to compose a whole\n        video, plus a good-vs-slop quality bar\n      </>\n    ),\n  },\n  {\n    tag: \"Added\",\n    color: GREEN,\n    text: (\n      <>\n        <b style={{ fontWeight: 600 }}>archetypes</b> — 9 ready recipes:\n        product demo, changelog, oss showcase…\n      </>\n    ),\n  },\n  {\n    tag: \"Changed\",\n    color: BLUE,\n    text: (\n      <>\n        <b style={{ fontWeight: 600 }}>components</b> — one file each, with\n        clear use / avoid notes\n      </>\n    ),\n  },\n];\n\nconst ChangeRow: React.FC<{ change: Change; delay: number }> = ({\n  change,\n  delay,\n}) => (\n  <Reveal delay={delay} y={18} x={-10} blur={7} duration={18}>\n    <div style={{ display: \"flex\", alignItems: \"center\", gap: 18 }}>\n      <span\n        style={{\n          flexShrink: 0,\n          width: 92,\n          textAlign: \"center\",\n          fontFamily: MONO,\n          fontSize: 15,\n          fontWeight: 500,\n          color: change.color,\n          padding: \"6px 0\",\n          borderRadius: 8,\n          background: `${change.color}1f`,\n          border: `1px solid ${change.color}33`,\n        }}\n      >\n        {change.tag}\n      </span>\n      <span style={{ fontFamily: SANS, fontSize: 23, color: INK }}>\n        {change.text}\n      </span>\n    </div>\n  </Reveal>\n);\n\nconst ChangesScene: React.FC = () => (\n  <AbsoluteFill\n    style={{\n      alignItems: \"center\",\n      justifyContent: \"center\",\n      flexDirection: \"column\",\n      gap: 30,\n    }}\n  >\n    <Reveal delay={2} y={14} blur={8} duration={18}>\n      <h2\n        style={{\n          margin: 0,\n          fontFamily: SANS,\n          fontWeight: 600,\n          fontSize: 34,\n          color: INK,\n        }}\n      >\n        And a lot more detail.\n      </h2>\n    </Reveal>\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 20 }}>\n      {CHANGES.map((c, i) => (\n        <ChangeRow key={i} change={c} delay={14 + i * 12} />\n      ))}\n    </div>\n  </AbsoluteFill>\n);\n\n// ===========================================================================\n// Scene 5 — Proof. Rolling numbers.\n// ===========================================================================\nconst Stat: React.FC<{\n  to: number;\n  label: string;\n  delay: number;\n}> = ({ to, label, delay }) => (\n  <Reveal delay={delay} y={24} blur={10} duration={20}>\n    <div\n      style={{\n        display: \"flex\",\n        flexDirection: \"column\",\n        alignItems: \"center\",\n        gap: 12,\n        width: 280,\n      }}\n    >\n      <div style={{ height: 96, display: \"flex\", alignItems: \"center\" }}>\n        <RollingNumber from={0} to={to} fontSize={96} color={ACCENT} />\n      </div>\n      <span\n        style={{\n          fontFamily: SANS,\n          fontWeight: 500,\n          fontSize: 22,\n          color: FAINT,\n        }}\n      >\n        {label}\n      </span>\n    </div>\n  </Reveal>\n);\n\nconst StatsScene: React.FC = () => (\n  <AbsoluteFill\n    style={{\n      alignItems: \"center\",\n      justifyContent: \"center\",\n      flexDirection: \"column\",\n      gap: 40,\n    }}\n  >\n    <Reveal delay={2} y={14} blur={8} duration={18}>\n      <h2\n        style={{\n          margin: 0,\n          fontFamily: SANS,\n          fontWeight: 600,\n          fontSize: 30,\n          color: INK,\n        }}\n      >\n        Everything your agent needs.\n      </h2>\n    </Reveal>\n    <div style={{ display: \"flex\", alignItems: \"flex-start\" }}>\n      <Stat to={124} label=\"components\" delay={10} />\n      <div style={{ width: 1, height: 120, background: HAIR }} />\n      <Stat to={9} label=\"archetypes\" delay={18} />\n      <div style={{ width: 1, height: 120, background: HAIR }} />\n      <Stat to={5} label=\"reference guides\" delay={26} />\n    </div>\n  </AbsoluteFill>\n);\n\n// ===========================================================================\n// Scene 6 — CTA. Calm wordmark lockup.\n// ===========================================================================\n// Wordmark — letter-spacing collapses + blur clears (tracking-in essence,\n// intentionally letter-spaced) on the dark canvas.\nconst Wordmark: React.FC = () => {\n  const frame = useCurrentFrame();\n  const { fps } = useVideoConfig();\n  const t = spring({ frame, fps, config: { damping: 18, stiffness: 90 } });\n  const letterSpacing = interpolate(t, [0, 1], [0.5, -0.03]) + \"em\";\n  const blurAmount = interpolate(t, [0, 1], [12, 0]);\n  const opacity = interpolate(frame, [0, 15], [0, 1], {\n    extrapolateLeft: \"clamp\",\n    extrapolateRight: \"clamp\",\n  });\n  return (\n    <div style={{ height: 120, display: \"flex\", alignItems: \"center\" }}>\n      <span\n        style={{\n          fontFamily: SANS,\n          fontSize: 104,\n          fontWeight: 700,\n          color: INK,\n          letterSpacing,\n          opacity,\n          filter: blurAmount > 0.05 ? `blur(${blurAmount}px)` : undefined,\n          whiteSpace: \"nowrap\",\n        }}\n      >\n        remocn\n      </span>\n    </div>\n  );\n};\n\nconst OutroScene: React.FC = () => (\n  <AbsoluteFill style={{ alignItems: \"center\", justifyContent: \"center\" }}>\n    <div\n      style={{\n        display: \"flex\",\n        flexDirection: \"column\",\n        alignItems: \"center\",\n        gap: 20,\n      }}\n    >\n      <Wordmark />\n      <Reveal delay={26} y={14} blur={8} duration={20}>\n        <p\n          style={{\n            margin: 0,\n            fontFamily: SANS,\n            fontWeight: 500,\n            fontSize: 26,\n            color: FAINT,\n            textAlign: \"center\",\n          }}\n        >\n          A sharper map for your agent.\n        </p>\n      </Reveal>\n      <Reveal delay={40} y={10} blur={6} duration={16}>\n        <div\n          style={{\n            display: \"inline-flex\",\n            alignItems: \"center\",\n            gap: 10,\n            marginTop: 6,\n            padding: \"9px 18px\",\n            borderRadius: 999,\n            border: `1px solid ${HAIR}`,\n            background: \"rgba(255,255,255,0.03)\",\n            fontFamily: MONO,\n            fontSize: 18,\n            color: INK,\n          }}\n        >\n          <span style={{ color: ACCENT }}>/</span>remocn\n        </div>\n      </Reveal>\n    </div>\n  </AbsoluteFill>\n);\n\n// ===========================================================================\n// Transition presentations.\n// ===========================================================================\ntype EmptyProps = Record<string, never>;\n\nconst Crossfade: React.FC<TransitionPresentationComponentProps<EmptyProps>> = ({\n  children,\n  presentationProgress,\n  presentationDirection,\n}) => {\n  const entering = presentationDirection === \"entering\";\n  const opacity = entering ? presentationProgress : 1 - presentationProgress;\n  return <AbsoluteFill style={{ opacity }}>{children}</AbsoluteFill>;\n};\nconst crossfade = (): TransitionPresentation<EmptyProps> => ({\n  component: Crossfade,\n  props: {},\n});\n\nconst ZoomBlur: React.FC<\n  TransitionPresentationComponentProps<{ rise: number }>\n> = ({ children, presentationProgress, presentationDirection, passedProps }) => {\n  const { rise } = passedProps;\n  const entering = presentationDirection === \"entering\";\n  const p = interpolate(presentationProgress, [0, 1], [0, 1], {\n    easing: entering ? Easing.out(Easing.cubic) : Easing.in(Easing.cubic),\n  });\n  const style: React.CSSProperties = entering\n    ? {\n        opacity: p,\n        transform: `translateY(${(1 - p) * rise}px) scale(${0.9 + p * 0.1})`,\n        filter: p < 1 ? `blur(${(1 - p) * 16}px)` : undefined,\n      }\n    : {\n        opacity: 1 - p,\n        transform: `translateY(${-p * rise}px) scale(${1 + p * 0.14})`,\n        filter: p > 0 ? `blur(${p * 16}px)` : undefined,\n      };\n  return <AbsoluteFill style={style}>{children}</AbsoluteFill>;\n};\nconst zoomBlur = (rise = 0): TransitionPresentation<{ rise: number }> => ({\n  component: ZoomBlur,\n  props: { rise },\n});\n\n// ===========================================================================\n// Composition root.\n// ===========================================================================\nexport const SkillChangelogDemo: React.FC = () => {\n  return (\n    <RemocnUIProvider>\n      <AbsoluteFill\n        style={\n          {\n            \"--font-geist-sans\": SANS_FAMILY,\n            \"--font-geist-mono\": MONO_FAMILY,\n            background: BG,\n          } as React.CSSProperties\n        }\n      >\n        {/* Static, low-opacity grid — the list/tree is the focus, not the bg. */}\n        <DynamicGrid\n          cellSize={44}\n          lineColor=\"rgba(255,255,255,0.035)\"\n          background={BG}\n          speed={0}\n        />\n        {/* Gentle neutral vignette for depth (not a colored glow). */}\n        <AbsoluteFill\n          style={{\n            background:\n              \"radial-gradient(120% 120% at 50% 42%, rgba(0,0,0,0) 38%, rgba(0,0,0,0.55) 100%)\",\n          }}\n        />\n\n        <TransitionSeries>\n          {/* 1 — Positioning */}\n          <TransitionSeries.Sequence durationInFrames={S_OPEN}>\n            <OpenScene />\n          </TransitionSeries.Sequence>\n          <TransitionSeries.Transition\n            timing={linearTiming({ durationInFrames: T_X })}\n            presentation={crossfade()}\n          />\n\n          {/* 2 — Problem: one file */}\n          <TransitionSeries.Sequence durationInFrames={S_BEFORE}>\n            <BeforeScene />\n          </TransitionSeries.Sequence>\n          <TransitionSeries.Transition\n            timing={linearTiming({ durationInFrames: T_ZOOM })}\n            presentation={zoomBlur(44)}\n          />\n\n          {/* 3 — Hero: the structure */}\n          <TransitionSeries.Sequence durationInFrames={S_TREE}>\n            <TreeScene />\n          </TransitionSeries.Sequence>\n          <TransitionSeries.Transition\n            timing={linearTiming({ durationInFrames: T_X })}\n            presentation={crossfade()}\n          />\n\n          {/* 4 — Change list */}\n          <TransitionSeries.Sequence durationInFrames={S_CHANGES}>\n            <ChangesScene />\n          </TransitionSeries.Sequence>\n          <TransitionSeries.Transition\n            timing={linearTiming({ durationInFrames: T_X })}\n            presentation={crossfade()}\n          />\n\n          {/* 5 — Proof */}\n          <TransitionSeries.Sequence durationInFrames={S_STATS}>\n            <StatsScene />\n          </TransitionSeries.Sequence>\n          <TransitionSeries.Transition\n            timing={linearTiming({ durationInFrames: T_OUT })}\n            presentation={zoomBlur(60)}\n          />\n\n          {/* 6 — CTA */}\n          <TransitionSeries.Sequence durationInFrames={S_OUTRO}>\n            <OutroScene />\n          </TransitionSeries.Sequence>\n        </TransitionSeries>\n      </AbsoluteFill>\n    </RemocnUIProvider>\n  );\n};\n",
      "type": "registry:component",
      "target": "demos/skill-changelog/index.tsx"
    },
    {
      "path": "src/demos/skill-changelog/prompt.md",
      "content": "<!-- TODO(draft): placeholder written by AI — replace with the real prompt used to generate this video -->\n\nWe just rebuilt the remocn agent skill itself — it went from one giant SKILL.md to a proper structured reference with a references folder (anatomy, design, motion-principles, anti-patterns, archetypes, per-component docs). Make a meta changelog video about that change for our own audience. Start with a hero beat that builds out the new file tree on screen, then a changelog-style list of what actually got added, then roll up some proof numbers — like 124 components, 9 archetypes, 5 guides — and close on a calm remocn wordmark. Give it its own look, separate from our other videos — warm accent color, flat near-black grid, something closer to a docs/IDE aesthetic. Use remocn components for the build and rolling-number beats.\n",
      "type": "registry:file",
      "target": "demos/skill-changelog/prompt.md"
    }
  ],
  "docs": "Register the composition in your Remotion Root:\n\n  import { SkillChangelogDemo } from \"@/demos/skill-changelog\";\n  <Composition id=\"skill-changelog\" component={SkillChangelogDemo} durationInFrames={624} fps={30} width={1280} height={720} />\n\nRequires Tailwind v4 wired into Remotion (@remotion/tailwind-v4).\nRender locally: npx remotion render skill-changelog out/skill-changelog.mp4",
  "type": "registry:block"
}