{
  "name": "video-player",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "files": [
    {
      "path": "ui/video-player.tsx",
      "content": "\"use client\";\n\nimport {\n  ChevronLeft,\n  ChevronRight,\n  ChevronsLeft,\n  ChevronsRight,\n  Loader2,\n  Maximize,\n  Maximize2,\n  MessageCircle,\n  Minimize,\n  MoreVertical,\n  Pause,\n  PictureInPicture2,\n  Play,\n  Repeat,\n  RotateCcw,\n  RotateCw,\n  Settings,\n  Volume2,\n  VolumeX,\n} from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport type React from \"react\";\nimport {\n  forwardRef,\n  useEffect,\n  useImperativeHandle,\n  useRef,\n  useState,\n} from \"react\";\n\ninterface QualitySource {\n  quality: string;\n  src: string;\n}\n\ninterface CaptionTrack {\n  src: string;\n  label: string;\n  srcLang: string;\n  default?: boolean;\n}\n\ninterface Chapter {\n  title: string;\n  startTime: number;\n  endTime: number;\n}\n\nexport interface VideoPlayerProps {\n  src: string | QualitySource[];\n  tracks?: CaptionTrack[];\n  poster?: string;\n  title?: string;\n  description?: string;\n  compact?: boolean;\n  chapters?: Chapter[];\n  onTimeUpdate?: (time: number) => void;\n  onNextVideo?: () => void;\n  onPrevVideo?: () => void;\n  currentVideoIndex?: number;\n  totalVideos?: number;\n}\n\nexport interface VideoPlayerRef {\n  seek: (time: number) => void;\n  play: () => void;\n  pause: () => void;\n}\n\nconst Tooltip = ({\n  children,\n  label,\n}: {\n  children: React.ReactNode;\n  label: string;\n}) => {\n  const [isHovered, setIsHovered] = useState(false);\n\n  return (\n    <div\n      className=\"relative inline-flex\"\n      onMouseEnter={() => setIsHovered(true)}\n      onMouseLeave={() => setIsHovered(false)}\n      role=\"button\"\n      tabIndex={0}\n    >\n      {children}\n      <motion.div\n        initial={{ opacity: 0 }}\n        animate={{ opacity: isHovered ? 1 : 0 }}\n        transition={{ duration: 0.2 }}\n        className=\"pointer-events-none absolute bottom-full left-1/2 z-50 mb-2 -translate-x-1/2 whitespace-nowrap rounded bg-black/90 px-2 py-1 text-white text-xs\"\n      >\n        {label}\n      </motion.div>\n    </div>\n  );\n};\n\nexport const VideoPlayer = forwardRef<VideoPlayerRef, VideoPlayerProps>(\n  (\n    {\n      src,\n      tracks = [],\n      poster,\n      title: _title,\n      description: _description,\n      compact: _compact = false,\n      chapters = [],\n      onTimeUpdate,\n      onNextVideo,\n      onPrevVideo,\n      currentVideoIndex = 0,\n      totalVideos = 1,\n    },\n    ref,\n  ) => {\n    const videoRef = useRef<HTMLVideoElement>(null);\n    const containerRef = useRef<HTMLDivElement>(null);\n\n    const [isPlaying, setIsPlaying] = useState(false);\n    const [isMuted, setIsMuted] = useState(false);\n    const [isFullscreen, setIsFullscreen] = useState(false);\n    const [isLoading, setIsLoading] = useState(false);\n    const [showControls, setShowControls] = useState(true);\n    const [activeDialog, setActiveDialog] = useState<\n      \"settings\" | \"options\" | \"captions\" | null\n    >(null);\n    const [volume, setVolume] = useState(1);\n    const [showVolumeSlider, setShowVolumeSlider] = useState(false);\n    const [quality, setQuality] = useState(\"auto\");\n    const [availableQualities, setAvailableQualities] = useState<string[]>([]);\n    const [currentSrc, setCurrentSrc] = useState(\"\");\n    const [speed, setSpeed] = useState(1);\n    const [isPictureInPicture, setIsPictureInPicture] = useState(false);\n    const [currentCaption, setCurrentCaption] = useState<string | null>(null);\n    const [isTheaterMode, setIsTheaterMode] = useState(false);\n    const [isLooping, setIsLooping] = useState(false);\n\n    const [currentTime, setCurrentTime] = useState(0);\n    const [duration, setDuration] = useState(0);\n    const [buffered, setBuffered] = useState(0);\n\n    // Hover state for timeline\n    const [hoverTime, setHoverTime] = useState<number | null>(null);\n    const [hoverPosition, setHoverPosition] = useState<number | null>(null);\n\n    // Double tap state\n    const [doubleTapAction, setDoubleTapAction] = useState<{\n      side: \"left\" | \"right\";\n      id: number;\n    } | null>(null);\n    const lastTapRef = useRef<{ time: number; x: number } | null>(null);\n    const tapTimeoutRef = useRef<NodeJS.Timeout>(undefined);\n\n    const controlsTimeoutRef = useRef<NodeJS.Timeout>(undefined);\n\n    const handleTap = (e: React.MouseEvent<HTMLDivElement>) => {\n      const time = Date.now();\n      const clientX = e.clientX;\n      const rect = containerRef.current?.getBoundingClientRect();\n      if (!rect) return;\n\n      const x = clientX - rect.left;\n      const width = rect.width;\n      const isLeft = x < width * 0.3;\n      const isRight = x > width * 0.7;\n\n      if (!isLeft && !isRight) {\n        togglePlay();\n        return;\n      }\n\n      if (lastTapRef.current && time - lastTapRef.current.time < 300) {\n        // Double tap detected\n        if (tapTimeoutRef.current) {\n          clearTimeout(tapTimeoutRef.current);\n        }\n\n        if (isLeft) {\n          handleSkip(-10);\n          setDoubleTapAction({ side: \"left\", id: time });\n        } else {\n          handleSkip(10);\n          setDoubleTapAction({ side: \"right\", id: time });\n        }\n        lastTapRef.current = null;\n      } else {\n        // First tap\n        lastTapRef.current = { time, x };\n        tapTimeoutRef.current = setTimeout(() => {\n          togglePlay();\n          lastTapRef.current = null;\n        }, 300);\n      }\n    };\n\n    // Clear double tap action after animation\n    useEffect(() => {\n      if (doubleTapAction) {\n        const timeout = setTimeout(() => {\n          setDoubleTapAction(null);\n        }, 1000);\n        return () => clearTimeout(timeout);\n      }\n    }, [doubleTapAction]);\n\n    useImperativeHandle(ref, () => ({\n      seek: (time: number) => {\n        if (videoRef.current) {\n          videoRef.current.currentTime = time;\n          setCurrentTime(time);\n        }\n      },\n      play: () => {\n        videoRef.current?.play();\n      },\n      pause: () => {\n        videoRef.current?.pause();\n      },\n    }));\n\n    // Initialize quality sources\n    useEffect(() => {\n      if (Array.isArray(src)) {\n        const qualities = src.map((s) => s.quality);\n        setAvailableQualities([\"auto\", ...qualities]);\n        // Default to the first quality source if auto\n        setCurrentSrc(src[0]?.src || \"\");\n      } else {\n        setAvailableQualities([\"auto\"]);\n        setCurrentSrc(src);\n      }\n    }, [src]);\n\n    // Initialize captions\n    useEffect(() => {\n      if (tracks.length > 0) {\n        const defaultTrack = tracks.find((t) => t.default);\n        if (defaultTrack) {\n          setCurrentCaption(defaultTrack.srcLang);\n        }\n      }\n    }, [tracks]);\n\n    // Handle caption change\n    const handleCaptionChange = (lang: string | null) => {\n      setCurrentCaption(lang);\n      if (videoRef.current) {\n        const textTracks = videoRef.current.textTracks;\n        for (let i = 0; i < textTracks.length; i++) {\n          const track = textTracks[i];\n          if (track) {\n            if (lang && track.language === lang) {\n              track.mode = \"showing\";\n            } else {\n              track.mode = \"hidden\";\n            }\n          }\n        }\n      }\n    };\n\n    // Format time display\n    const formatTime = (time: number) => {\n      if (!time || Number.isNaN(time)) return \"0:00\";\n      const hours = Math.floor(time / 3600);\n      const minutes = Math.floor((time % 3600) / 60);\n      const seconds = Math.floor(time % 60);\n\n      if (hours > 0) {\n        return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n      }\n      return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n    };\n\n    // Handle play/pause\n    const togglePlay = () => {\n      if (videoRef.current) {\n        if (isPlaying) {\n          videoRef.current.pause();\n        } else {\n          videoRef.current.play();\n        }\n        setIsPlaying(!isPlaying);\n      }\n    };\n\n    // Handle volume change\n    const handleVolumeChange = (value: number[]) => {\n      const newVolume = value[0] ?? 1;\n      setVolume(newVolume);\n      if (videoRef.current) {\n        videoRef.current.volume = newVolume;\n      }\n      if (newVolume === 0) {\n        setIsMuted(true);\n      } else if (isMuted) {\n        setIsMuted(false);\n      }\n    };\n\n    // Toggle mute\n    const toggleMute = () => {\n      if (videoRef.current) {\n        if (isMuted) {\n          videoRef.current.volume = volume || 0.5;\n          setIsMuted(false);\n        } else {\n          videoRef.current.volume = 0;\n          setIsMuted(true);\n        }\n      }\n    };\n\n    // Handle progress bar click\n    const handleProgressClick = (e: React.MouseEvent<HTMLDivElement>) => {\n      if (!videoRef.current || !duration) return;\n      const rect = e.currentTarget.getBoundingClientRect();\n      const percent = (e.clientX - rect.left) / rect.width;\n      const newTime = percent * duration;\n      videoRef.current.currentTime = newTime;\n      setCurrentTime(newTime);\n    };\n\n    // Handle progress bar hover\n    const handleProgressHover = (e: React.MouseEvent<HTMLDivElement>) => {\n      if (!duration) return;\n      const rect = e.currentTarget.getBoundingClientRect();\n      const percent = (e.clientX - rect.left) / rect.width;\n      const time = Math.max(0, Math.min(percent * duration, duration));\n      setHoverTime(time);\n      setHoverPosition(percent * 100);\n    };\n\n    const handleProgressLeave = () => {\n      setHoverTime(null);\n      setHoverPosition(null);\n    };\n\n    // Toggle fullscreen\n    const toggleFullscreen = () => {\n      if (!containerRef.current) return;\n\n      if (!isFullscreen) {\n        if (containerRef.current.requestFullscreen) {\n          containerRef.current.requestFullscreen();\n        } else if (\n          (\n            containerRef.current as HTMLElement & {\n              webkitRequestFullscreen?: () => void;\n            }\n          ).webkitRequestFullscreen\n        ) {\n          (\n            containerRef.current as HTMLElement & {\n              webkitRequestFullscreen?: () => void;\n            }\n          ).webkitRequestFullscreen?.();\n        }\n        setIsFullscreen(true);\n      } else {\n        if (document.fullscreenElement) {\n          document.exitFullscreen();\n        }\n        setIsFullscreen(false);\n      }\n    };\n\n    const toggleTheaterMode = () => {\n      const newTheaterMode = !isTheaterMode;\n      setIsTheaterMode(newTheaterMode);\n\n      // Lock/unlock body scroll\n      if (newTheaterMode) {\n        document.body.style.overflow = \"hidden\";\n      } else {\n        document.body.style.overflow = \"\";\n      }\n    };\n\n    // Handle Picture-in-Picture\n    const togglePictureInPicture = async () => {\n      try {\n        if (document.pictureInPictureElement) {\n          await document.exitPictureInPicture();\n          setIsPictureInPicture(false);\n        } else if (videoRef.current && document.pictureInPictureEnabled) {\n          await videoRef.current.requestPictureInPicture();\n          setIsPictureInPicture(true);\n        }\n      } catch (error) {\n        console.error(\"PiP error:\", error);\n      }\n    };\n\n    // Handle quality change\n    const handleQualityChange = (newQuality: string) => {\n      if (!videoRef.current) return;\n\n      const currentTime = videoRef.current.currentTime;\n      const wasPlaying = !videoRef.current.paused;\n\n      setQuality(newQuality);\n\n      if (Array.isArray(src)) {\n        let newSrc = \"\";\n        if (newQuality === \"auto\") {\n          newSrc = src[0]?.src || \"\";\n        } else {\n          const source = src.find((s) => s.quality === newQuality);\n          if (source) newSrc = source.src;\n        }\n\n        if (newSrc && newSrc !== currentSrc) {\n          setCurrentSrc(newSrc);\n          // Restore playback position after source change\n          const handleCanPlay = () => {\n            if (videoRef.current) {\n              videoRef.current.currentTime = currentTime;\n              if (wasPlaying) videoRef.current.play();\n              videoRef.current.removeEventListener(\n                \"loadedmetadata\",\n                handleCanPlay,\n              );\n            }\n          };\n          videoRef.current.addEventListener(\"loadedmetadata\", handleCanPlay);\n        }\n      }\n    };\n\n    // Handle speed change\n    const handleSpeedChange = (newSpeed: number) => {\n      setSpeed(newSpeed);\n      if (videoRef.current) {\n        videoRef.current.playbackRate = newSpeed;\n      }\n    };\n\n    // Handle skip\n    const handleSkip = (seconds: number) => {\n      if (videoRef.current) {\n        videoRef.current.currentTime += seconds;\n      }\n    };\n\n    const handleToggleLoop = () => {\n      if (videoRef.current) {\n        videoRef.current.loop = !videoRef.current.loop;\n        setIsLooping(!isLooping);\n      }\n    };\n\n    // Handle video metadata loaded\n    const handleLoadedMetadata = () => {\n      setDuration(videoRef.current?.duration || 0);\n      setIsLoading(false);\n    };\n\n    // Handle time update\n    const handleTimeUpdate = () => {\n      setCurrentTime(videoRef.current?.currentTime || 0);\n      if (onTimeUpdate) {\n        onTimeUpdate(videoRef.current?.currentTime || 0);\n      }\n\n      // Update buffered amount\n      if (videoRef.current && videoRef.current.buffered.length > 0) {\n        const bufferedEnd = videoRef.current.buffered.end(\n          videoRef.current.buffered.length - 1,\n        );\n        setBuffered((bufferedEnd / duration) * 100);\n      }\n    };\n\n    // Handle fullscreen change\n    useEffect(() => {\n      const handleFullscreenChange = () => {\n        setIsFullscreen(!!document.fullscreenElement);\n      };\n      document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n      return () =>\n        document.removeEventListener(\n          \"fullscreenchange\",\n          handleFullscreenChange,\n        );\n    }, []);\n\n    // Handle mouse movement for controls\n    useEffect(() => {\n      const container = containerRef.current;\n      if (!container) return;\n\n      const handleMouseMove = () => {\n        setShowControls(true);\n        if (controlsTimeoutRef.current) {\n          clearTimeout(controlsTimeoutRef.current);\n        }\n\n        if (isPlaying) {\n          controlsTimeoutRef.current = setTimeout(() => {\n            setShowControls(false);\n          }, 3000);\n        }\n      };\n\n      container.addEventListener(\"mousemove\", handleMouseMove);\n      return () => container.removeEventListener(\"mousemove\", handleMouseMove);\n    }, [isPlaying]);\n\n    return (\n      <div\n        ref={containerRef}\n        className={`group relative w-full overflow-hidden rounded-lg bg-black ${\n          isTheaterMode\n            ? \"fixed inset-0 z-50 h-screen w-screen rounded-none\"\n            : \"\"\n        }`}\n      >\n        <div\n          className={`relative w-full transition-all duration-300 ${isTheaterMode ? \"h-screen\" : \"aspect-video\"}`}\n        >\n          {/* Video Element */}\n          {/* biome-ignore lint/a11y/useMediaCaption: Video player component may not have captions */}\n          <video\n            ref={videoRef}\n            src={currentSrc}\n            poster={poster}\n            onLoadedMetadata={handleLoadedMetadata}\n            onTimeUpdate={handleTimeUpdate}\n            onPlay={() => setIsPlaying(true)}\n            onPause={() => setIsPlaying(false)}\n            onLoadStart={() => setIsLoading(true)}\n            onEnded={() => setIsPlaying(false)}\n            className=\"absolute inset-0 h-full w-full\"\n          >\n            {tracks.map((track, index) => (\n              <track\n                key={index}\n                kind=\"subtitles\"\n                src={track.src}\n                srcLang={track.srcLang}\n                label={track.label}\n                default={track.default}\n              />\n            ))}\n          </video>\n\n          {/* Loading Spinner */}\n          <AnimatePresence>\n            {isLoading && (\n              <motion.div\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{ opacity: 0 }}\n                className=\"absolute inset-0 flex items-center justify-center bg-black/20 backdrop-blur-sm\"\n              >\n                <motion.div\n                  animate={{ rotate: 360 }}\n                  transition={{ duration: 1, repeat: Number.POSITIVE_INFINITY }}\n                >\n                  <Loader2 className=\"h-12 w-12 text-white\" />\n                </motion.div>\n              </motion.div>\n            )}\n          </AnimatePresence>\n\n          {/* Controls Background Gradient */}\n          <AnimatePresence>\n            {showControls && (\n              <motion.div\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{ opacity: 0 }}\n                className=\"absolute right-0 bottom-0 left-0 h-32 bg-gradient-to-t from-black via-black/50 to-transparent\"\n              />\n            )}\n          </AnimatePresence>\n\n          {/* Click Overlay */}\n          <div\n            className=\"absolute inset-0 z-10\"\n            onClick={handleTap}\n            role=\"button\"\n            aria-label=\"Play/Pause\"\n            tabIndex={0}\n          />\n\n          {/* Double Tap Animation */}\n          <AnimatePresence>\n            {doubleTapAction && (\n              <div\n                key={doubleTapAction.id}\n                className={`absolute inset-y-0 ${\n                  doubleTapAction.side === \"left\"\n                    ? \"left-0 justify-start pl-12\"\n                    : \"right-0 justify-end pr-12\"\n                } pointer-events-none z-20 flex w-1/2 items-center`}\n              >\n                <motion.div\n                  initial={{ opacity: 0, scale: 0.5 }}\n                  animate={{ opacity: 1, scale: 1 }}\n                  exit={{ opacity: 0, scale: 1.5 }}\n                  transition={{ duration: 0.5 }}\n                  className=\"flex flex-col items-center justify-center rounded-full shadow-lg\"\n                >\n                  {doubleTapAction.side === \"left\" ? (\n                    <>\n                      <ChevronsLeft className=\"h-8 w-8 text-white\" />\n                      <span className=\"mt-1 select-none font-bold text-white text-xs shadow-lg\">\n                        10s\n                      </span>\n                    </>\n                  ) : (\n                    <>\n                      <ChevronsRight className=\"h-8 w-8 text-white\" />\n                      <span className=\"mt-1 select-none font-bold text-white text-xs shadow-lg\">\n                        10s\n                      </span>\n                    </>\n                  )}\n                </motion.div>\n              </div>\n            )}\n          </AnimatePresence>\n\n          {/* Center Play Button */}\n          <AnimatePresence>\n            {showControls && !isPlaying && (\n              <motion.button\n                initial={{ opacity: 0, scale: 0.8 }}\n                animate={{ opacity: 1, scale: 1 }}\n                exit={{ opacity: 0, scale: 0.8 }}\n                className=\"pointer-events-none absolute inset-0 z-20 flex items-center justify-center\"\n              >\n                <motion.div\n                  whileHover={{ scale: 1.1 }}\n                  whileTap={{ scale: 0.95 }}\n                  className=\"pointer-events-auto rounded-full bg-white/20 p-4 backdrop-blur-sm transition-colors hover:bg-white/30\"\n                  onClick={togglePlay}\n                >\n                  <Play className=\"h-12 w-12 fill-white text-white\" />\n                </motion.div>\n              </motion.button>\n            )}\n          </AnimatePresence>\n\n          {/* Controls Bar */}\n          <AnimatePresence>\n            {showControls && (\n              <motion.div\n                initial={{ opacity: 0, y: 20 }}\n                animate={{ opacity: 1, y: 0 }}\n                exit={{ opacity: 0, y: 20 }}\n                className=\"absolute right-0 bottom-0 left-0 z-40 flex flex-col gap-3 px-4 py-3\"\n              >\n                {/* Progress Bar */}\n                <div\n                  onClick={handleProgressClick}\n                  onMouseMove={handleProgressHover}\n                  onMouseLeave={handleProgressLeave}\n                  className=\"group/progress relative h-1.5 w-full cursor-pointer rounded-full bg-white/20 transition-all hover:h-2\"\n                  role=\"button\"\n                  aria-label=\"Seek\"\n                  tabIndex={0}\n                >\n                  {/* Buffered indicator */}\n                  <div\n                    className=\"absolute inset-y-0 left-0 rounded-full bg-white/40\"\n                    style={{ width: `${buffered}%` }}\n                  />\n\n                  {/* Progress indicator */}\n                  <div\n                    className=\"absolute inset-y-0 left-0 rounded-full bg-gradient-to-r from-blue-500 to-cyan-400 transition-all\"\n                    style={{ width: `${(currentTime / duration) * 100}%` }}\n                  />\n\n                  {/* Chapter markers */}\n                  {chapters.length > 0 && duration > 0 && (\n                    <div className=\"pointer-events-none absolute inset-0 h-full w-full\">\n                      {chapters.map((chapter, index) => {\n                        if (index === 0) return null;\n                        const left = (chapter.startTime / duration) * 100;\n                        return (\n                          <div\n                            key={index}\n                            className=\"absolute top-0 bottom-0 z-10 w-0.5 bg-black/50\"\n                            style={{ left: `${left}%` }}\n                          />\n                        );\n                      })}\n                    </div>\n                  )}\n\n                  {/* Scrubber */}\n                  <motion.div\n                    className=\"absolute top-1/2 z-20 h-4 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 shadow-lg transition-opacity group-hover/progress:opacity-100\"\n                    style={{ left: `${(currentTime / duration) * 100}%` }}\n                  />\n\n                  {/* Hover Time Tooltip */}\n                  <AnimatePresence>\n                    {hoverTime !== null && hoverPosition !== null && (\n                      <motion.div\n                        initial={{ opacity: 0, y: 10, scale: 0.8 }}\n                        animate={{ opacity: 1, y: 0, scale: 1 }}\n                        exit={{ opacity: 0, y: 10, scale: 0.8 }}\n                        className=\"pointer-events-none absolute bottom-full z-50 mb-4 flex -translate-x-1/2 flex-col items-center gap-0.5 whitespace-nowrap rounded-lg border border-white/10 bg-black/90 px-2 py-1 text-white text-xs\"\n                        style={{ left: `${hoverPosition}%` }}\n                      >\n                        {chapters.length > 0 && (\n                          <span className=\"font-medium text-white/90\">\n                            {\n                              chapters.find((c, i) => {\n                                const nextChapter = chapters[i + 1];\n                                return (\n                                  hoverTime >= c.startTime &&\n                                  (!nextChapter ||\n                                    hoverTime < nextChapter.startTime)\n                                );\n                              })?.title\n                            }\n                          </span>\n                        )}\n                        <span\n                          className={chapters.length > 0 ? \"text-white/70\" : \"\"}\n                        >\n                          {formatTime(hoverTime)}\n                        </span>\n                      </motion.div>\n                    )}\n                  </AnimatePresence>\n                </div>\n\n                {/* Time Display and Controls */}\n                <div className=\"flex items-center justify-between gap-2\">\n                  {/* Left Controls */}\n                  <div className=\"flex items-center gap-1\">\n                    {/* Play/Pause */}\n                    <Tooltip\n                      label={isPlaying ? \"Pause (Space)\" : \"Play (Space)\"}\n                    >\n                      <motion.button\n                        whileHover={{ scale: 1.1 }}\n                        whileTap={{ scale: 0.95 }}\n                        onClick={togglePlay}\n                        className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                        aria-label=\"Play/Pause\"\n                      >\n                        {isPlaying ? (\n                          <Pause className=\"h-5 w-5 fill-white text-white\" />\n                        ) : (\n                          <Play className=\"h-5 w-5 fill-white text-white\" />\n                        )}\n                      </motion.button>\n                    </Tooltip>\n\n                    {/* Skip Back 10s */}\n                    <Tooltip label=\"Previous 10 seconds (J)\">\n                      <motion.button\n                        whileHover={{ scale: 1.1 }}\n                        whileTap={{ scale: 0.95 }}\n                        onClick={() => handleSkip(-10)}\n                        className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                        aria-label=\"Skip back 10 seconds\"\n                      >\n                        <RotateCcw className=\"h-5 w-5 text-white\" />\n                      </motion.button>\n                    </Tooltip>\n\n                    {/* Skip Forward 10s */}\n                    <Tooltip label=\"Next 10 seconds (L)\">\n                      <motion.button\n                        whileHover={{ scale: 1.1 }}\n                        whileTap={{ scale: 0.95 }}\n                        onClick={() => handleSkip(10)}\n                        className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                        aria-label=\"Skip forward 10 seconds\"\n                      >\n                        <RotateCw className=\"h-5 w-5 text-white\" />\n                      </motion.button>\n                    </Tooltip>\n\n                    {/* Previous Video */}\n                    {currentVideoIndex > 0 && (\n                      <Tooltip label=\"Previous Video\">\n                        <motion.button\n                          whileHover={{ scale: 1.1 }}\n                          whileTap={{ scale: 0.95 }}\n                          onClick={onPrevVideo}\n                          className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                          aria-label=\"Previous video\"\n                        >\n                          <ChevronLeft className=\"h-5 w-5 text-white\" />\n                        </motion.button>\n                      </Tooltip>\n                    )}\n\n                    {/* Next Video */}\n                    {currentVideoIndex < totalVideos - 1 && (\n                      <Tooltip label=\"Next Video\">\n                        <motion.button\n                          whileHover={{ scale: 1.1 }}\n                          whileTap={{ scale: 0.95 }}\n                          onClick={onNextVideo}\n                          className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                          aria-label=\"Next video\"\n                        >\n                          <ChevronRight className=\"h-5 w-5 text-white\" />\n                        </motion.button>\n                      </Tooltip>\n                    )}\n\n                    {/* Volume Control */}\n                    <div className=\"flex items-center gap-1\">\n                      <Tooltip label={isMuted ? \"Unmute (M)\" : \"Mute (M)\"}>\n                        <motion.button\n                          whileHover={{ scale: 1.1 }}\n                          whileTap={{ scale: 0.95 }}\n                          onMouseEnter={() => setShowVolumeSlider(true)}\n                          onMouseLeave={() => setShowVolumeSlider(false)}\n                          onClick={toggleMute}\n                          className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                          aria-label=\"Mute/Unmute\"\n                        >\n                          {isMuted ? (\n                            <VolumeX className=\"h-5 w-5 text-white\" />\n                          ) : (\n                            <Volume2 className=\"h-5 w-5 text-white\" />\n                          )}\n                        </motion.button>\n                      </Tooltip>\n\n                      {/* Volume Slider */}\n                      <AnimatePresence>\n                        {showVolumeSlider && (\n                          <motion.div\n                            initial={{ opacity: 0, width: 0 }}\n                            animate={{ opacity: 1, width: 80 }}\n                            exit={{ opacity: 0, width: 0 }}\n                            className=\"flex items-center overflow-hidden pl-2\"\n                            onMouseEnter={() => setShowVolumeSlider(true)}\n                            onMouseLeave={() => setShowVolumeSlider(false)}\n                          >\n                            <input\n                              type=\"range\"\n                              min=\"0\"\n                              max=\"1\"\n                              step=\"0.01\"\n                              value={isMuted ? 0 : volume}\n                              onChange={(e) =>\n                                handleVolumeChange([\n                                  Number.parseFloat(e.target.value),\n                                ])\n                              }\n                              className=\"h-1 w-full cursor-pointer appearance-none rounded-full focus:outline-none [&::-moz-range-thumb]:h-3 [&::-moz-range-thumb]:w-3 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-none [&::-moz-range-thumb]:bg-white [&::-webkit-slider-thumb]:h-3 [&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white\"\n                              style={{\n                                background: `linear-gradient(to right, white ${isMuted ? 0 : volume * 100}%, rgba(255, 255, 255, 0.2) ${isMuted ? 0 : volume * 100}%)`,\n                              }}\n                            />\n                          </motion.div>\n                        )}\n                      </AnimatePresence>\n                    </div>\n\n                    {/* Time Display */}\n                    <span className=\"ml-2 flex min-w-24 items-center text-sm text-white\">\n                      {formatTime(currentTime)} / {formatTime(duration)}\n                    </span>\n                  </div>\n\n                  {/* Right Controls */}\n                  <div className=\"flex items-center gap-1\">\n                    {/* Captions */}\n                    {tracks.length > 0 && (\n                      <div className=\"relative flex items-center\">\n                        <Tooltip label=\"Captions (C)\">\n                          <motion.button\n                            whileHover={{ scale: 1.1 }}\n                            whileTap={{ scale: 0.95 }}\n                            onClick={() => {\n                              if (tracks.length === 1 && tracks[0]) {\n                                handleCaptionChange(\n                                  currentCaption ? null : tracks[0].srcLang,\n                                );\n                              } else {\n                                setActiveDialog(\n                                  activeDialog === \"captions\"\n                                    ? null\n                                    : \"captions\",\n                                );\n                              }\n                            }}\n                            className={`flex items-center justify-center rounded-lg p-2 transition-colors ${\n                              currentCaption\n                                ? \"bg-cyan-500/30 hover:bg-cyan-500/40\"\n                                : \"hover:bg-white/20\"\n                            }`}\n                            aria-label=\"Captions\"\n                          >\n                            <MessageCircle className=\"h-5 w-5 text-white\" />\n                          </motion.button>\n                        </Tooltip>\n\n                        <AnimatePresence>\n                          {activeDialog === \"captions\" && tracks.length > 1 && (\n                            <motion.div\n                              initial={{ opacity: 0, y: 10 }}\n                              animate={{ opacity: 1, y: 0 }}\n                              exit={{ opacity: 0, y: 10 }}\n                              className=\"absolute right-0 bottom-full z-50 mb-2 min-w-40 rounded-lg border border-white/10 bg-black/95 p-3 backdrop-blur-sm\"\n                            >\n                              <p className=\"mb-2 font-semibold text-white text-xs uppercase opacity-70\">\n                                Captions\n                              </p>\n                              <div className=\"space-y-1\">\n                                <button\n                                  onClick={() => {\n                                    handleCaptionChange(null);\n                                    setActiveDialog(null);\n                                  }}\n                                  className={`w-full rounded px-2 py-1 text-left text-sm transition-colors ${\n                                    !currentCaption\n                                      ? \"bg-cyan-500 text-white\"\n                                      : \"text-white/70 hover:bg-white/10\"\n                                  }`}\n                                >\n                                  Off\n                                </button>\n                                {tracks.map((track) => (\n                                  <button\n                                    key={track.srcLang}\n                                    onClick={() => {\n                                      handleCaptionChange(track.srcLang);\n                                      setActiveDialog(null);\n                                    }}\n                                    className={`w-full rounded px-2 py-1 text-left text-sm transition-colors ${\n                                      currentCaption === track.srcLang\n                                        ? \"bg-cyan-500 text-white\"\n                                        : \"text-white/70 hover:bg-white/10\"\n                                    }`}\n                                  >\n                                    {track.label}\n                                  </button>\n                                ))}\n                              </div>\n                            </motion.div>\n                          )}\n                        </AnimatePresence>\n                      </div>\n                    )}\n\n                    {/* Picture-in-Picture */}\n                    <Tooltip label=\"Picture in Picture (P)\">\n                      <motion.button\n                        whileHover={{ scale: 1.1 }}\n                        whileTap={{ scale: 0.95 }}\n                        onClick={togglePictureInPicture}\n                        className={`flex items-center justify-center rounded-lg p-2 transition-colors ${\n                          isPictureInPicture\n                            ? \"bg-cyan-500/30 hover:bg-cyan-500/40\"\n                            : \"hover:bg-white/20\"\n                        }`}\n                        aria-label=\"Picture in Picture\"\n                      >\n                        <PictureInPicture2 className=\"h-5 w-5 text-white\" />\n                      </motion.button>\n                    </Tooltip>\n\n                    {/* Settings */}\n                    <div className=\"relative flex items-center\">\n                      <Tooltip label=\"Settings\">\n                        <motion.button\n                          whileHover={{ scale: 1.1 }}\n                          whileTap={{ scale: 0.95 }}\n                          onClick={() =>\n                            setActiveDialog(\n                              activeDialog === \"settings\" ? null : \"settings\",\n                            )\n                          }\n                          className={`flex items-center justify-center rounded-lg p-2 transition-colors ${\n                            activeDialog === \"settings\"\n                              ? \"bg-cyan-500/30\"\n                              : \"hover:bg-white/20\"\n                          }`}\n                          aria-label=\"Settings\"\n                        >\n                          <Settings className=\"h-5 w-5 text-white\" />\n                        </motion.button>\n                      </Tooltip>\n\n                      <AnimatePresence>\n                        {activeDialog === \"settings\" && (\n                          <motion.div\n                            initial={{ opacity: 0, y: 10 }}\n                            animate={{ opacity: 1, y: 0 }}\n                            exit={{ opacity: 0, y: 10 }}\n                            className=\"absolute right-0 bottom-full z-50 mb-2 min-w-40 rounded-lg border border-white/10 bg-black/95 p-3 backdrop-blur-sm\"\n                          >\n                            {/* Quality Selection */}\n                            {availableQualities.length > 1 && (\n                              <div className=\"mb-3\">\n                                <p className=\"mb-2 font-semibold text-white text-xs uppercase opacity-70\">\n                                  Quality\n                                </p>\n                                <div className=\"space-y-1\">\n                                  {availableQualities.map((q) => (\n                                    <button\n                                      key={q}\n                                      onClick={() => handleQualityChange(q)}\n                                      className={`w-full rounded px-2 py-1 text-left text-sm transition-colors ${\n                                        quality === q\n                                          ? \"bg-cyan-500 text-white\"\n                                          : \"text-white/70 hover:bg-white/10\"\n                                      }`}\n                                    >\n                                      {q}\n                                    </button>\n                                  ))}\n                                </div>\n                              </div>\n                            )}\n\n                            {/* Speed Selection */}\n                            <div>\n                              <p className=\"mb-2 font-semibold text-white text-xs uppercase opacity-70\">\n                                Speed\n                              </p>\n                              <div className=\"space-y-1\">\n                                {[0.5, 0.75, 1, 1.25, 1.5, 2].map((s) => (\n                                  <button\n                                    key={s}\n                                    onClick={() => handleSpeedChange(s)}\n                                    className={`w-full rounded px-2 py-1 text-left text-sm transition-colors ${\n                                      speed === s\n                                        ? \"bg-cyan-500 text-white\"\n                                        : \"text-white/70 hover:bg-white/10\"\n                                    }`}\n                                  >\n                                    {s}x\n                                  </button>\n                                ))}\n                              </div>\n                            </div>\n                          </motion.div>\n                        )}\n                      </AnimatePresence>\n                    </div>\n\n                    {/* More Options */}\n                    <div className=\"relative flex items-center\">\n                      <Tooltip label=\"More Options\">\n                        <motion.button\n                          whileHover={{ scale: 1.1 }}\n                          whileTap={{ scale: 0.95 }}\n                          onClick={() =>\n                            setActiveDialog(\n                              activeDialog === \"options\" ? null : \"options\",\n                            )\n                          }\n                          className={`flex items-center justify-center rounded-lg p-2 transition-colors ${\n                            activeDialog === \"options\"\n                              ? \"bg-cyan-500/30\"\n                              : \"hover:bg-white/20\"\n                          }`}\n                          aria-label=\"More options\"\n                        >\n                          <MoreVertical className=\"h-5 w-5 text-white\" />\n                        </motion.button>\n                      </Tooltip>\n\n                      <AnimatePresence>\n                        {activeDialog === \"options\" && (\n                          <motion.div\n                            initial={{ opacity: 0, y: 10 }}\n                            animate={{ opacity: 1, y: 0 }}\n                            exit={{ opacity: 0, y: 10 }}\n                            className=\"absolute right-0 bottom-full z-50 mb-2 min-w-48 rounded-lg border border-white/10 bg-black/95 p-2 backdrop-blur-sm\"\n                          >\n                            {/* Theater Mode */}\n                            <button\n                              onClick={() => {\n                                toggleTheaterMode();\n                                setActiveDialog(null);\n                              }}\n                              className=\"flex w-full items-center gap-2 rounded px-3 py-2 text-left text-sm text-white transition-colors hover:bg-white/10\"\n                            >\n                              <Maximize2 className=\"h-4 w-4\" />\n                              {isTheaterMode\n                                ? \"Exit Theater Mode\"\n                                : \"Theater Mode\"}\n                            </button>\n\n                            {/* Loop */}\n                            <button\n                              onClick={() => handleToggleLoop()}\n                              className={`flex w-full items-center gap-2 rounded px-3 py-2 text-left text-sm transition-colors ${\n                                isLooping\n                                  ? \"bg-cyan-500/30 text-white\"\n                                  : \"text-white hover:bg-white/10\"\n                              }`}\n                            >\n                              <Repeat className=\"h-4 w-4\" />\n                              Loop\n                            </button>\n                          </motion.div>\n                        )}\n                      </AnimatePresence>\n                    </div>\n\n                    {/* Fullscreen */}\n                    <Tooltip\n                      label={\n                        isFullscreen ? \"Exit Fullscreen (F)\" : \"Fullscreen (F)\"\n                      }\n                    >\n                      <motion.button\n                        whileHover={{ scale: 1.1 }}\n                        whileTap={{ scale: 0.95 }}\n                        onClick={toggleFullscreen}\n                        className=\"flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-white/20\"\n                        aria-label=\"Fullscreen\"\n                      >\n                        {isFullscreen ? (\n                          <Minimize className=\"h-5 w-5 text-white\" />\n                        ) : (\n                          <Maximize className=\"h-5 w-5 text-white\" />\n                        )}\n                      </motion.button>\n                    </Tooltip>\n                  </div>\n                </div>\n              </motion.div>\n            )}\n          </AnimatePresence>\n        </div>\n      </div>\n    );\n  },\n);\nVideoPlayer.displayName = \"VideoPlayer\";\n",
      "type": "registry:ui",
      "target": ""
    }
  ],
  "type": "registry:ui"
}