# Tonykipkemboi Cc Plugins Insights Video

> Insights Video

- Skill: `tomevault-io/tonykipkemboi-cc-plugins-insights-video` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/tonykipkemboi-cc-plugins-insights-video`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/tonykipkemboi-cc-plugins-insights-video/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/tonykipkemboi-cc-plugins-insights-video

---


# Insights Video

Generate a polished 30-second animated video showcasing Claude Code usage insights. Features Claude branding, animated stats, project areas chart, friction analysis, and background music.

## Pipeline

Execute the entire pipeline automatically with no user interaction needed (except for choosing the project location). Complete all steps in order:

### Step 1: Read and Parse Insights Data

Read the HTML report from `~/.claude/usage-data/report.html` and parse it to extract:
- Total sessions count (from subtitle line like "X messages across Y sessions")
- Total messages count
- Date range (from the date subtitle)
- Project areas with session counts (from `.project-area` divs)
- Top 3 friction categories (from `.friction-category` divs)
- Interaction style narrative (from narrative sections)

Also read ALL JSON files from `~/.claude/usage-data/facets/*.json` and aggregate:
- Total friction_counts across all sessions
- User satisfaction counts (sum likely_satisfied and dissatisfied)
- Outcome distribution

Calculate:
- `satisfaction_rate = likely_satisfied / (likely_satisfied + dissatisfied) * 100`
- `total_hours = (total sessions * median_response_time_seconds) / 3600` (approximate from report data)

If `~/.claude/usage-data/` does not exist, display a message that `/insights` must be run first and stop execution.

### Step 2: Ask Where to Create the Project

Use a simple inline question (not a blocking dialog) to ask where to create the Remotion project:
- Desktop (recommended)
- Home directory
- Custom path

Wait for the user's response, then proceed.

### Step 3: Scaffold Remotion Project

Create directory structure at the chosen location: `claude-insights-video/`

Write `package.json` with these exact dependencies:

```json
{
  "name": "claude-insights-video",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "remotion studio",
    "build": "remotion render InsightsVideo out/insights.mp4",
    "render": "remotion render InsightsVideo out/insights.mp4"
  },
  "dependencies": {
    "@remotion/cli": "4.0.419",
    "@remotion/google-fonts": "4.0.419",
    "@remotion/media": "4.0.419",
    "@remotion/paths": "4.0.419",
    "@remotion/transitions": "4.0.419",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "remotion": "4.0.419"
  },
  "devDependencies": {
    "@types/react": "^18.3.3",
    "typescript": "^5.5.3"
  }
}
```

Write `tsconfig.json`:

```json
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "commonjs",
    "jsx": "react-jsx",
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "moduleResolution": "node",
    "lib": ["ES2018", "DOM"]
  },
  "include": ["src"]
}
```

Write `remotion.config.ts`:

```ts
import { Config } from "@remotion/cli/config";
Config.setVideoImageFormat("jpeg");
Config.setOverwriteOutput(true);
```

### Step 4: Copy Background Music

Create the `public/` directory first, then copy the bundled background music:

```bash
cp ${CLAUDE_PLUGIN_ROOT}/skills/insights-video/assets/background-music.mp3 <project>/public/background-music.mp3
```

### Step 5: Generate Source Files

Create all source files under `src/` with the user's personalized data substituted in.

**IMPORTANT REMOTION RULES:**
- All animations MUST use `useCurrentFrame()` + `interpolate()` or `spring()`. CSS transitions/animations are FORBIDDEN.
- Always use `extrapolateRight: 'clamp'` on interpolations.
- Use `loadFont` from `@remotion/google-fonts/Inter` for typography.
- Use `TransitionSeries` with `fade()` and `slide()` transitions.
- Use `<Audio>` from `@remotion/media` with `staticFile()` for the music.

#### src/lib/constants.ts

This file contains all the personalized data. Substitute the user's actual values:

```ts
// Claude brand palette
export const COLORS = {
  claude: "#D97757",
  claudeLight: "#E8956F",
  claudeDark: "#C45E3E",
  bg: "#1a1107",
  bgMid: "#1f1610",
  bgLight: "#2a1f15",
  bgCard: "rgba(217, 119, 87, 0.08)",
  bgCardBorder: "rgba(217, 119, 87, 0.2)",
  text: "#faf5f0",
  textSecondary: "#d4bfb0",
  textMuted: "#9a8578",
  green: "#5cb88a",
  greenGlow: "#3ddc84",
  amber: "#e6a23c",
  red: "#e06c5a",
  purple: "#b39ddb",
  blue: "#7eb8da",
  cyan: "#6ec6c8",
  glowOrange: "rgba(217, 119, 87, 0.3)",
  glowGreen: "rgba(92, 184, 138, 0.3)",
  glowAmber: "rgba(230, 162, 60, 0.3)",
};

// PERSONALIZE THESE with user's actual data:
export const STATS = [
  { label: "Sessions", value: USER_SESSIONS, color: COLORS.claude, icon: "terminal" },
  { label: "Messages", value: USER_MESSAGES, color: COLORS.blue, icon: "message" },
  { label: "Hours", value: USER_HOURS, color: COLORS.cyan, icon: "clock" },
  { label: "Commits", value: USER_COMMITS, color: COLORS.green, icon: "git" },
];

// Use top 5 project areas from insights, assign colors rotating through: claude, blue, cyan, green, amber
export const PROJECT_AREAS = [
  { name: "AREA_NAME", sessions: AREA_COUNT, color: COLORS.claude },
  // ... up to 5 entries
];

// Use top 3 "What's Working" items from insights
export const WHATS_WORKING = [
  "WORKING_ITEM_1",
  "WORKING_ITEM_2",
  "WORKING_ITEM_3",
];

// Use top 3 friction categories from insights
export const FRICTION_POINTS = [
  { label: "FRICTION_LABEL", count: FRICTION_COUNT, color: COLORS.red },
  // ... up to 3 entries, first gets red, rest get amber
];

// The user's key interaction style quote and subtitle from insights
export const STYLE_QUOTE = "USER_STYLE_QUOTE"; // e.g. "Rapid iteration with tight oversight"
export const STYLE_SUBTITLE = "USER_STYLE_SUBTITLE"; // e.g. "Hands-on, correction-driven collaborator"

// Satisfaction rate percentage
export const SATISFACTION_RATE = USER_SATISFACTION_RATE; // e.g. 97

// Date range from insights
export const DATE_RANGE = "USER_DATE_RANGE"; // e.g. "Jan 6 — Feb 5, 2026"

// Total sessions for title scene
export const TOTAL_SESSIONS = USER_TOTAL_SESSIONS; // e.g. 666

export const FPS = 30;
export const WIDTH = 1080;
export const HEIGHT = 1080;

export const SCENE_DURATIONS = {
  title: 4 * FPS,
  stats: 5 * FPS,
  projects: 5 * FPS,
  working: 5 * FPS,
  friction: 5 * FPS,
  style: 5 * FPS,
  closing: 4 * FPS,
};
export const TRANSITION_DURATION = 15;
export const TOTAL_DURATION =
  Object.values(SCENE_DURATIONS).reduce((a, b) => a + b, 0) - 6 * TRANSITION_DURATION;
```

#### src/index.ts

```ts
import { registerRoot } from "remotion";
import { RemotionRoot } from "./Root";
registerRoot(RemotionRoot);
```

#### src/Root.tsx

```tsx
import { Composition } from "remotion";
import { InsightsVideo } from "./InsightsVideo";
import { WIDTH, HEIGHT, FPS, TOTAL_DURATION } from "./lib/constants";

export const RemotionRoot: React.FC = () => {
  return (
    <Composition
      id="InsightsVideo"
      component={InsightsVideo}
      durationInFrames={TOTAL_DURATION}
      fps={FPS}
      width={WIDTH}
      height={HEIGHT}
    />
  );
};
```

#### src/InsightsVideo.tsx

```tsx
import React from "react";
import { interpolate, staticFile, useVideoConfig } from "remotion";
import { Audio } from "@remotion/media";
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
import { slide } from "@remotion/transitions/slide";
import { SCENE_DURATIONS, TRANSITION_DURATION, TOTAL_DURATION } from "./lib/constants";
import { TitleScene } from "./scenes/TitleScene";
import { StatsScene } from "./scenes/StatsScene";
import { ProjectsScene } from "./scenes/ProjectsScene";
import { WorkingScene } from "./scenes/WorkingScene";
import { FrictionScene } from "./scenes/FrictionScene";
import { StyleScene } from "./scenes/StyleScene";
import { ClosingScene } from "./scenes/ClosingScene";

export const InsightsVideo: React.FC = () => {
  const { fps } = useVideoConfig();
  return (
    <>
      <Audio
        src={staticFile("background-music.mp3")}
        volume={(f) => {
          const fadeInEnd = 2 * fps;
          const fadeOutStart = TOTAL_DURATION - 3 * fps;
          if (f < fadeInEnd) return interpolate(f, [0, fadeInEnd], [0, 0.6], { extrapolateRight: "clamp" });
          if (f > fadeOutStart) return interpolate(f, [fadeOutStart, TOTAL_DURATION], [0.6, 0], { extrapolateRight: "clamp" });
          return 0.6;
        }}
      />
      <TransitionSeries>
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.title}><TitleScene /></TransitionSeries.Sequence>
        <TransitionSeries.Transition presentation={fade()} timing={linearTiming({ durationInFrames: TRANSITION_DURATION })} />
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.stats}><StatsScene /></TransitionSeries.Sequence>
        <TransitionSeries.Transition presentation={slide({ direction: "from-left" })} timing={linearTiming({ durationInFrames: TRANSITION_DURATION })} />
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.projects}><ProjectsScene /></TransitionSeries.Sequence>
        <TransitionSeries.Transition presentation={fade()} timing={linearTiming({ durationInFrames: TRANSITION_DURATION })} />
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.working}><WorkingScene /></TransitionSeries.Sequence>
        <TransitionSeries.Transition presentation={slide({ direction: "from-right" })} timing={linearTiming({ durationInFrames: TRANSITION_DURATION })} />
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.friction}><FrictionScene /></TransitionSeries.Sequence>
        <TransitionSeries.Transition presentation={fade()} timing={linearTiming({ durationInFrames: TRANSITION_DURATION })} />
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.style}><StyleScene /></TransitionSeries.Sequence>
        <TransitionSeries.Transition presentation={fade()} timing={linearTiming({ durationInFrames: TRANSITION_DURATION })} />
        <TransitionSeries.Sequence durationInFrames={SCENE_DURATIONS.closing}><ClosingScene /></TransitionSeries.Sequence>
      </TransitionSeries>
    </>
  );
};
```

#### src/components/Background.tsx

```tsx
import React from "react";
import { AbsoluteFill, useCurrentFrame, useVideoConfig, interpolate } from "remotion";
import { COLORS } from "../lib/constants";

export const Background: React.FC<{ accentColor?: string; glowIntensity?: number }> = ({ accentColor, glowIntensity = 0.4 }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const accent = accentColor || COLORS.claude;
  const fadeIn = interpolate(frame, [0, fps * 0.5], [0, 1], { extrapolateRight: "clamp" });
  const glow1X = interpolate(frame, [0, 10 * fps], [20, 80], { extrapolateRight: "clamp" });
  const glow1Y = interpolate(frame, [0, 10 * fps], [15, 35], { extrapolateRight: "clamp" });
  const glow2X = interpolate(frame, [0, 10 * fps], [70, 30], { extrapolateRight: "clamp" });
  const glow2Y = interpolate(frame, [0, 10 * fps], [75, 60], { extrapolateRight: "clamp" });

  return (
    <AbsoluteFill>
      <AbsoluteFill style={{ background: `radial-gradient(ellipse at 50% 50%, ${COLORS.bgMid} 0%, ${COLORS.bg} 70%)` }} />
      <AbsoluteFill style={{ opacity: fadeIn * glowIntensity }}>
        <div style={{ position: "absolute", width: 600, height: 600, borderRadius: "50%", background: `radial-gradient(circle, ${accent}40 0%, transparent 70%)`, left: `${glow1X}%`, top: `${glow1Y}%`, transform: "translate(-50%, -50%)", filter: "blur(80px)" }} />
        <div style={{ position: "absolute", width: 500, height: 500, borderRadius: "50%", background: `radial-gradient(circle, ${COLORS.claude}25 0%, transparent 70%)`, left: `${glow2X}%`, top: `${glow2Y}%`, transform: "translate(-50%, -50%)", filter: "blur(100px)" }} />
      </AbsoluteFill>
      <AbsoluteFill style={{ opacity: fadeIn * 0.15, backgroundImage: `radial-gradient(${accent}30 1px, transparent 1px)`, backgroundSize: "32px 32px" }} />
      <div style={{ position: "absolute", top: 40, left: 40, width: interpolate(frame, [0, fps], [0, 60], { extrapolateRight: "clamp" }), height: 3, background: accent, borderRadius: 2, opacity: fadeIn * 0.6 }} />
      <div style={{ position: "absolute", top: 40, left: 40, width: 3, height: interpolate(frame, [0, fps], [0, 60], { extrapolateRight: "clamp" }), background: accent, borderRadius: 2, opacity: fadeIn * 0.6 }} />
      <div style={{ position: "absolute", bottom: 40, right: 40, width: interpolate(frame, [0, fps], [0, 60], { extrapolateRight: "clamp" }), height: 3, background: accent, borderRadius: 2, opacity: fadeIn * 0.6 }} />
      <div style={{ position: "absolute", bottom: 40, right: 40, width: 3, height: interpolate(frame, [0, fps], [0, 60], { extrapolateRight: "clamp" }), background: accent, borderRadius: 2, opacity: fadeIn * 0.6 }} />
    </AbsoluteFill>
  );
};
```

#### src/components/AnimatedNumber.tsx

```tsx
import React from "react";
import { useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion";
import { COLORS } from "../lib/constants";

type Props = { value: number; color: string; label: string; delay: number; fontSize?: number };

export const AnimatedNumber: React.FC<Props> = ({ value, color, label, delay, fontSize = 68 }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const entrance = spring({ frame, fps, delay, config: { damping: 200 } });
  const scale = interpolate(entrance, [0, 1], [0.5, 1]);
  const translateY = interpolate(entrance, [0, 1], [30, 0]);
  const numberProgress = interpolate(frame, [delay, delay + 2 * fps], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const displayValue = Math.round(numberProgress * value);
  const formatted = displayValue >= 1000 ? displayValue.toLocaleString() : String(displayValue);

  return (
    <div style={{ display: "flex", flexDirection: "column", alignItems: "center", opacity: entrance, transform: `scale(${scale}) translateY(${translateY}px)` }}>
      <span style={{ fontSize, fontWeight: 900, color, lineHeight: 1, fontVariantNumeric: "tabular-nums", textShadow: `0 0 40px ${color}60, 0 0 80px ${color}20` }}>{formatted}</span>
      <span style={{ fontSize: 20, color: COLORS.textMuted, marginTop: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: 3 }}>{label}</span>
    </div>
  );
};
```

#### src/components/BarChart.tsx

```tsx
import React from "react";
import { useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion";
import { COLORS } from "../lib/constants";

type BarData = { name: string; sessions: number; color: string };
type Props = { data: BarData[]; maxValue?: number };

export const BarChart: React.FC<Props> = ({ data, maxValue }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const max = maxValue || Math.max(...data.map((d) => d.sessions));

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 22, width: "100%", padding: "0 40px" }}>
      {data.map((item, i) => {
        const barProgress = spring({ frame, fps, delay: i * 8 + 15, config: { damping: 200 } });
        const labelOpacity = interpolate(frame, [i * 8 + 10, i * 8 + 25], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
        const barWidth = interpolate(barProgress, [0, 1], [0, (item.sessions / max) * 100]);
        return (
          <div key={item.name} style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", opacity: labelOpacity }}>
              <span style={{ fontSize: 24, color: COLORS.text, fontWeight: 500 }}>{item.name}</span>
              <span style={{ fontSize: 28, color: item.color, fontWeight: 800, fontVariantNumeric: "tabular-nums", textShadow: `0 0 20px ${item.color}40` }}>{item.sessions}</span>
            </div>
            <div style={{ height: 14, borderRadius: 7, background: "rgba(255,255,255,0.05)", overflow: "hidden", border: "1px solid rgba(255,255,255,0.05)" }}>
              <div style={{ height: "100%", width: `${barWidth}%`, borderRadius: 7, background: `linear-gradient(90deg, ${item.color}cc, ${item.color})`, boxShadow: `0 0 16px ${item.color}50` }} />
            </div>
          </div>
        );
      })}
    </div>
  );
};
```

#### src/components/ClaudeLogo.tsx

```tsx
import React from "react";
import { useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion";
import { COLORS } from "../lib/constants";

type Props = { size?: number; delay?: number };

export const ClaudeLogo: React.FC<Props> = ({ size = 80, delay = 0 }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const entrance = spring({ frame, fps, delay, config: { damping: 12, stiffness: 80 } });
  const scale = interpolate(entrance, [0, 1], [0.3, 1]);
  const glowPulse = interpolate(frame, [delay, delay + 2 * fps, delay + 4 * fps], [0.4, 0.8, 0.4], { extrapolateRight: "clamp", extrapolateLeft: "clamp" });

  return (
    <div style={{ width: size, height: size, opacity: entrance, transform: `scale(${scale})`, position: "relative", display: "flex", alignItems: "center", justifyContent: "center" }}>
      <div style={{ position: "absolute", inset: -20, borderRadius: "50%", background: `radial-gradient(circle, ${COLORS.claude}${Math.round(glowPulse * 60).toString(16).padStart(2, "0")} 0%, transparent 70%)`, filter: "blur(15px)" }} />
      <svg width={size} height={size} viewBox="0 0 100 100" fill="none">
        {[0, 60, 120, 180, 240, 300].map((angle) => (
          <line key={angle} x1="50" y1="50" x2={50 + 38 * Math.cos((angle * Math.PI) / 180)} y2={50 + 38 * Math.sin((angle * Math.PI) / 180)} stroke={COLORS.claude} strokeWidth="6" strokeLinecap="round" />
        ))}
        <circle cx="50" cy="50" r="8" fill={COLORS.claude} />
      </svg>
    </div>
  );
};
```

#### src/scenes/TitleScene.tsx

```tsx
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
  Easing,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";
import { Background } from "../components/Background";
import { ClaudeLogo } from "../components/ClaudeLogo";
import { COLORS, DATE_RANGE, TOTAL_SESSIONS } from "../lib/constants";

const { fontFamily } = loadFont("normal", {
  weights: ["400", "700", "900"],
  subsets: ["latin"],
});

export const TitleScene: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const titleSpring = spring({
    frame,
    fps,
    delay: 10,
    config: { damping: 15, stiffness: 80 },
  });
  const titleScale = interpolate(titleSpring, [0, 1], [0.6, 1]);

  const subtitleOpacity = interpolate(frame, [fps * 1.5, fps * 2.5], [0, 1], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });
  const subtitleY = interpolate(frame, [fps * 1.5, fps * 2.5], [15, 0], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });

  const lineWidth = interpolate(frame, [fps, fps * 2], [0, 300], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
    easing: Easing.out(Easing.quad),
  });

  // Floating particles
  const particles = Array.from({ length: 12 }, (_, i) => {
    const baseX = (i * 97 + 13) % 100;
    const baseY = (i * 71 + 29) % 100;
    const speed = 0.3 + (i % 4) * 0.15;
    const yOffset = interpolate(
      frame,
      [0, 10 * fps],
      [0, -40 * speed],
      { extrapolateRight: "clamp" }
    );
    const particleOpacity = interpolate(
      frame,
      [i * 3, i * 3 + fps],
      [0, 0.3 + (i % 3) * 0.15],
      { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
    );
    return { x: baseX, y: baseY, yOffset, opacity: particleOpacity, size: 3 + (i % 3) * 2 };
  });

  return (
    <AbsoluteFill style={{ fontFamily }}>
      <Background accentColor={COLORS.claude} glowIntensity={0.5} />

      {/* Floating particles */}
      {particles.map((p, i) => (
        <div
          key={i}
          style={{
            position: "absolute",
            left: `${p.x}%`,
            top: `${p.y}%`,
            width: p.size,
            height: p.size,
            borderRadius: "50%",
            background: COLORS.claude,
            opacity: p.opacity,
            transform: `translateY(${p.yOffset}px)`,
            boxShadow: `0 0 ${p.size * 3}px ${COLORS.claude}60`,
          }}
        />
      ))}

      <AbsoluteFill
        style={{
          justifyContent: "center",
          alignItems: "center",
          flexDirection: "column",
          gap: 20,
        }}
      >
        <ClaudeLogo size={90} delay={0} />

        <div style={{ height: 20 }} />

        {/* Title */}
        <div
          style={{
            opacity: titleSpring,
            transform: `scale(${titleScale})`,
            textAlign: "center",
          }}
        >
          <div
            style={{
              fontSize: 76,
              fontWeight: 900,
              color: COLORS.text,
              lineHeight: 1.1,
              textShadow: `0 0 60px ${COLORS.claude}30`,
            }}
          >
            Claude Code
          </div>
          <div
            style={{
              fontSize: 76,
              fontWeight: 900,
              color: COLORS.claude,
              lineHeight: 1.1,
              textShadow: `0 0 60px ${COLORS.claude}50`,
            }}
          >
            Insights
          </div>
        </div>

        {/* Divider line */}
        <div
          style={{
            width: lineWidth,
            height: 2,
            background: `linear-gradient(90deg, transparent, ${COLORS.claude}, transparent)`,
            borderRadius: 2,
            marginTop: 8,
            boxShadow: `0 0 20px ${COLORS.claude}40`,
          }}
        />

        {/* Date range */}
        <div
          style={{
            fontSize: 24,
            color: COLORS.textMuted,
            opacity: subtitleOpacity,
            transform: `translateY(${subtitleY}px)`,
            letterSpacing: 4,
            textTransform: "uppercase",
            marginTop: 8,
          }}
        >
          {DATE_RANGE}
        </div>

        {/* Bottom badge */}
        <div
          style={{
            position: "absolute",
            bottom: 70,
            opacity: subtitleOpacity,
            display: "flex",
            alignItems: "center",
            gap: 8,
            padding: "10px 24px",
            borderRadius: 100,
            border: `1px solid ${COLORS.bgCardBorder}`,
            background: COLORS.bgCard,
          }}
        >
          <div
            style={{
              width: 8,
              height: 8,
              borderRadius: "50%",
              background: COLORS.claude,
              boxShadow: `0 0 8px ${COLORS.claude}`,
            }}
          />
          <span style={{ fontSize: 16, color: COLORS.textSecondary, fontWeight: 500 }}>
            {TOTAL_SESSIONS} sessions analyzed
          </span>
        </div>
      </AbsoluteFill>
    </AbsoluteFill>
  );
};
```

#### src/scenes/StatsScene.tsx

```tsx
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";
import { Background } from "../components/Background";
import { AnimatedNumber } from "../components/AnimatedNumber";
import { COLORS, STATS } from "../lib/constants";

const { fontFamily } = loadFont("normal", {
  weights: ["400", "700", "900"],
  subsets: ["latin"],
});

const StatIcon: React.FC<{ type: string; color: string }> = ({ type, color }) => {
  const icons: Record<string, React.ReactNode> = {
    terminal: (
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <polyline points="4 17 10 11 4 5" />
        <line x1="12" y1="19" x2="20" y2="19" />
      </svg>
    ),
    message: (
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
      </svg>
    ),
    clock: (
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <circle cx="12" cy="12" r="10" />
        <polyline points="12 6 12 12 16 14" />
      </svg>
    ),
    git: (
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <circle cx="12" cy="18" r="3" />
        <circle cx="12" cy="6" r="3" />
        <line x1="12" y1="9" x2="12" y2="15" />
      </svg>
    ),
  };
  return <>{icons[type] || null}</>;
};

export const StatsScene: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const headerSpring = spring({ frame, fps, config: { damping: 200 } });

  return (
    <AbsoluteFill style={{ fontFamily }}>
      <Background accentColor={COLORS.claude} />
      <AbsoluteFill
        style={{
          justifyContent: "center",
          alignItems: "center",
          flexDirection: "column",
          gap: 50,
          padding: 60,
        }}
      >
        {/* Header */}
        <div
          style={{
            display: "flex",
            alignItems: "center",
            gap: 14,
            opacity: headerSpring,
            transform: `translateY(${interpolate(headerSpring, [0, 1], [20, 0])}px)`,
          }}
        >
          <div style={{ width: 40, height: 2, background: COLORS.claude, borderRadius: 1 }} />
          <span
            style={{
              fontSize: 36,
              fontWeight: 700,
              color: COLORS.text,
              textTransform: "uppercase",
              letterSpacing: 6,
            }}
          >
            By the Numbers
          </span>
          <div style={{ width: 40, height: 2, background: COLORS.claude, borderRadius: 1 }} />
        </div>

        {/* Stats grid */}
        <div
          style={{
            display: "flex",
            flexWrap: "wrap",
            justifyContent: "center",
            gap: 30,
            width: "100%",
          }}
        >
          {STATS.map((stat, i) => {
            const cardSpring = spring({
              frame,
              fps,
              delay: i * 8 + 8,
              config: { damping: 200 },
            });

            return (
              <div
                key={stat.label}
                style={{
                  width: "44%",
                  display: "flex",
                  flexDirection: "column",
                  alignItems: "center",
                  justifyContent: "center",
                  padding: "32px 20px 28px",
                  background: COLORS.bgCard,
                  borderRadius: 20,
                  border: `1px solid ${COLORS.bgCardBorder}`,
                  opacity: cardSpring,
                  transform: `translateY(${interpolate(cardSpring, [0, 1], [20, 0])}px)`,
                  boxShadow: `0 4px 30px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.03)`,
                }}
              >
                <div style={{ marginBottom: 12, opacity: 0.7 }}>
                  <StatIcon type={stat.icon} color={stat.color} />
                </div>
                <AnimatedNumber
                  value={stat.value}
                  color={stat.color}
                  label={stat.label}
                  delay={i * 8 + 8}
                />
              </div>
            );
          })}
        </div>
      </AbsoluteFill>
    </AbsoluteFill>
  );
};
```

#### src/scenes/ProjectsScene.tsx

```tsx
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";
import { Background } from "../components/Background";
import { BarChart } from "../components/BarChart";
import { COLORS, PROJECT_AREAS } from "../lib/constants";

const { fontFamily } = loadFont("normal", {
  weights: ["400", "700", "900"],
  subsets: ["latin"],
});

export const ProjectsScene: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const headerSpring = spring({ frame, fps, config: { damping: 200 } });

  return (
    <AbsoluteFill style={{ fontFamily }}>
      <Background accentColor={COLORS.cyan} />
      <AbsoluteFill
        style={{
          justifyContent: "center",
          alignItems: "center",
          flexDirection: "column",
          gap: 50,
          padding: 60,
        }}
      >
        <div
          style={{
            display: "flex",
            alignItems: "center",
            gap: 14,
            opacity: headerSpring,
            transform: `translateY(${interpolate(headerSpring, [0, 1], [20, 0])}px)`,
          }}
        >
          <div style={{ width: 40, height: 2, background: COLORS.cyan, borderRadius: 1 }} />
          <span
            style={{
              fontSize: 36,
              fontWeight: 700,
              color: COLORS.text,
              textTransform: "uppercase",
              letterSpacing: 6,
            }}
          >
            Project Areas
          </span>
          <div style={{ width: 40, height: 2, background: COLORS.cyan, borderRadius: 1 }} />
        </div>

        <div
          style={{
            width: "100%",
            background: COLORS.bgCard,
            borderRadius: 24,
            border: `1px solid ${COLORS.bgCardBorder}`,
            padding: "36px 20px",
            boxShadow: "0 4px 30px rgba(0,0,0,0.3)",
          }}
        >
          <BarChart data={PROJECT_AREAS} />
        </div>
      </AbsoluteFill>
    </AbsoluteFill>
  );
};
```

#### src/scenes/WorkingScene.tsx

```tsx
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";
import { Background } from "../components/Background";
import { COLORS, WHATS_WORKING } from "../lib/constants";

const { fontFamily } = loadFont("normal", {
  weights: ["400", "700", "900"],
  subsets: ["latin"],
});

const CheckCircle: React.FC<{ progress: number }> = ({ progress }) => {
  const dashOffset = interpolate(progress, [0, 1], [63, 0]);
  return (
    <svg width="36" height="36" viewBox="0 0 24 24" fill="none">
      <circle
        cx="12"
        cy="12"
        r="10"
        stroke={COLORS.green}
        strokeWidth="2"
        strokeDasharray="63"
        strokeDashoffset={dashOffset}
        opacity={0.3}
      />
      <circle cx="12" cy="12" r="10" fill={`${COLORS.green}15`} />
      <polyline
        points="8 12 11 15 16 9"
        stroke={COLORS.green}
        strokeWidth="2.5"
        strokeLinecap="round"
        strokeLinejoin="round"
        opacity={progress}
      />
    </svg>
  );
};

export const WorkingScene: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const headerSpring = spring({ frame, fps, config: { damping: 200 } });

  return (
    <AbsoluteFill style={{ fontFamily }}>
      <Background accentColor={COLORS.green} />
      <AbsoluteFill
        style={{
          justifyContent: "center",
          alignItems: "center",
          flexDirection: "column",
          gap: 44,
          padding: 80,
        }}
      >
        <div
          style={{
            display: "flex",
            alignItems: "center",
            gap: 14,
            opacity: headerSpring,
            transform: `translateY(${interpolate(headerSpring, [0, 1], [20, 0])}px)`,
          }}
        >
          <div style={{ width: 40, height: 2, background: COLORS.green, borderRadius: 1 }} />
          <span
            style={{
              fontSize: 36,
              fontWeight: 700,
              color: COLORS.green,
              textTransform: "uppercase",
              letterSpacing: 6,
              textShadow: `0 0 30px ${COLORS.green}30`,
            }}
          >
            What's Working
          </span>
          <div style={{ width: 40, height: 2, background: COLORS.green, borderRadius: 1 }} />
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 24, width: "100%" }}>
          {WHATS_WORKING.map((item, i) => {
            const itemSpring = spring({
              frame,
              fps,
              delay: i * 12 + 15,
              config: { damping: 200 },
            });

            const translateX = interpolate(itemSpring, [0, 1], [-50, 0]);

            return (
              <div
                key={item}
                style={{
                  display: "flex",
                  alignItems: "center",
                  gap: 20,
                  opacity: itemSpring,
                  transform: `translateX(${translateX}px)`,
                  background: COLORS.bgCard,
                  borderRadius: 18,
                  padding: "26px 32px",
                  borderLeft: `3px solid ${COLORS.green}`,
                  border: `1px solid ${COLORS.bgCardBorder}`,
                  borderLeftColor: COLORS.green,
                  borderLeftWidth: 3,
                  boxShadow: `0 4px 20px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.03)`,
                }}
              >
                <CheckCircle progress={itemSpring} />
                <span style={{ fontSize: 26, color: COLORS.text, fontWeight: 500 }}>
                  {item}
                </span>
              </div>
            );
          })}
        </div>
      </AbsoluteFill>
    </AbsoluteFill>
  );
};
```

#### src/scenes/FrictionScene.tsx

```tsx
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";
import { Background } from "../components/Background";
import { COLORS, FRICTION_POINTS } from "../lib/constants";

const { fontFamily } = loadFont("normal", {
  weights: ["400", "700", "900"],
  subsets: ["latin"],
});

const WarningTriangle: React.FC<{ color: string; progress: number }> = ({ color, progress }) => (
  <svg width="34" height="34" viewBox="0 0 24 24" fill="none">
    <path
      d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
      fill={`${color}15`}
      stroke={color}
      strokeWidth="1.5"
      strokeLinecap="round"
      strokeLinejoin="round"
      opacity={progress}
    />
    <line x1="12" y1="9" x2="12" y2="13" stroke={color} strokeWidth="2" strokeLinecap="round" opacity={progress} />
    <circle cx="12" cy="17" r="1" fill={color} opacity={progress} />
  </svg>
);

export const FrictionScene: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const headerSpring = spring({ frame, fps, config: { damping: 200 } });

  return (
    <AbsoluteFill style={{ fontFamily }}>
      <Background accentColor={COLORS.amber} />
      <AbsoluteFill
        style={{
          justifyContent: "center",
          alignItems: "center",
          flexDirection: "column",
          gap: 44,
          padding: 80,
        }}
      >
        <div
          style={{
            display: "flex",
            alignItems: "center",
            gap: 14,
            opacity: headerSpring,
            transform: `translateY(${interpolate(headerSpring, [0, 1], [20, 0])}px)`,
          }}
        >
          <div style={{ width: 40, height: 2, background: COLORS.amber, borderRadius: 1 }} />
          <span
            style={{
              fontSize: 36,
              fontWeight: 700,
              color: COLORS.amber,
              textTransform: "uppercase",
              letterSpacing: 6,
              textShadow: `0 0 30px ${COLORS.amber}30`,
            }}
          >
            Friction Points
          </span>
          <div style={{ width: 40, height: 2, background: COLORS.amber, borderRadius: 1 }} />
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 24, width: "100%" }}>
          {FRICTION_POINTS.map((item, i) => {
            const itemSpring = spring({
              frame,
              fps,
              delay: i * 12 + 15,
              config: { damping: 200 },
            });

            const translateX = interpolate(itemSpring, [0, 1], [50, 0]);

            const countProgress = interpolate(
              frame,
              [i * 12 + 15, i * 12 + 15 + 1.5 * fps],
              [0, 1],
              { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
            );

            return (
              <div
                key={item.label}
                style={{
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "space-between",
                  opacity: itemSpring,
                  transform: `translateX(${translateX}px)`,
                  background: COLORS.bgCard,
                  borderRadius: 18,
                  padding: "26px 32px",
                  border: `1px solid ${COLORS.bgCardBorder}`,
                  borderLeftColor: item.color,
                  borderLeftWidth: 3,
                  boxShadow: `0 4px 20px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.03)`,
                }}
              >
                <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
                  <WarningTriangle color={item.color} progress={itemSpring} />
                  <span style={{ fontSize: 26, color: COLORS.text, fontWeight: 500 }}>
                    {item.label}
                  </span>
                </div>
                <div
                  style={{
                    display: "flex",
                    alignItems: "baseline",
                    gap: 4,
                  }}
                >
                  <span
                    style={{
                      fontSize: 40,
                      fontWeight: 900,
                      color: item.color,
                      fontVariantNumeric: "tabular-nums",
                      textShadow: `0 0 20px ${item.color}40`,
                    }}
                  >
                    {Math.round(countProgress * item.count)}
                  </span>
                  <span style={{ fontSize: 16, color: COLORS.textMuted, fontWeight: 500 }}>
                    events
                  </span>
                </div>
              </div>
            );
          })}
        </div>
      </AbsoluteFill>
    </AbsoluteFill>
  );
};
```

#### src/scenes/StyleScene.tsx

```tsx
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";
import { Background } from "../components/Background";
import { COLORS, STYLE_QUOTE, STYLE_SUBTITLE } from "../lib/constants";

const { fontFamily } = loadFont("normal", {
  weights: ["400", "700", "900"],
  subsets: ["latin"],
});

export const StyleScene: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const headerSpring = spring({ frame, fps, config: { damping: 200 } });

  const quote = STYLE_QUOTE;
  const words = quote.split(" ");

  const subtitleOpacity = interpolate(
    frame,
    [words.length * 6 + 40, words.length * 6 + 60],
    [0, 1],
    { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
  );

  const subtitleY = interpolate(
    frame,
    [words.length * 6 + 40, words.length * 6 + 60],
    [15, 0],
    { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
  );

  return (
    <AbsoluteFill style={{ fontFamily }}>
      <Background accentColor={COLORS.purple} />
      <AbsoluteFill
        style={{
          justifyContent: "center",
          al

…(truncated)
