{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "enhance-count",
  "title": "Enhance Count",
  "description": "A blurred line sharpens in place, 'Draft it fast. Finish it sharp.', the last word accented.",
  "dependencies": ["remotion", "@remotion/google-fonts"],
  "files": [
    {
      "path": "registry/remocn/enhance-count/index.tsx",
      "content": "\"use client\";\n\nimport { loadVariableFont } from \"@remotion/google-fonts/InterTight\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n  AbsoluteFill,\n  continueRender,\n  delayRender,\n  Easing,\n  interpolate,\n  spring,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\n\nconst inter = loadVariableFont(\"normal\", { subsets: [\"latin\"] });\n\nexport interface EnhanceCountProps {\n  text?: string;\n  highlight?: string;\n  accent?: string;\n  background?: string;\n  speed?: number;\n  theme?: \"dark\" | \"light\";\n}\n\nconst THEMES = {\n  dark: {\n    bg: \"#1C1C1E\",\n    ink: \"#E9E9E6\",\n    accent: \"#6D5BFF\",\n  },\n  light: {\n    bg: \"#E9E9E6\",\n    ink: \"#0B0B0C\",\n    accent: \"#6D5BFF\",\n  },\n} as const;\n\nconst DRAFT_WGHT = 100;\nconst DONE_WGHT = 440;\nconst TRACK = -0.025;\n\nconst ENTER_LEN = 14;\nconst ENHANCE_AT = 38;\nconst ENHANCE_SPAN = 34;\nconst ENHANCE_MAX_GAP = 2.4;\n\nconst EASE_OUT = Easing.bezier(0.22, 1, 0.36, 1);\nconst CLAMP = {\n  extrapolateLeft: \"clamp\",\n  extrapolateRight: \"clamp\",\n} as const;\n\ninterface LineMetrics {\n  chars: string[];\n  x: number[];\n  width: number;\n}\n\ninterface Metrics {\n  lines: LineMetrics[];\n  capTop: number;\n  baseline: number;\n}\n\nfunction measure(lines: string[]): Metrics {\n  const canvas = document.createElement(\"canvas\");\n  canvas.width = 10;\n  canvas.height = 10;\n  const ctx = canvas.getContext(\"2d\");\n  const size = 200;\n  const out: LineMetrics[] = [];\n  let capTop = 0.72;\n  let baseline = 0.8;\n  if (!ctx) {\n    for (const l of lines) {\n      const chars = Array.from(l);\n      out.push({\n        chars,\n        x: chars.map((_, i) => i * 0.55),\n        width: chars.length * 0.55,\n      });\n    }\n    return { lines: out, capTop, baseline };\n  }\n  ctx.font = `${DONE_WGHT} ${size}px \"${inter.fontFamily}\"`;\n  ctx.letterSpacing = `${TRACK * size}px`;\n  for (const l of lines) {\n    const chars = Array.from(l);\n    const x: number[] = [];\n    let acc = \"\";\n    for (const ch of chars) {\n      x.push(ctx.measureText(acc).width / size);\n      acc += ch;\n    }\n    out.push({ chars, x, width: ctx.measureText(acc).width / size });\n  }\n  const fm = ctx.measureText(\"H\");\n  const asc = fm.fontBoundingBoxAscent / size;\n  const desc = fm.fontBoundingBoxDescent / size;\n  baseline = (1 - (asc + desc)) / 2 + asc;\n  capTop = fm.actualBoundingBoxAscent / size;\n  return { lines: out, capTop, baseline };\n}\n\nfunction useMetrics(lines: string[]) {\n  const key = lines.join(\"\\n\");\n  const [state, setState] = useState<{ key: string; m: Metrics } | null>(null);\n  const [handle] = useState(() => delayRender(\"enhance-count: measuring\"));\n  const released = useRef(false);\n  useEffect(() => {\n    let live = true;\n    Promise.all([\n      inter.waitUntilDone(),\n      document.fonts.load(`${DONE_WGHT} 100px \"${inter.fontFamily}\"`),\n      document.fonts.load(`${DRAFT_WGHT} 100px \"${inter.fontFamily}\"`),\n    ])\n      .catch(() => undefined)\n      .then(() => {\n        if (!live) return;\n        setState({ key, m: measure(key.split(\"\\n\")) });\n        if (!released.current) {\n          released.current = true;\n          continueRender(handle);\n        }\n      });\n    return () => {\n      live = false;\n    };\n  }, [key, handle]);\n  return state && state.key === key ? state.m : null;\n}\n\nconst mix = (a: string, b: string, u: number) =>\n  `color-mix(in oklab, ${a} ${((1 - u) * 100).toFixed(1)}%, ${b})`;\n\nexport function EnhanceCount({\n  text = \"Draft it fast.\\nFinish it sharp.\",\n  highlight = \"sharp.\",\n  accent,\n  background,\n  speed = 1,\n  theme = \"dark\",\n}: EnhanceCountProps) {\n  const t = useCurrentFrame() * speed;\n  const { width: W, height: H, fps } = useVideoConfig();\n  const c = THEMES[theme];\n  const spot = accent ?? c.accent;\n  const lines = useMemo(() => {\n    const l = text\n      .split(\"\\n\")\n      .map((s) => s.trim())\n      .filter(Boolean);\n    return l.length ? l : [\"Finish it sharp.\"];\n  }, [text]);\n  const m = useMetrics(lines);\n\n  const transparent = background === \"transparent\";\n  const stage = transparent ? \"transparent\" : (background ?? c.bg);\n\n  if (!m) {\n    return (\n      <div style={{ position: \"absolute\", inset: 0, background: stage }} />\n    );\n  }\n\n  const portrait = H > W * 1.1;\n  const widest = Math.max(0.1, ...m.lines.map((l) => l.width));\n  const LH = 1.1;\n  const F = Math.min(\n    (W * (portrait ? 0.78 : 0.56)) / widest,\n    (H * (portrait ? 0.07 : 0.12)) / m.capTop,\n  );\n  const lineH = F * LH;\n  const blockH = lineH * m.lines.length;\n  const top0 = (H - blockH) / 2;\n\n  const hiWords = new Set(\n    highlight\n      .split(/\\s+/)\n      .filter(Boolean)\n      .map((w) => w.toLowerCase()),\n  );\n  const nGlyphs = m.lines.reduce((a, l) => a + l.chars.length, 0);\n  const gap = Math.min(ENHANCE_MAX_GAP, ENHANCE_SPAN / Math.max(1, nGlyphs));\n  const enter = interpolate(t, [0, ENTER_LEN], [0, 1], {\n    ...CLAMP,\n    easing: EASE_OUT,\n  });\n\n  let gi = 0;\n  const glyphs = m.lines.flatMap((line, li) => {\n    const left0 = (W - line.width * F) / 2;\n    const baseY = top0 + li * lineH + (lineH + m.capTop * F) / 2;\n    const words: boolean[] = [];\n    let wordStart = 0;\n    for (let i = 0; i <= line.chars.length; i++) {\n      if (i === line.chars.length || line.chars[i] === \" \") {\n        const w = line.chars.slice(wordStart, i).join(\"\").toLowerCase();\n        for (let k = wordStart; k < i; k++) words[k] = hiWords.has(w);\n        words[i] = false;\n        wordStart = i + 1;\n      }\n    }\n    return line.chars.map((ch, i) => {\n      const idx = gi++;\n      const u = spring({\n        frame: t - ENHANCE_AT - idx * gap,\n        fps,\n        config: { damping: 18, stiffness: 140, mass: 0.8 },\n      });\n      const uc = Math.min(1, Math.max(0, u));\n      const next = i + 1 < line.chars.length ? line.x[i + 1] : line.width;\n      const slot = (next - line.x[i]) * F;\n      const wght = DRAFT_WGHT + (DONE_WGHT - DRAFT_WGHT) * u;\n      const blur = (1 - uc) * F * 0.045;\n      const hi = words[i] && ch !== \" \";\n      const color = hi ? mix(c.ink, spot, uc) : c.ink;\n      return (\n        <div\n          key={`${li}-${i}`}\n          style={{\n            position: \"absolute\",\n            left: left0 + line.x[i] * F,\n            width: slot,\n            top: baseY - m.baseline * F,\n            height: F,\n            lineHeight: `${F}px`,\n            textAlign: \"center\",\n            whiteSpace: \"pre\",\n            fontFamily: inter.fontFamily,\n            fontSize: F,\n            fontVariationSettings: `\"wght\" ${wght.toFixed(1)}`,\n            color,\n            opacity: enter * (0.5 + 0.5 * uc),\n            filter: blur > 0.05 ? `blur(${blur.toFixed(2)}px)` : undefined,\n          }}\n        >\n          {ch}\n        </div>\n      );\n    });\n  });\n\n  return (\n    <AbsoluteFill style={{ background: stage, overflow: \"hidden\" }}>\n      {glyphs}\n    </AbsoluteFill>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/enhance-count.tsx"
    }
  ],
  "type": "registry:component"
}
