@livepeer-frameworks/player-react 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/components/DvdLogo.tsx","../../src/assets/logomark.svg","../../src/components/IdleScreen.tsx","../../src/components/TitleOverlay.tsx","../../src/components/StatsPanel.tsx","../../src/hooks/usePlayerController.ts","../../src/context/PlayerContext.tsx","../../src/ui/slider.tsx","../../src/components/SeekBar.tsx","../../src/components/Icons.tsx","../../src/components/PlayerControls.tsx","../../src/components/DevModePanel.tsx","../../src/components/SpeedIndicator.tsx","../../src/components/SkipIndicator.tsx","../../src/ui/context-menu.tsx","../../src/components/Player.tsx","../../src/components/LoadingScreen.tsx","../../src/ui/button.tsx","../../src/components/StreamStateOverlay.tsx","../../src/components/PlayerErrorBoundary.tsx","../../src/ui/badge.tsx","../../src/hooks/useStreamState.ts","../../src/hooks/useViewerEndpoints.ts","../../src/components/ThumbnailOverlay.tsx","../../src/hooks/useMetaTrack.ts","../../src/hooks/usePlaybackQuality.ts","../../src/hooks/usePlayerSelection.ts","../../src/hooks/useTelemetry.ts"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { DvdLogoProps } from \"../types\";\n\ntype Point = { top: number; left: number };\ntype Velocity = { x: number; y: number };\ntype Size = { width: number; height: number };\n\nconst ORIGINAL_WIDTH = 153;\nconst ORIGINAL_HEIGHT = 69;\nconst ASPECT_RATIO = ORIGINAL_WIDTH / ORIGINAL_HEIGHT;\n\nconst COLORS = [\n \"#7aa2f7\",\n \"#bb9af7\",\n \"#9ece6a\",\n \"#73daca\",\n \"#7dcfff\",\n \"#f7768e\",\n \"#e0af68\",\n \"#2ac3de\",\n];\n\nconst pickNextColor = (current?: string): string => {\n if (COLORS.length === 0) {\n return current ?? \"#ffffff\";\n }\n\n if (COLORS.length === 1) {\n return COLORS[0];\n }\n\n let next: string;\n do {\n next = COLORS[Math.floor(Math.random() * COLORS.length)];\n } while (next === current);\n\n return next;\n};\n\nconst DvdLogo: React.FC<DvdLogoProps> = ({ parentRef, scale = 0.15 }) => {\n const [position, setPosition] = useState<Point>({ top: 0, left: 0 });\n const positionRef = useRef<Point>(position);\n useEffect(() => {\n positionRef.current = position;\n }, [position]);\n\n const [dimensions, setDimensions] = useState<Size>({\n width: ORIGINAL_WIDTH,\n height: ORIGINAL_HEIGHT,\n });\n const dimensionsRef = useRef<Size>(dimensions);\n useEffect(() => {\n dimensionsRef.current = dimensions;\n }, [dimensions]);\n\n const velocityRef = useRef<Velocity>({ x: 1.8, y: 1.6 });\n const [color, setColor] = useState<string>(pickNextColor());\n\n const recalculateDimensions = React.useCallback(() => {\n const parent = parentRef.current;\n if (!parent) {\n return;\n }\n\n const parentWidth = parent.clientWidth;\n const parentHeight = parent.clientHeight;\n if (parentWidth === 0 || parentHeight === 0) {\n return;\n }\n\n const maxWidth = parentWidth * scale;\n const maxHeight = parentHeight * scale;\n\n let width = maxWidth;\n let height = width / ASPECT_RATIO;\n\n if (height > maxHeight) {\n height = maxHeight;\n width = height * ASPECT_RATIO;\n }\n\n const nextDimensions: Size = {\n width: Math.max(20, width),\n height: Math.max(20, height),\n };\n\n dimensionsRef.current = nextDimensions;\n setDimensions(nextDimensions);\n\n const maxTop = Math.max(0, parentHeight - nextDimensions.height);\n const maxLeft = Math.max(0, parentWidth - nextDimensions.width);\n\n const startPosition: Point = {\n top: Math.random() * maxTop,\n left: Math.random() * maxLeft,\n };\n\n positionRef.current = startPosition;\n setPosition(startPosition);\n\n const baseSpeed = Math.max(1.2, Math.min(nextDimensions.width, nextDimensions.height) / 70);\n velocityRef.current = {\n x: baseSpeed * (Math.random() > 0.5 ? 1 : -1),\n y: baseSpeed * (Math.random() > 0.5 ? 1 : -1),\n };\n }, [parentRef, scale]);\n\n useEffect(() => {\n if (!parentRef.current) {\n return;\n }\n\n recalculateDimensions();\n\n if (typeof ResizeObserver !== \"undefined\") {\n const observer = new ResizeObserver(() => recalculateDimensions());\n observer.observe(parentRef.current);\n return () => observer.disconnect();\n }\n\n const onResize = () => recalculateDimensions();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, [parentRef, recalculateDimensions]);\n\n useEffect(() => {\n let animationFrame: number;\n let lastTimestamp = performance.now();\n\n const animate = (timestamp: number) => {\n const parent = parentRef.current;\n const dims = dimensionsRef.current;\n\n if (!parent || dims.width === 0 || dims.height === 0) {\n animationFrame = requestAnimationFrame(animate);\n return;\n }\n\n const deltaMs = timestamp - lastTimestamp;\n lastTimestamp = timestamp;\n const speedMultiplier = Math.min(deltaMs / 16, 2);\n\n const maxTop = parent.clientHeight - dims.height;\n const maxLeft = parent.clientWidth - dims.width;\n\n let { top, left } = positionRef.current;\n let { x, y } = velocityRef.current;\n let bounced = false;\n\n top += y * speedMultiplier;\n left += x * speedMultiplier;\n\n if (top <= 0 || top >= maxTop) {\n y = -y;\n top = Math.max(0, Math.min(maxTop, top));\n bounced = true;\n }\n\n if (left <= 0 || left >= maxLeft) {\n x = -x;\n left = Math.max(0, Math.min(maxLeft, left));\n bounced = true;\n }\n\n velocityRef.current = { x, y };\n const nextPosition = { top, left };\n positionRef.current = nextPosition;\n setPosition(nextPosition);\n\n if (bounced) {\n setColor((current) => pickNextColor(current));\n }\n\n animationFrame = requestAnimationFrame(animate);\n };\n\n animationFrame = requestAnimationFrame(animate);\n\n return () => cancelAnimationFrame(animationFrame);\n }, [parentRef]);\n\n return (\n <div\n className=\"fw-player-dvd\"\n style={{\n top: `${position.top}px`,\n left: `${position.left}px`,\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n }}\n >\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 153 69\" fill={color} className=\"select-none\">\n <g>\n <path d=\"M140.186,63.52h-1.695l-0.692,5.236h-0.847l0.77-5.236h-1.693l0.076-0.694h4.158L140.186,63.52L140.186,63.52z M146.346,68.756h-0.848v-4.545l0,0l-2.389,4.545l-1-4.545l0,0l-1.462,4.545h-0.771l1.924-5.931h0.695l0.924,4.006l2.078-4.006 h0.848V68.756L146.346,68.756z M126.027,0.063H95.352c0,0-8.129,9.592-9.654,11.434c-8.064,9.715-9.523,12.32-9.779,13.02 c0.063-0.699-0.256-3.304-3.686-13.148C71.282,8.7,68.359,0.062,68.359,0.062H57.881V0L32.35,0.063H13.169l-1.97,8.131 l14.543,0.062h3.365c9.336,0,15.055,3.747,13.467,10.354c-1.717,7.24-9.91,10.416-18.545,10.416h-3.24l4.191-17.783H10.502 L4.34,37.219h20.578c15.432,0,30.168-8.13,32.709-18.608c0.508-1.906,0.443-6.67-0.764-9.527c0-0.127-0.063-0.191-0.127-0.444 c-0.064-0.063-0.127-0.509,0.127-0.571c0.128-0.062,0.383,0.189,0.445,0.254c0.127,0.317,0.19,0.57,0.19,0.57l13.083,36.965 l33.344-37.6h14.1h3.365c9.337,0,15.055,3.747,13.528,10.354c-1.778,7.24-9.972,10.416-18.608,10.416h-3.238l4.191-17.783h-14.481 l-6.159,25.976h20.576c15.434,0,30.232-8.13,32.709-18.608C152.449,8.193,141.523,0.063,126.027,0.063L126.027,0.063z M71.091,45.981c-39.123,0-70.816,4.512-70.816,10.035c0,5.59,31.693,10.034,70.816,10.034c39.121,0,70.877-4.444,70.877-10.034 C141.968,50.493,110.212,45.981,71.091,45.981L71.091,45.981z M68.55,59.573c-8.956,0-16.196-1.523-16.196-3.365 c0-1.84,7.239-3.303,16.196-3.303c8.955,0,16.195,1.463,16.195,3.303C84.745,58.050,77.505,59.573,68.55,59.573L68.55,59.573z\" />\n </g>\n </svg>\n </div>\n );\n};\n\nexport default DvdLogo;\n","export default \"data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20standalone%3D%22no%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%2015806%2015806%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20xml%3Aspace%3D%22preserve%22%20xmlns%3Aserif%3D%22http%3A%2F%2Fwww.serif.com%2F%22%20style%3D%22fill-rule%3Aevenodd%3Bclip-rule%3Aevenodd%3Bstroke-linejoin%3Around%3Bstroke-miterlimit%3A2%3B%22%3E%20%20%20%20%3Cg%20transform%3D%22matrix%285.55556%2C0%2C0%2C5.55556%2C0%2C0%29%22%3E%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%288.31462%2C0%2C0%2C8.31462%2C8.22267e-14%2C-6.49389e-14%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M488.82%2C596.09C489.36%2C595.2%20489.89%2C594.31%20490.41%2C593.41C490.5%2C593.25%20490.59%2C593.09%20490.68%2C592.93C499.43%2C577.56%20504.8%2C560.03%20505.8%2C541.33C505.82%2C541.05%20505.83%2C540.77%20505.85%2C540.49C505.88%2C539.79%20505.91%2C539.09%20505.93%2C538.38C505.96%2C537.46%20505.97%2C536.54%20505.98%2C535.61C505.98%2C535.41%20505.99%2C535.2%20505.99%2C535L505.99%2C534.72C505.99%2C469.43%20453.06%2C416.51%20387.78%2C416.51C322.5%2C416.51%20269.57%2C469.44%20269.57%2C534.72C269.57%2C582.95%20298.45%2C624.43%20339.86%2C642.81C342.17%2C641.83%20344.82%2C641.6%20347.6%2C642.5C347.71%2C642.48%20348.06%2C642.58%20348.8%2C642.93C349.87%2C642.59%20351.08%2C642.46%20352.17%2C642.22C354.63%2C641.68%20357.12%2C641.33%20359.58%2C640.81C365.15%2C639.64%20370.59%2C637.89%20376.16%2C636.73C382.32%2C635.45%20388.69%2C638.46%20390.44%2C644.84C391.16%2C647.46%20390.81%2C650.38%20389.65%2C652.91C430.42%2C652.28%20466.17%2C631.01%20486.93%2C599.09C487.1%2C598.83%20487.27%2C598.57%20487.44%2C598.31C487.91%2C597.57%20488.37%2C596.83%20488.83%2C596.09L488.82%2C596.09Z%22%20style%3D%22fill%3Argb%2826%2C26%2C26%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M398.87%2C484.2L399.88%2C505.89L410.28%2C509.55L395.52%2C509.55L394.43%2C479.48L415.2%2C479.48L398.87%2C484.2Z%22%20style%3D%22fill%3Argb%2877%2C77%2C77%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M407.52%2C632.43L407.52%2C632.37L405.83%2C567.81L405.91%2C560.75L420.81%2C555.3L399.31%2C556L402.95%2C630.22C404.49%2C630.89%20406.02%2C631.62%20407.53%2C632.42L407.52%2C632.43Z%22%20style%3D%22fill%3Argb%2877%2C77%2C77%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M315.75%2C435.86L315.75%2C445.19C315.75%2C445.19%20343.09%2C444.1%20343.09%2C467.32L343.09%2C491.12L366.17%2C476.2L467.27%2C476.2C473.14%2C476.2%20478.98%2C477.27%20484.41%2C479.5C489.4%2C481.55%20494.15%2C484.61%20494.15%2C488.82L494.15%2C442.41L406.24%2C442.41L406.24%2C435.92L315.75%2C435.86Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M384.52%2C549.53C383%2C549.84%20374.5%2C554.81%20372.41%2C555.99C361.06%2C562.39%20350.66%2C570.29%20340.56%2C578.47L343.55%2C511.3C357.29%2C499.76%20372.89%2C489.71%20389.69%2C483.46L391.34%2C511.85L380.41%2C515.68L465.05%2C515.68L465.05%2C549.54L384.51%2C549.54L384.52%2C549.53Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M384.62%2C620.15C386.3%2C618.47%20388.78%2C617.44%20391.15%2C617.44C392.32%2C617.44%20393.42%2C617.66%20394.43%2C618.05L391.53%2C561.24C376.44%2C568.54%20361.62%2C576.78%20348.45%2C587.23C346.53%2C588.75%20339.44%2C594.3%20338.53%2C595.88C338.16%2C596.53%20338.08%2C596.77%20337.99%2C597.52C336.15%2C611.29%20341.68%2C626.24%20327.48%2C635.06C325.4%2C636.35%20322.28%2C637.18%20320.41%2C638.36C319.72%2C638.79%20319.26%2C638.87%20319.46%2C639.87L357.68%2C640.77L357.68%2C621.03C357.68%2C620.82%20358.79%2C618.46%20359.07%2C618.05C362%2C613.76%20368.64%2C613.05%20372.45%2C616.63C373.18%2C617.32%20375.15%2C620.84%20375.15%2C621.57L375.15%2C626.68C376.32%2C626.01%20377.56%2C625.46%20378.87%2C625.04C380.03%2C624.43%20381.23%2C623.94%20382.45%2C623.58C382.94%2C622.27%20383.71%2C621.04%20384.62%2C620.14L384.62%2C620.15Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%22336.59%22%20y%3D%22428.82%22%20width%3D%2255.13%22%20height%3D%228.66%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M370.43%2C405.41L381.28%2C405.41L381.28%2C428.82L347.02%2C428.82C347.02%2C415.9%20357.51%2C405.41%20370.43%2C405.41Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M375.15%2C621.59L375.15%2C646.4L399.31%2C643.32L393.82%2C606.12%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M434.95%2C641.77C427.45%2C636.79%20420.54%2C630.98%20414.13%2C624.68C378.86%2C650.1%20331.68%2C660.51%20289.92%2C645.24C276.7%2C656.38%20260.2%2C663.03%20243.21%2C666.13C245.28%2C668.42%20247.17%2C670.85%20249%2C673.36C259.11%2C673.75%20269.41%2C673.79%20279.47%2C672.94C316.6%2C669.77%20351.78%2C651.88%20389.38%2C653.26C420.31%2C654.4%20448.46%2C670.95%20479.26%2C673.24C493.74%2C674.31%20510.78%2C671.04%20524.28%2C665.72C524.6%2C665.6%20525.17%2C665.63%20525.1%2C665.2C493.55%2C667.12%20461.22%2C659.22%20434.94%2C641.78L434.95%2C641.77Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M431.64%2C681.28C431.71%2C681.82%20430.99%2C681.55%20430.67%2C681.5C428.7%2C681.19%20426.49%2C680.36%20424.48%2C679.92C400.81%2C674.72%20375.35%2C672.69%20351.2%2C675.65C341.11%2C676.89%20331.28%2C679.62%20321.24%2C681.22C300.45%2C684.53%20278.62%2C685.74%20257.83%2C682.01C273.85%2C682.14%20289.66%2C680.16%20305.21%2C676.54C319.99%2C673.09%20334.95%2C667.38%20350.01%2C665.52C377.55%2C662.11%20406.29%2C671.7%20431.64%2C681.28Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M376.31%2C636.41L367.67%2C639.94C342.05%2C648.2%20314.13%2C646.84%20288.76%2C638.37C280.1%2C644.46%20271.14%2C650.64%20260.82%2C653.56L267.06%2C649.22C276.19%2C642.22%20285.08%2C634.65%20291.47%2C624.98C294.79%2C626.43%20297.92%2C628.31%20301.23%2C629.78C323.76%2C639.82%20352.12%2C642.31%20376.31%2C636.41Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M496.44%2C679.79L493.62%2C680.99C455.11%2C696.09%20422.32%2C666.01%20385.12%2C661.7L374.61%2C660.13C397.05%2C658.33%20419.03%2C663.62%20440.24%2C670.18C445.86%2C671.92%20451.4%2C674.13%20457.03%2C675.77C469.67%2C679.46%20483.33%2C681.19%20496.45%2C679.8L496.44%2C679.79Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M502.72%2C658.04L499.89%2C658.33C480.42%2C655.87%20461.58%2C649.56%20444.59%2C639.91C442.86%2C638.93%20440.96%2C637.83%20439.42%2C636.58C447.9%2C638.94%20456.77%2C635.92%20464.33%2C632.12C472.21%2C646.13%20487.36%2C654.62%20502.73%2C658.03L502.72%2C658.04Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M440%2C690.82C440.07%2C691.36%20439.35%2C691.09%20439.03%2C691.04C435.69%2C690.51%20432.35%2C689.64%20429.02%2C689.11C398.16%2C684.21%20366.77%2C684.02%20335.64%2C686.06C335.32%2C686.08%20334.23%2C686.27%20334.29%2C685.75C369.06%2C676.79%20406.04%2C680.41%20440%2C690.82Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M313.56%2C572.87L313.69%2C572.14L313.94%2C572.49L313.56%2C572.87Z%22%20style%3D%22fill%3Argb%282%2C38%2C43%29%3Bfill-opacity%3A0.6%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M539.06%2C620.51C542.62%2C613.83%20545.72%2C606.95%20548.35%2C599.91C560.45%2C567.54%20562.63%2C531.85%20554.01%2C497.83C553.56%2C496.03%20551.73%2C494.94%20549.93%2C495.4C548.14%2C495.85%20547.05%2C497.68%20547.5%2C499.47C555.79%2C532.17%20553.69%2C566.46%20542.08%2C597.56C539.98%2C603.18%20537.56%2C608.71%20534.84%2C614.1C532.63%2C618.48%20530.21%2C622.77%20527.59%2C626.96C527.3%2C627.44%20527%2C627.91%20526.69%2C628.38C525.42%2C630.39%20524.1%2C632.37%20522.71%2C634.32C522.05%2C635.28%20521.36%2C636.24%20520.66%2C637.19C519.76%2C638.42%20518.84%2C639.63%20517.89%2C640.84C512.56%2C647.71%20506.62%2C654.2%20500.09%2C660.26C498.25%2C661.96%20496.36%2C663.64%20494.43%2C665.27C490.48%2C668.61%20486.33%2C671.8%20482%2C674.81C478.57%2C677.19%20474.88%2C679.59%20471.13%2C681.77C467.82%2C683.69%20464.47%2C685.45%20461.2%2C686.92C461.06%2C686.99%20460.92%2C687.06%20460.79%2C687.14L460.76%2C687.16L460.74%2C687.16L460.58%2C687.29L460.43%2C687.41L460.37%2C687.45L460.3%2C687.51L460.11%2C687.7L460.07%2C687.75L460.05%2C687.77L460.03%2C687.8L460%2C687.83C459.77%2C688.11%20459.57%2C688.43%20459.44%2C688.79C459.3%2C689.15%20459.23%2C689.53%20459.22%2C689.9L459.22%2C690.26L459.25%2C690.42L459.29%2C690.67L459.35%2C690.9C459.39%2C691.06%20459.45%2C691.21%20459.51%2C691.36C459.58%2C691.5%20459.65%2C691.64%20459.73%2C691.77L459.75%2C691.79L459.77%2C691.82L459.88%2C691.98L460%2C692.13L460.04%2C692.19L460.34%2C692.49L460.36%2C692.49L460.42%2C692.56C460.7%2C692.79%20461.02%2C692.98%20461.38%2C693.12L483.09%2C701.39L504.75%2C709.65C504.94%2C709.72%20505.13%2C709.78%20505.34%2C709.82C506.31%2C710.21%20507.44%2C710.1%20508.32%2C709.48C508.49%2C709.37%20508.64%2C709.23%20508.79%2C709.08L556.35%2C659.8C557.38%2C658.73%20557.5%2C657.12%20556.75%2C655.92L539.06%2C620.51Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M427.7%2C697.67C395%2C705.96%20360.71%2C703.86%20329.62%2C692.24C313.96%2C686.39%20299.11%2C678.13%20285.67%2C667.54C283.67%2C665.98%20281.69%2C664.35%20279.75%2C662.67C272.21%2C656.14%20265.17%2C648.83%20258.77%2C640.77C257.46%2C639.14%20256.18%2C637.46%20254.94%2C635.76C254.57%2C635.27%20254.21%2C634.78%20253.85%2C634.28C253.35%2C633.58%20252.85%2C632.88%20252.36%2C632.17C249.98%2C628.73%20247.59%2C625.05%20245.4%2C621.29C243.51%2C618.05%20241.78%2C614.76%20240.33%2C611.54C240.3%2C611.48%20240.28%2C611.43%20240.25%2C611.37C240.25%2C611.35%20240.23%2C611.32%20240.22%2C611.3C240.16%2C611.18%20240.1%2C611.07%20240.03%2C610.96L240.01%2C610.93L240.01%2C610.9L239.89%2C610.74L239.77%2C610.6L239.72%2C610.54L239.66%2C610.47L239.56%2C610.36L239.47%2C610.28L239.43%2C610.24L239.4%2C610.22L239.38%2C610.19L239.34%2C610.17C239.29%2C610.13%20239.24%2C610.09%20239.19%2C610.05C238.95%2C609.87%20238.68%2C609.72%20238.39%2C609.61C238.02%2C609.47%20237.65%2C609.4%20237.28%2C609.39L236.91%2C609.39L236.75%2C609.42L236.51%2C609.46L236.27%2C609.52C236.12%2C609.56%20235.97%2C609.62%20235.81%2C609.68C235.67%2C609.75%20235.54%2C609.82%20235.41%2C609.9L235.35%2C609.94L235.19%2C610.05L234.99%2C610.21L234.92%2C610.27L234.73%2C610.46L234.69%2C610.51L234.61%2C610.59C234.38%2C610.87%20234.19%2C611.19%20234.05%2C611.55L225.78%2C633.25L217.53%2C654.92C217.45%2C655.11%20217.39%2C655.3%20217.35%2C655.51C216.96%2C656.48%20217.08%2C657.61%20217.69%2C658.49C217.8%2C658.66%20217.94%2C658.81%20218.09%2C658.96L267.38%2C706.52C268.44%2C707.55%20270.05%2C707.67%20271.25%2C706.92L306.67%2C689.23C313.34%2C692.79%20320.22%2C695.89%20327.26%2C698.52C359.63%2C710.62%20395.32%2C712.8%20429.34%2C704.18C431.14%2C703.72%20432.23%2C701.9%20431.78%2C700.1C431.32%2C698.31%20429.5%2C697.22%20427.7%2C697.67Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M222.39%2C582.08C222.84%2C583.87%20224.67%2C584.96%20226.46%2C584.51C228.26%2C584.05%20229.35%2C582.23%20228.89%2C580.43C220.61%2C547.74%20222.7%2C513.44%20234.32%2C482.35C240.43%2C466.01%20249.16%2C450.55%20260.42%2C436.66C266.85%2C428.7%20274.11%2C421.26%20282.17%2C414.47C286.06%2C411.19%20290.14%2C408.06%20294.4%2C405.1C297.83%2C402.71%20301.52%2C400.32%20305.27%2C398.13C308.57%2C396.21%20311.92%2C394.45%20315.2%2C392.98C315.34%2C392.92%20315.48%2C392.84%20315.61%2C392.76L315.63%2C392.74L315.66%2C392.74L315.82%2C392.62L315.97%2C392.5L316.03%2C392.45L316.09%2C392.39L316.2%2C392.29L316.28%2C392.2L316.33%2C392.16L316.35%2C392.13L316.37%2C392.11L316.4%2C392.07C316.63%2C391.79%20316.82%2C391.48%20316.96%2C391.12C317.1%2C390.75%20317.17%2C390.38%20317.18%2C390.01L317.18%2C389.78L317.17%2C389.64L317.15%2C389.48L317.11%2C389.24L317.05%2C389C317.01%2C388.85%20316.95%2C388.7%20316.88%2C388.55C316.82%2C388.4%20316.74%2C388.27%20316.66%2C388.14L316.64%2C388.11L316.64%2C388.08L316.52%2C387.92L316.4%2C387.77L316.35%2C387.72L316.29%2C387.65L316.06%2C387.42L316.03%2C387.4L316.01%2C387.37L315.97%2C387.35C315.69%2C387.11%20315.37%2C386.92%20315.02%2C386.79L293.31%2C378.51L271.65%2C370.26C271.46%2C370.18%20271.26%2C370.12%20271.06%2C370.08C270.08%2C369.7%20268.96%2C369.81%20268.08%2C370.42C267.91%2C370.54%20267.75%2C370.67%20267.61%2C370.82L220.05%2C420.11C219.02%2C421.18%20218.89%2C422.78%20219.65%2C423.98L237.33%2C459.4C233.77%2C466.07%20230.67%2C472.95%20228.04%2C480C215.95%2C512.36%20213.77%2C548.05%20222.39%2C582.08Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M519.68%2C441.65C520.78%2C443.12%20521.85%2C444.61%20522.91%2C446.13C525.3%2C449.56%20527.69%2C453.25%20529.88%2C457C531.8%2C460.3%20533.56%2C463.65%20535.03%2C466.93C535.09%2C467.07%20535.17%2C467.21%20535.25%2C467.34L535.27%2C467.36L535.27%2C467.39L535.39%2C467.55L535.51%2C467.7L535.56%2C467.76L535.62%2C467.82L535.72%2C467.93L535.81%2C468.01L535.85%2C468.05L535.88%2C468.07L535.9%2C468.1L535.94%2C468.13C536.22%2C468.36%20536.54%2C468.55%20536.89%2C468.69C537.26%2C468.83%20537.63%2C468.89%20538%2C468.9L538.37%2C468.9L538.53%2C468.88L538.77%2C468.84L539.01%2C468.78C539.16%2C468.73%20539.31%2C468.68%20539.46%2C468.61C539.61%2C468.54%20539.74%2C468.47%20539.87%2C468.39L539.9%2C468.37L539.93%2C468.37L540.09%2C468.25L540.24%2C468.13L540.29%2C468.08L540.36%2C468.02L540.59%2C467.79L540.61%2C467.76L540.64%2C467.74L540.66%2C467.7C540.9%2C467.42%20541.09%2C467.1%20541.22%2C466.74L549.5%2C445.04L557.75%2C423.38C557.83%2C423.19%20557.89%2C422.99%20557.93%2C422.79C558.32%2C421.81%20558.2%2C420.69%20557.59%2C419.81C557.47%2C419.64%20557.34%2C419.48%20557.19%2C419.33L507.9%2C371.78C506.84%2C370.75%20505.23%2C370.62%20504.03%2C371.38L468.61%2C389.06C461.94%2C385.5%20455.06%2C382.4%20448.01%2C379.77C415.65%2C367.68%20379.96%2C365.5%20345.93%2C374.12C344.14%2C374.57%20343.05%2C376.4%20343.5%2C378.19C343.96%2C379.98%20345.78%2C381.08%20347.58%2C380.62C380.27%2C372.34%20414.57%2C374.43%20445.66%2C386.05C461.19%2C391.85%20475.94%2C400.04%20489.29%2C410.5C500.52%2C419.29%20510.77%2C429.7%20519.68%2C441.65Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%3C%2Fg%3E%3C%2Fsvg%3E\"","import React, { useRef, useEffect, useState } from \"react\";\nimport DvdLogo from \"./DvdLogo\";\nimport logomarkAsset from \"../assets/logomark.svg\";\nimport type { StreamStatus } from \"../types\";\n\n// ============================================================================\n// AnimatedBubble Component\n// ============================================================================\n\ninterface AnimatedBubbleProps {\n index: number;\n}\n\nconst AnimatedBubble: React.FC<AnimatedBubbleProps> = ({ index }) => {\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const [size, setSize] = useState(40);\n const [opacity, setOpacity] = useState(0);\n\n const getRandomPosition = () => ({\n top: Math.random() * 80 + 10,\n left: Math.random() * 80 + 10,\n });\n\n const getRandomSize = () => Math.random() * 60 + 30;\n\n useEffect(() => {\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n\n const animationCycle = () => {\n setOpacity(0.15);\n setTimeout(() => {\n setOpacity(0);\n setTimeout(() => {\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n setTimeout(() => {\n animationCycle();\n }, 200);\n }, 1500);\n }, 4000 + Math.random() * 3000);\n };\n\n const timeout = setTimeout(animationCycle, index * 500);\n return () => clearTimeout(timeout);\n }, [index]);\n\n const bubbleColors = [\n \"rgba(122, 162, 247, 0.2)\",\n \"rgba(187, 154, 247, 0.2)\",\n \"rgba(158, 206, 106, 0.2)\",\n \"rgba(115, 218, 202, 0.2)\",\n \"rgba(125, 207, 255, 0.2)\",\n \"rgba(247, 118, 142, 0.2)\",\n \"rgba(224, 175, 104, 0.2)\",\n \"rgba(42, 195, 222, 0.2)\",\n ];\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: `${position.top}%`,\n left: `${position.left}%`,\n width: `${size}px`,\n height: `${size}px`,\n borderRadius: \"50%\",\n background: bubbleColors[index % bubbleColors.length],\n opacity,\n transition: \"opacity 1s ease-in-out\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n } as React.CSSProperties}\n />\n );\n};\n\n// ============================================================================\n// CenterLogo Component\n// ============================================================================\n\ninterface CenterLogoProps {\n containerRef: React.RefObject<HTMLDivElement>;\n scale?: number;\n onHitmarker?: (e: { clientX: number; clientY: number }) => void;\n}\n\nconst CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHitmarker }) => {\n const [logoSize, setLogoSize] = useState(100);\n const [offset, setOffset] = useState({ x: 0, y: 0 });\n const [isHovered, setIsHovered] = useState(false);\n\n useEffect(() => {\n if (containerRef.current) {\n const containerWidth = containerRef.current.clientWidth;\n const containerHeight = containerRef.current.clientHeight;\n const minDimension = Math.min(containerWidth, containerHeight);\n setLogoSize(minDimension * scale);\n }\n }, [containerRef, scale]);\n\n const handleLogoClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onHitmarker) {\n onHitmarker({ clientX: e.clientX, clientY: e.clientY });\n }\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const deltaX = e.clientX - centerX;\n const deltaY = e.clientY - centerY;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n const maxDistance = logoSize * 1.5;\n if (distance < maxDistance && distance > 0) {\n const pushStrength = (maxDistance - distance) / maxDistance;\n const pushDistance = 50 * pushStrength;\n const pushX = -(deltaX / distance) * pushDistance;\n const pushY = -(deltaY / distance) * pushDistance;\n setOffset({ x: pushX, y: pushY });\n setIsHovered(true);\n } else {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n }\n };\n\n const handleMouseLeave = () => {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n };\n\n useEffect(() => {\n if (containerRef.current) {\n const container = containerRef.current;\n container.addEventListener('mousemove', handleMouseMove);\n container.addEventListener('mouseleave', handleMouseLeave);\n return () => {\n container.removeEventListener('mousemove', handleMouseMove);\n container.removeEventListener('mouseleave', handleMouseLeave);\n };\n }\n }, [logoSize, containerRef]);\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: `translate(-50%, -50%) translate(${offset.x}px, ${offset.y}px)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10,\n transition: \"transform 0.3s ease-out\",\n userSelect: \"none\",\n }}\n >\n <div\n style={{\n position: \"absolute\",\n width: `${logoSize * 1.4}px`,\n height: `${logoSize * 1.4}px`,\n borderRadius: \"50%\",\n background: \"rgba(122, 162, 247, 0.15)\",\n animation: isHovered ? \"logoPulse 1s ease-in-out infinite\" : \"logoPulse 3s ease-in-out infinite\",\n transform: isHovered ? \"scale(1.2)\" : \"scale(1)\",\n transition: \"transform 0.3s ease-out\",\n pointerEvents: \"none\",\n }}\n />\n <img\n src={logomarkAsset}\n alt=\"FrameWorks Logo\"\n onClick={handleLogoClick}\n style={{\n width: `${logoSize}px`,\n height: `${logoSize}px`,\n position: \"relative\",\n zIndex: 1,\n filter: isHovered\n ? \"drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1)\"\n : \"drop-shadow(0 4px 8px rgba(36, 40, 59, 0.3))\",\n transform: isHovered ? \"scale(1.1)\" : \"scale(1)\",\n transition: \"all 0.3s ease-out\",\n cursor: isHovered ? \"pointer\" : \"default\",\n userSelect: \"none\",\n WebkitUserDrag: \"none\",\n } as React.CSSProperties}\n />\n </div>\n );\n};\n\n// ============================================================================\n// Status Overlay Component (shows on top of the fancy background)\n// ============================================================================\n\ninterface StatusOverlayProps {\n status?: StreamStatus;\n message: string;\n percentage?: number;\n error?: string;\n onRetry?: () => void;\n}\n\nfunction getStatusLabel(status?: StreamStatus): string {\n switch (status) {\n case 'ONLINE': return 'ONLINE';\n case 'OFFLINE': return 'OFFLINE';\n case 'INITIALIZING': return 'STARTING';\n case 'BOOTING': return 'STARTING';\n case 'WAITING_FOR_DATA': return 'WAITING';\n case 'SHUTTING_DOWN': return 'ENDING';\n case 'ERROR': return 'ERROR';\n case 'INVALID': return 'ERROR';\n default: return 'CONNECTING';\n }\n}\n\nfunction StatusIcon({ status }: { status?: StreamStatus }) {\n const iconClass = \"w-5 h-5\";\n\n // Spinner for loading states\n if (status === 'INITIALIZING' || status === 'BOOTING' || status === 'WAITING_FOR_DATA' || !status) {\n return (\n <svg className={`${iconClass} animate-spin`} fill=\"none\" viewBox=\"0 0 24 24\" style={{ color: 'hsl(var(--tn-yellow, 40 95% 64%))' }}>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n );\n }\n\n // Offline icon\n if (status === 'OFFLINE') {\n return (\n <svg className={iconClass} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" style={{ color: 'hsl(var(--tn-red, 348 100% 72%))' }}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414\" />\n </svg>\n );\n }\n\n // Error icon\n if (status === 'ERROR' || status === 'INVALID') {\n return (\n <svg className={iconClass} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" style={{ color: 'hsl(var(--tn-red, 348 100% 72%))' }}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n );\n }\n\n // Default spinner\n return (\n <svg className={`${iconClass} animate-spin`} fill=\"none\" viewBox=\"0 0 24 24\" style={{ color: 'hsl(var(--tn-cyan, 193 100% 75%))' }}>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n );\n}\n\nconst StatusOverlay: React.FC<StatusOverlayProps> = ({ status, message, percentage, error, onRetry }) => {\n const showRetry = (status === 'ERROR' || status === 'INVALID') && onRetry;\n const showProgress = status === 'INITIALIZING' && percentage !== undefined;\n const displayMessage = error || message;\n\n return (\n <div\n style={{\n position: \"absolute\",\n bottom: \"16px\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 20,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"8px\",\n maxWidth: \"280px\",\n textAlign: \"center\",\n }}\n >\n {/* Subtle status indicator - just icon + message */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n color: \"#787c99\",\n fontSize: \"13px\",\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n }}\n >\n <StatusIcon status={status} />\n <span>{displayMessage}</span>\n </div>\n\n {/* Progress bar */}\n {showProgress && (\n <div\n style={{\n width: \"160px\",\n height: \"4px\",\n background: \"rgba(65, 72, 104, 0.4)\",\n borderRadius: \"2px\",\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n width: `${Math.min(100, percentage)}%`,\n height: \"100%\",\n background: \"hsl(var(--tn-cyan, 193 100% 75%))\",\n transition: \"width 0.3s ease-out\",\n }}\n />\n </div>\n )}\n\n {/* Retry button - only for errors */}\n {showRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n style={{\n padding: \"6px 16px\",\n background: \"transparent\",\n border: \"1px solid rgba(122, 162, 247, 0.4)\",\n borderRadius: \"4px\",\n color: \"#7aa2f7\",\n fontSize: \"11px\",\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(122, 162, 247, 0.1)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n }}\n >\n Retry\n </button>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// Hitmarker System\n// ============================================================================\n\ninterface Hitmarker {\n id: number;\n x: number;\n y: number;\n}\n\nconst playHitmarkerSound = () => {\n try {\n // Embedded hitmarker sound as base64 data URL\n const hitmarkerDataUrl = 'data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA' +\n 'AAD/+1QAAAAAAAAAAAAAAAAAAAAA' +\n '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' +\n 'qqqqqqqqqqqqqqqqqqqqqqqqqqo=';\n\n const audio = new Audio(hitmarkerDataUrl);\n audio.volume = 0.3;\n audio.play().catch(() => createSyntheticHitmarkerSound());\n } catch {\n createSyntheticHitmarkerSound();\n }\n};\n\nconst createSyntheticHitmarkerSound = () => {\n try {\n const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\n const oscillator1 = audioContext.createOscillator();\n const oscillator2 = audioContext.createOscillator();\n const gainNode1 = audioContext.createGain();\n const gainNode2 = audioContext.createGain();\n const masterGain = audioContext.createGain();\n\n oscillator1.connect(gainNode1);\n oscillator2.connect(gainNode2);\n gainNode1.connect(masterGain);\n gainNode2.connect(masterGain);\n masterGain.connect(audioContext.destination);\n\n oscillator1.frequency.setValueAtTime(1800, audioContext.currentTime);\n oscillator1.frequency.exponentialRampToValueAtTime(900, audioContext.currentTime + 0.08);\n oscillator2.frequency.setValueAtTime(3600, audioContext.currentTime);\n oscillator2.frequency.exponentialRampToValueAtTime(1800, audioContext.currentTime + 0.04);\n\n oscillator1.type = 'triangle';\n oscillator2.type = 'sine';\n\n gainNode1.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode1.gain.linearRampToValueAtTime(0.4, audioContext.currentTime + 0.002);\n gainNode1.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.12);\n\n gainNode2.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode2.gain.linearRampToValueAtTime(0.3, audioContext.currentTime + 0.001);\n gainNode2.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.06);\n\n masterGain.gain.setValueAtTime(0.5, audioContext.currentTime);\n\n const startTime = audioContext.currentTime;\n const stopTime = startTime + 0.15;\n\n oscillator1.start(startTime);\n oscillator2.start(startTime);\n oscillator1.stop(stopTime);\n oscillator2.stop(stopTime);\n } catch {\n // Audio context not available\n }\n};\n\n// ============================================================================\n// IdleScreen Component (Main Export)\n// ============================================================================\n\nexport interface IdleScreenProps {\n /** Stream status (OFFLINE, INITIALIZING, ERROR, etc.) */\n status?: StreamStatus;\n /** Human-readable message */\n message?: string;\n /** Processing percentage (for INITIALIZING) */\n percentage?: number;\n /** Error message */\n error?: string;\n /** Callback for retry button */\n onRetry?: () => void;\n}\n\nexport const IdleScreen: React.FC<IdleScreenProps> = ({\n status,\n message = \"Waiting for stream...\",\n percentage,\n error,\n onRetry,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [hitmarkers, setHitmarkers] = useState<Hitmarker[]>([]);\n\n const createHitmarker = (e: { clientX: number; clientY: number }) => {\n if (!containerRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n const newHitmarker: Hitmarker = {\n id: Date.now() + Math.random(),\n x,\n y,\n };\n\n setHitmarkers(prev => [...prev, newHitmarker]);\n playHitmarkerSound();\n\n setTimeout(() => {\n setHitmarkers(prev => prev.filter(h => h.id !== newHitmarker.id));\n }, 600);\n };\n\n // Inject CSS animations\n useEffect(() => {\n const styleId = 'idle-screen-animations';\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes fadeInOut {\n 0%, 100% { opacity: 0.6; }\n 50% { opacity: 0.9; }\n }\n @keyframes logoPulse {\n 0%, 100% { opacity: 0.15; transform: scale(1); }\n 50% { opacity: 0.25; transform: scale(1.05); }\n }\n @keyframes floatUp {\n 0% { transform: translateY(100vh) rotate(0deg); opacity: 0; }\n 10% { opacity: 0.6; }\n 90% { opacity: 0.6; }\n 100% { transform: translateY(-100px) rotate(360deg); opacity: 0; }\n }\n @keyframes gradientShift {\n 0%, 100% { background-position: 0% 50%; }\n 50% { background-position: 100% 50%; }\n }\n @keyframes hitmarkerFade45 {\n 0% { opacity: 1; transform: translate(-50%, -50%) rotate(45deg) scale(0.5); }\n 20% { opacity: 1; transform: translate(-50%, -50%) rotate(45deg) scale(1.2); }\n 100% { opacity: 0; transform: translate(-50%, -50%) rotate(45deg) scale(1); }\n }\n @keyframes hitmarkerFadeNeg45 {\n 0% { opacity: 1; transform: translate(-50%, -50%) rotate(-45deg) scale(0.5); }\n 20% { opacity: 1; transform: translate(-50%, -50%) rotate(-45deg) scale(1.2); }\n 100% { opacity: 0; transform: translate(-50%, -50%) rotate(-45deg) scale(1); }\n }\n `;\n document.head.appendChild(style);\n }\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"fw-player-root\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 5,\n background: `\n linear-gradient(135deg,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,\n hsl(var(--tn-bg, 233 23% 17%)) 25%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,\n hsl(var(--tn-bg, 233 23% 17%)) 75%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 100%\n )\n `,\n backgroundSize: \"400% 400%\",\n animation: \"gradientShift 16s ease-in-out infinite\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderRadius: \"0\",\n userSelect: \"none\",\n } as React.CSSProperties}\n >\n {/* Hitmarkers */}\n {hitmarkers.map(hitmarker => (\n <div\n key={hitmarker.id}\n style={{\n position: \"absolute\",\n left: `${hitmarker.x}px`,\n top: `${hitmarker.y}px`,\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\",\n zIndex: 100,\n width: \"40px\",\n height: \"40px\",\n }}\n >\n <div style={{ position: \"absolute\", top: \"25%\", left: \"25%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(45deg)\", animation: \"hitmarkerFade45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n <div style={{ position: \"absolute\", top: \"25%\", left: \"75%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(-45deg)\", animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n <div style={{ position: \"absolute\", top: \"75%\", left: \"25%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(-45deg)\", animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n <div style={{ position: \"absolute\", top: \"75%\", left: \"75%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(45deg)\", animation: \"hitmarkerFade45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n </div>\n ))}\n\n {/* Floating particles */}\n {[...Array(12)].map((_, index) => (\n <div\n key={`particle-${index}`}\n style={{\n position: \"absolute\",\n left: `${Math.random() * 100}%`,\n width: `${Math.random() * 4 + 2}px`,\n height: `${Math.random() * 4 + 2}px`,\n borderRadius: \"50%\",\n background: [\"#7aa2f7\", \"#bb9af7\", \"#9ece6a\", \"#73daca\", \"#7dcfff\", \"#f7768e\", \"#e0af68\", \"#2ac3de\"][index % 8],\n opacity: 0,\n animation: `floatUp ${8 + Math.random() * 4}s linear infinite`,\n animationDelay: `${Math.random() * 8}s`,\n pointerEvents: \"none\",\n }}\n />\n ))}\n\n {/* Animated bubbles */}\n {[...Array(8)].map((_, index) => (\n <AnimatedBubble key={index} index={index} />\n ))}\n\n {/* Center logo */}\n <CenterLogo containerRef={containerRef as React.RefObject<HTMLDivElement>} onHitmarker={createHitmarker} />\n\n {/* DVD Logo */}\n <DvdLogo parentRef={containerRef as React.RefObject<HTMLDivElement>} scale={0.08} />\n\n {/* Status overlay */}\n <StatusOverlay\n status={status}\n message={message}\n percentage={percentage}\n error={error}\n onRetry={onRetry}\n />\n\n {/* Overlay texture */}\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: `\n radial-gradient(circle at 20% 80%, rgba(122, 162, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(187, 154, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(158, 206, 106, 0.02) 0%, transparent 50%)\n `,\n pointerEvents: \"none\",\n }}\n />\n </div>\n );\n};\n\nexport default IdleScreen;\n","import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface TitleOverlayProps {\n title?: string | null;\n description?: string | null;\n isVisible: boolean;\n className?: string;\n}\n\n/**\n * Title/description overlay that appears at the top of the player.\n * Visible on hover or when paused - controlled by parent via isVisible prop.\n */\nconst TitleOverlay: React.FC<TitleOverlayProps> = ({\n title,\n description,\n isVisible,\n className,\n}) => {\n // Don't render if no content\n if (!title && !description) return null;\n\n return (\n <div\n className={cn(\n \"fw-title-overlay absolute inset-x-0 top-0 z-20 pointer-events-none\",\n \"bg-gradient-to-b from-black/70 via-black/40 to-transparent\",\n \"px-4 py-3 transition-opacity duration-300\",\n isVisible ? \"opacity-100\" : \"opacity-0\",\n className\n )}\n >\n {title && (\n <h2 className=\"text-white text-sm font-medium truncate max-w-[80%]\">\n {title}\n </h2>\n )}\n {description && (\n <p className=\"text-white/70 text-xs mt-0.5 line-clamp-2 max-w-[70%]\">\n {description}\n </p>\n )}\n </div>\n );\n};\n\nexport default TitleOverlay;\n","import React from \"react\";\nimport { cn, type ContentMetadata, type PlaybackQuality } from \"@livepeer-frameworks/player-core\";\n\ninterface StreamStateInfo {\n status?: string;\n viewers?: number;\n tracks?: Array<{\n type: string;\n codec: string;\n width?: number;\n height?: number;\n bps?: number;\n channels?: number;\n }>;\n}\n\ninterface StatsPanelProps {\n isOpen: boolean;\n onClose: () => void;\n metadata?: ContentMetadata | null;\n streamState?: StreamStateInfo | null;\n quality?: PlaybackQuality | null;\n videoElement?: HTMLVideoElement | null;\n protocol?: string;\n nodeId?: string;\n geoDistance?: number;\n}\n\n/**\n * \"Stats for nerds\" panel showing detailed playback information.\n * Toggleable overlay with technical details about the stream.\n */\nconst StatsPanel: React.FC<StatsPanelProps> = ({\n isOpen,\n onClose,\n metadata,\n streamState,\n quality,\n videoElement,\n protocol,\n nodeId,\n geoDistance,\n}) => {\n if (!isOpen) return null;\n\n // Video element stats\n const video = videoElement;\n const currentRes = video ? `${video.videoWidth}x${video.videoHeight}` : \"—\";\n const buffered = video && video.buffered.length > 0\n ? (video.buffered.end(video.buffered.length - 1) - video.currentTime).toFixed(1)\n : \"—\";\n const playbackRate = video?.playbackRate?.toFixed(2) ?? \"1.00\";\n\n // Quality monitor stats\n const qualityScore = quality?.score?.toFixed(0) ?? \"—\";\n const bitrateKbps = quality?.bitrate\n ? `${(quality.bitrate / 1000).toFixed(0)} kbps`\n : \"—\";\n const frameDropRate = quality?.frameDropRate?.toFixed(1) ?? \"—\";\n const stallCount = quality?.stallCount ?? 0;\n const latency = quality?.latency ? `${Math.round(quality.latency)} ms` : \"—\";\n\n // Stream state stats\n const viewers = streamState?.viewers ?? metadata?.viewers ?? \"—\";\n const streamStatus = streamState?.status ?? metadata?.status ?? \"—\";\n\n // Format track info from metadata\n const formatTracks = () => {\n if (!streamState?.tracks?.length) return \"—\";\n return streamState.tracks.map(t => {\n if (t.type === \"video\") {\n return `${t.codec} ${t.width}x${t.height}@${t.bps ? Math.round(t.bps / 1000) + \"kbps\" : \"?\"}`;\n }\n return `${t.codec} ${t.channels}ch`;\n }).join(\", \");\n };\n\n const stats = [\n { label: \"Resolution\", value: currentRes },\n { label: \"Buffer\", value: `${buffered}s` },\n { label: \"Latency\", value: latency },\n { label: \"Bitrate\", value: bitrateKbps },\n { label: \"Quality Score\", value: `${qualityScore}/100` },\n { label: \"Frame Drop Rate\", value: `${frameDropRate}%` },\n { label: \"Stalls\", value: String(stallCount) },\n { label: \"Playback Rate\", value: `${playbackRate}x` },\n { label: \"Protocol\", value: protocol ?? \"—\" },\n { label: \"Node\", value: nodeId ?? \"—\" },\n { label: \"Geo Distance\", value: geoDistance ? `${geoDistance.toFixed(0)} km` : \"—\" },\n { label: \"Viewers\", value: String(viewers) },\n { label: \"Status\", value: streamStatus },\n { label: \"Tracks\", value: formatTracks() },\n ];\n\n // Add metadata fields if available\n if (metadata?.title) {\n stats.unshift({ label: \"Title\", value: metadata.title });\n }\n if (metadata?.durationSeconds) {\n const mins = Math.floor(metadata.durationSeconds / 60);\n const secs = metadata.durationSeconds % 60;\n stats.push({ label: \"Duration\", value: `${mins}:${String(secs).padStart(2, \"0\")}` });\n }\n if (metadata?.recordingSizeBytes) {\n const mb = (metadata.recordingSizeBytes / (1024 * 1024)).toFixed(1);\n stats.push({ label: \"Size\", value: `${mb} MB` });\n }\n\n return (\n <div\n className={cn(\n \"fw-stats-panel absolute top-2 right-2 z-30\",\n \"bg-black border border-white/10 rounded\",\n \"text-white text-xs font-mono\",\n \"max-w-[320px] max-h-[80%] overflow-auto\",\n \"shadow-lg\"\n )}\n style={{ backgroundColor: '#000000' }} // Inline fallback for opaque background\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-white/10\">\n <span className=\"text-white/70 text-[10px] uppercase tracking-wider\">\n Stats Overlay\n </span>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"text-white/50 hover:text-white transition-colors p-1 -mr-1\"\n aria-label=\"Close stats panel\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M2 2l8 8M10 2l-8 8\" />\n </svg>\n </button>\n </div>\n\n {/* Stats grid */}\n <div className=\"px-3 py-2 space-y-1\">\n {stats.map(({ label, value }) => (\n <div key={label} className=\"flex justify-between gap-4\">\n <span className=\"text-white/50 shrink-0\">{label}</span>\n <span className=\"text-white/90 truncate text-right\">{value}</span>\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default StatsPanel;\n","/**\n * usePlayerController.ts\n *\n * React hook that wraps PlayerController for declarative usage.\n * Manages the complete player lifecycle and provides reactive state.\n */\n\nimport { useState, useEffect, useRef, useCallback, useMemo } from 'react';\nimport {\n PlayerController,\n type PlayerControllerConfig,\n type PlayerControllerEvents,\n type PlayerState,\n type StreamState,\n type StreamSource,\n type StreamInfo,\n type PlaybackQuality,\n type ContentEndpoints,\n type ContentMetadata,\n type MistStreamInfo,\n} from '@livepeer-frameworks/player-core';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UsePlayerControllerConfig extends Omit<PlayerControllerConfig, 'playerManager'> {\n /** Enable/disable the hook */\n enabled?: boolean;\n /** Callback when state changes */\n onStateChange?: (state: PlayerState) => void;\n /** Callback when stream state changes */\n onStreamStateChange?: (state: StreamState) => void;\n /** Callback when error occurs */\n onError?: (error: string) => void;\n /** Callback when ready */\n onReady?: (videoElement: HTMLVideoElement) => void;\n}\n\nexport interface PlayerControllerState {\n /** Current player state */\n state: PlayerState;\n /** Stream state (for live streams) */\n streamState: StreamState | null;\n /** Resolved endpoints */\n endpoints: ContentEndpoints | null;\n /** Content metadata */\n metadata: ContentMetadata | null;\n /** Video element (null if not ready) */\n videoElement: HTMLVideoElement | null;\n /** Current time */\n currentTime: number;\n /** Duration */\n duration: number;\n /** Is playing */\n isPlaying: boolean;\n /** Is paused */\n isPaused: boolean;\n /** Is buffering */\n isBuffering: boolean;\n /** Is muted */\n isMuted: boolean;\n /** Volume (0-1) */\n volume: number;\n /** Error text */\n error: string | null;\n /** Is passive error */\n isPassiveError: boolean;\n /** Has playback ever started */\n hasPlaybackStarted: boolean;\n /** Is holding speed (2x gesture) */\n isHoldingSpeed: boolean;\n /** Current hold speed */\n holdSpeed: number;\n /** Is hovering (controls visible) */\n isHovering: boolean;\n /** Should show controls */\n shouldShowControls: boolean;\n /** Is loop enabled */\n isLoopEnabled: boolean;\n /** Is fullscreen */\n isFullscreen: boolean;\n /** Is PiP active */\n isPiPActive: boolean;\n /** Is effectively live (live or DVR recording) */\n isEffectivelyLive: boolean;\n /** Should show idle screen */\n shouldShowIdleScreen: boolean;\n /** Current player info */\n currentPlayerInfo: { name: string; shortname: string } | null;\n /** Current source info */\n currentSourceInfo: { url: string; type: string } | null;\n /** Playback quality metrics */\n playbackQuality: PlaybackQuality | null;\n /** Subtitles enabled */\n subtitlesEnabled: boolean;\n /** Available quality levels */\n qualities: Array<{ id: string; label: string; bitrate?: number; width?: number; height?: number; isAuto?: boolean; active?: boolean }>;\n /** Available text/caption tracks */\n textTracks: Array<{ id: string; label: string; language?: string; active: boolean }>;\n /** Stream info for player selection (sources + tracks) */\n streamInfo: StreamInfo | null;\n}\n\nexport interface UsePlayerControllerReturn {\n /** Container ref to attach to your player container div */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Current state (reactive) */\n state: PlayerControllerState;\n /** Controller instance (for direct method calls) */\n controller: PlayerController | null;\n /** Play */\n play: () => Promise<void>;\n /** Pause */\n pause: () => void;\n /** Toggle play/pause */\n togglePlay: () => void;\n /** Seek to time */\n seek: (time: number) => void;\n /** Seek by delta */\n seekBy: (delta: number) => void;\n /** Set volume */\n setVolume: (volume: number) => void;\n /** Toggle mute */\n toggleMute: () => void;\n /** Toggle loop */\n toggleLoop: () => void;\n /** Toggle fullscreen */\n toggleFullscreen: () => Promise<void>;\n /** Toggle PiP */\n togglePiP: () => Promise<void>;\n /** Toggle subtitles */\n toggleSubtitles: () => void;\n /** Clear error */\n clearError: () => void;\n /** Retry playback */\n retry: () => Promise<void>;\n /** Reload player */\n reload: () => Promise<void>;\n /** Get qualities */\n getQualities: () => Array<{ id: string; label: string; bitrate?: number }>;\n /** Select quality */\n selectQuality: (id: string) => void;\n /** Handle mouse enter (for controls visibility) */\n handleMouseEnter: () => void;\n /** Handle mouse leave (for controls visibility) */\n handleMouseLeave: () => void;\n /** Handle mouse move (for controls visibility) */\n handleMouseMove: () => void;\n /** Handle touch start (for controls visibility) */\n handleTouchStart: () => void;\n /** Set dev mode options (force player, type, source) */\n setDevModeOptions: (options: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n playbackMode?: 'auto' | 'low-latency' | 'quality' | 'vod';\n }) => Promise<void>;\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialState: PlayerControllerState = {\n state: 'booting',\n streamState: null,\n endpoints: null,\n metadata: null,\n videoElement: null,\n currentTime: 0,\n duration: NaN,\n isPlaying: false,\n isPaused: true,\n isBuffering: false,\n isMuted: true,\n volume: 1,\n error: null,\n isPassiveError: false,\n hasPlaybackStarted: false,\n isHoldingSpeed: false,\n holdSpeed: 2,\n isHovering: false,\n shouldShowControls: false,\n isLoopEnabled: false,\n isFullscreen: false,\n isPiPActive: false,\n isEffectivelyLive: false,\n shouldShowIdleScreen: true,\n currentPlayerInfo: null,\n currentSourceInfo: null,\n playbackQuality: null,\n subtitlesEnabled: false,\n qualities: [],\n textTracks: [],\n streamInfo: null,\n};\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function usePlayerController(\n config: UsePlayerControllerConfig\n): UsePlayerControllerReturn {\n const { enabled = true, onStateChange, onStreamStateChange, onError, onReady, ...controllerConfig } = config;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const controllerRef = useRef<PlayerController | null>(null);\n const [state, setState] = useState<PlayerControllerState>(initialState);\n\n // Stable config ref for effect dependencies\n const configRef = useRef(controllerConfig);\n configRef.current = controllerConfig;\n\n // Create and attach controller\n useEffect(() => {\n if (!enabled) return;\n\n const container = containerRef.current;\n if (!container) return;\n\n // Create controller\n const controller = new PlayerController({\n contentId: configRef.current.contentId,\n contentType: configRef.current.contentType,\n endpoints: configRef.current.endpoints,\n gatewayUrl: configRef.current.gatewayUrl,\n mistUrl: configRef.current.mistUrl,\n authToken: configRef.current.authToken,\n autoplay: configRef.current.autoplay,\n muted: configRef.current.muted,\n controls: configRef.current.controls,\n poster: configRef.current.poster,\n debug: configRef.current.debug,\n });\n\n controllerRef.current = controller;\n\n // Subscribe to events\n const unsubs: Array<() => void> = [];\n\n // Sync state from controller - called on video events\n const syncState = () => {\n if (!controllerRef.current) return;\n const c = controllerRef.current;\n setState(prev => ({\n ...prev,\n isPlaying: c.isPlaying(),\n isPaused: c.isPaused(),\n isBuffering: c.isBuffering(),\n isMuted: c.isMuted(),\n volume: c.getVolume(),\n hasPlaybackStarted: c.hasPlaybackStarted(),\n shouldShowControls: c.shouldShowControls(),\n shouldShowIdleScreen: c.shouldShowIdleScreen(),\n playbackQuality: c.getPlaybackQuality(),\n isLoopEnabled: c.isLoopEnabled(),\n subtitlesEnabled: c.isSubtitlesEnabled(),\n qualities: c.getQualities(),\n streamInfo: c.getStreamInfo(),\n }));\n };\n\n unsubs.push(controller.on('stateChange', ({ state: newState }) => {\n setState(prev => ({ ...prev, state: newState }));\n onStateChange?.(newState);\n }));\n\n unsubs.push(controller.on('streamStateChange', ({ state: streamState }) => {\n setState(prev => ({\n ...prev,\n streamState,\n isEffectivelyLive: controller.isEffectivelyLive(),\n shouldShowIdleScreen: controller.shouldShowIdleScreen(),\n }));\n onStreamStateChange?.(streamState);\n }));\n\n unsubs.push(controller.on('timeUpdate', ({ currentTime, duration }) => {\n setState(prev => ({ ...prev, currentTime, duration }));\n }));\n\n unsubs.push(controller.on('error', ({ error }) => {\n setState(prev => ({\n ...prev,\n error,\n isPassiveError: controller.isPassiveError(),\n }));\n onError?.(error);\n }));\n\n unsubs.push(controller.on('errorCleared', () => {\n setState(prev => ({ ...prev, error: null, isPassiveError: false }));\n }));\n\n unsubs.push(controller.on('ready', ({ videoElement }) => {\n setState(prev => ({\n ...prev,\n videoElement,\n endpoints: controller.getEndpoints(),\n metadata: controller.getMetadata(),\n streamInfo: controller.getStreamInfo(),\n isEffectivelyLive: controller.isEffectivelyLive(),\n shouldShowIdleScreen: controller.shouldShowIdleScreen(),\n currentPlayerInfo: controller.getCurrentPlayerInfo(),\n currentSourceInfo: controller.getCurrentSourceInfo(),\n qualities: controller.getQualities(),\n }));\n onReady?.(videoElement);\n\n // Set up video event listeners AFTER video is ready\n // syncState is defined below - this closure captures it\n videoElement.addEventListener('play', syncState);\n videoElement.addEventListener('pause', syncState);\n videoElement.addEventListener('waiting', syncState);\n videoElement.addEventListener('playing', syncState);\n unsubs.push(() => {\n videoElement.removeEventListener('play', syncState);\n videoElement.removeEventListener('pause', syncState);\n videoElement.removeEventListener('waiting', syncState);\n videoElement.removeEventListener('playing', syncState);\n });\n }));\n\n unsubs.push(controller.on('playerSelected', ({ player, source }) => {\n setState(prev => ({\n ...prev,\n currentPlayerInfo: controller.getCurrentPlayerInfo(),\n currentSourceInfo: { url: source.url, type: source.type },\n qualities: controller.getQualities(),\n }));\n }));\n\n unsubs.push(controller.on('volumeChange', ({ volume, muted }) => {\n setState(prev => ({ ...prev, volume, isMuted: muted }));\n }));\n\n unsubs.push(controller.on('loopChange', ({ isLoopEnabled }) => {\n setState(prev => ({ ...prev, isLoopEnabled }));\n }));\n\n unsubs.push(controller.on('fullscreenChange', ({ isFullscreen }) => {\n setState(prev => ({ ...prev, isFullscreen }));\n }));\n\n unsubs.push(controller.on('pipChange', ({ isPiP }) => {\n setState(prev => ({ ...prev, isPiPActive: isPiP }));\n }));\n\n unsubs.push(controller.on('holdSpeedStart', ({ speed }) => {\n setState(prev => ({ ...prev, isHoldingSpeed: true, holdSpeed: speed }));\n }));\n\n unsubs.push(controller.on('holdSpeedEnd', () => {\n setState(prev => ({ ...prev, isHoldingSpeed: false }));\n }));\n\n unsubs.push(controller.on('hoverStart', () => {\n setState(prev => ({ ...prev, isHovering: true, shouldShowControls: true }));\n }));\n\n unsubs.push(controller.on('hoverEnd', () => {\n setState(prev => ({\n ...prev,\n isHovering: false,\n shouldShowControls: controller.shouldShowControls(),\n }));\n }));\n\n unsubs.push(controller.on('captionsChange', ({ enabled }) => {\n setState(prev => ({ ...prev, subtitlesEnabled: enabled }));\n }));\n\n // Attach controller to container\n // Note: Video event listeners are set up in the 'ready' handler above\n controller.attach(container).catch(err => {\n console.warn('[usePlayerController] Attach failed:', err);\n });\n\n // Set initial state\n setState(prev => ({\n ...prev,\n isLoopEnabled: controller.isLoopEnabled(),\n }));\n\n return () => {\n unsubs.forEach(fn => fn());\n controller.destroy();\n controllerRef.current = null;\n setState(initialState);\n };\n }, [enabled, config.contentId, config.contentType]); // Re-create on content change\n\n // Stable action callbacks\n const play = useCallback(async () => {\n await controllerRef.current?.play();\n }, []);\n\n const pause = useCallback(() => {\n controllerRef.current?.pause();\n }, []);\n\n const togglePlay = useCallback(() => {\n controllerRef.current?.togglePlay();\n }, []);\n\n const seek = useCallback((time: number) => {\n controllerRef.current?.seek(time);\n }, []);\n\n const seekBy = useCallback((delta: number) => {\n controllerRef.current?.seekBy(delta);\n }, []);\n\n const setVolume = useCallback((volume: number) => {\n controllerRef.current?.setVolume(volume);\n }, []);\n\n const toggleMute = useCallback(() => {\n controllerRef.current?.toggleMute();\n }, []);\n\n const toggleLoop = useCallback(() => {\n controllerRef.current?.toggleLoop();\n }, []);\n\n const toggleFullscreen = useCallback(async () => {\n await controllerRef.current?.toggleFullscreen();\n }, []);\n\n const togglePiP = useCallback(async () => {\n await controllerRef.current?.togglePictureInPicture();\n }, []);\n\n const toggleSubtitles = useCallback(() => {\n controllerRef.current?.toggleSubtitles();\n }, []);\n\n const clearError = useCallback(() => {\n controllerRef.current?.clearError();\n setState(prev => ({ ...prev, error: null, isPassiveError: false }));\n }, []);\n\n const retry = useCallback(async () => {\n await controllerRef.current?.retry();\n }, []);\n\n const reload = useCallback(async () => {\n await controllerRef.current?.reload();\n }, []);\n\n const getQualities = useCallback(() => {\n return controllerRef.current?.getQualities() ?? [];\n }, []);\n\n const selectQuality = useCallback((id: string) => {\n controllerRef.current?.selectQuality(id);\n }, []);\n\n const handleMouseEnter = useCallback(() => {\n controllerRef.current?.handleMouseEnter();\n }, []);\n\n const handleMouseLeave = useCallback(() => {\n controllerRef.current?.handleMouseLeave();\n }, []);\n\n const handleMouseMove = useCallback(() => {\n controllerRef.current?.handleMouseMove();\n }, []);\n\n const handleTouchStart = useCallback(() => {\n controllerRef.current?.handleTouchStart();\n }, []);\n\n const setDevModeOptions = useCallback(async (options: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n playbackMode?: 'auto' | 'low-latency' | 'quality' | 'vod';\n }) => {\n await controllerRef.current?.setDevModeOptions(options);\n }, []);\n\n return {\n containerRef,\n state,\n controller: controllerRef.current,\n play,\n pause,\n togglePlay,\n seek,\n seekBy,\n setVolume,\n toggleMute,\n toggleLoop,\n toggleFullscreen,\n togglePiP,\n toggleSubtitles,\n clearError,\n retry,\n reload,\n getQualities,\n selectQuality,\n handleMouseEnter,\n handleMouseLeave,\n handleMouseMove,\n handleTouchStart,\n setDevModeOptions,\n };\n}\n\nexport default usePlayerController;\n","/**\n * PlayerContext\n *\n * React context for sharing PlayerController state across components.\n * Follows the \"context wraps hook\" pattern (same as npm_studio).\n *\n * Usage:\n * ```tsx\n * <PlayerProvider config={{ contentId: 'stream-1', contentType: 'live' }}>\n * <PlayerControls />\n * </PlayerProvider>\n * ```\n */\n\nimport React, { createContext, useContext, type ReactNode } from 'react';\nimport {\n usePlayerController,\n type UsePlayerControllerConfig,\n type UsePlayerControllerReturn,\n} from '../hooks/usePlayerController';\n\n// Context holds the full hook return value\nconst PlayerContext = createContext<UsePlayerControllerReturn | null>(null);\n\nexport interface PlayerProviderProps {\n children: ReactNode;\n /** Configuration for the player controller */\n config: UsePlayerControllerConfig;\n}\n\n/**\n * Provider component that wraps Player and its controls.\n * Calls usePlayerController internally and shares state via context.\n */\nexport function PlayerProvider({ children, config }: PlayerProviderProps) {\n const playerController = usePlayerController(config);\n\n return (\n <PlayerContext.Provider value={playerController}>\n {children}\n </PlayerContext.Provider>\n );\n}\n\n/**\n * Hook to access player context.\n * Must be used within a PlayerProvider.\n */\nexport function usePlayerContext(): UsePlayerControllerReturn {\n const context = useContext(PlayerContext);\n if (!context) {\n throw new Error('usePlayerContext must be used within a PlayerProvider');\n }\n return context;\n}\n\n/**\n * Hook to optionally access player context.\n * Returns null if not within a PlayerProvider (no error thrown).\n * Use this when component may or may not be within a PlayerProvider.\n */\nexport function usePlayerContextOptional(): UsePlayerControllerReturn | null {\n return useContext(PlayerContext);\n}\n\n// Export context for advanced use cases\nexport { PlayerContext };\n\n// Type exports\nexport type { UsePlayerControllerReturn as PlayerContextValue };\nexport type { UsePlayerControllerConfig };\n","import * as React from \"react\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nexport interface SliderProps extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {\n showTrack?: boolean;\n trackClassName?: string;\n thumbClassName?: string;\n /** Show thumb only on hover (YouTube-style) - but always shows a smaller thumb when not hovered */\n hoverThumb?: boolean;\n /** Use cyan accent color (matches SeekBar styling) */\n accentColor?: boolean;\n}\n\nconst Slider = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, SliderProps>(\n ({ className, trackClassName, thumbClassName, showTrack = true, hoverThumb = false, accentColor = false, orientation = \"horizontal\", ...props }, ref) => {\n // Colors based on accentColor prop\n const rangeColorClass = accentColor ? \"bg-[hsl(var(--tn-cyan,195_100%_50%))]\" : \"bg-white/90\";\n const thumbColorClass = accentColor ? \"bg-[hsl(var(--tn-cyan,195_100%_50%))]\" : \"bg-white\";\n\n return (\n <SliderPrimitive.Root\n ref={ref}\n orientation={orientation}\n className={cn(\n \"group relative flex touch-none select-none items-center cursor-pointer\",\n orientation === \"horizontal\" ? \"w-full h-5\" : \"h-full flex-col w-5\",\n className\n )}\n {...props}\n >\n {showTrack && (\n <SliderPrimitive.Track\n className={cn(\n \"absolute rounded-full bg-white/30 transition-all duration-150\",\n orientation === \"horizontal\"\n ? \"inset-x-0 h-1 group-hover:h-1.5\"\n : \"inset-y-0 w-1 group-hover:w-1.5\",\n trackClassName\n )}\n >\n <SliderPrimitive.Range\n className={cn(\n \"absolute rounded-full transition-all duration-150\",\n orientation === \"horizontal\" ? \"h-full\" : \"w-full bottom-0\",\n rangeColorClass\n )}\n />\n </SliderPrimitive.Track>\n )}\n <SliderPrimitive.Thumb\n className={cn(\n \"block rounded-full border-0 cursor-pointer shadow-md transition-all duration-150\",\n \"w-2.5 h-2.5 group-hover:w-3.5 group-hover:h-3.5\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n thumbColorClass,\n thumbClassName\n )}\n />\n </SliderPrimitive.Root>\n );\n }\n);\nSlider.displayName = SliderPrimitive.Root.displayName;\n\nexport { Slider };\n","import React, { useRef, useState, useCallback, useMemo } from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface SeekBarProps {\n /** Current playback time in seconds */\n currentTime: number;\n /** Total duration in seconds */\n duration: number;\n /** Buffered time ranges from video element */\n buffered?: TimeRanges;\n /** Whether seeking is allowed */\n disabled?: boolean;\n /** Called when user seeks to a new time */\n onSeek?: (time: number) => void;\n /** Additional class names */\n className?: string;\n /** Whether this is a live stream */\n isLive?: boolean;\n /** For live: start of seekable DVR window (seconds) */\n seekableStart?: number;\n /** For live: current live edge position (seconds) */\n liveEdge?: number;\n /** Defer seeking until drag release */\n commitOnRelease?: boolean;\n}\n\n/**\n * Industry-standard video seek bar with:\n * - Track background\n * - Buffer progress indicator\n * - Playback progress indicator\n * - Thumb on hover\n * - Time tooltip on hover (relative for live: \"-5:30\")\n */\nconst SeekBar: React.FC<SeekBarProps> = ({\n currentTime,\n duration,\n buffered,\n disabled = false,\n onSeek,\n className,\n isLive = false,\n seekableStart = 0,\n liveEdge,\n commitOnRelease = false,\n}) => {\n const trackRef = useRef<HTMLDivElement>(null);\n const [isHovering, setIsHovering] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n const [dragTime, setDragTime] = useState<number | null>(null);\n const dragTimeRef = useRef<number | null>(null);\n const [hoverPosition, setHoverPosition] = useState(0);\n const [hoverTime, setHoverTime] = useState(0);\n\n // Effective live edge (use provided or fall back to duration)\n const effectiveLiveEdge = liveEdge ?? duration;\n\n // Seekable window size\n const seekableWindow = effectiveLiveEdge - seekableStart;\n\n // Calculate progress percentage\n // For live streams: position within the DVR window\n // For VOD: position within total duration\n const displayTime = dragTime ?? currentTime;\n const progressPercent = useMemo(() => {\n if (isLive && seekableWindow > 0) {\n const positionInWindow = displayTime - seekableStart;\n return Math.min(100, Math.max(0, (positionInWindow / seekableWindow) * 100));\n }\n if (!Number.isFinite(duration) || duration <= 0) return 0;\n return Math.min(100, Math.max(0, (displayTime / duration) * 100));\n }, [displayTime, duration, isLive, seekableStart, seekableWindow]);\n\n // Calculate buffered segments as array of {start%, end%} for accurate display\n const bufferedSegments = useMemo(() => {\n if (!buffered || buffered.length === 0) return [];\n\n const rangeEnd = isLive ? effectiveLiveEdge : duration;\n const rangeStart = isLive ? seekableStart : 0;\n const rangeSize = rangeEnd - rangeStart;\n\n if (!Number.isFinite(rangeSize) || rangeSize <= 0) return [];\n\n const segments: Array<{ startPercent: number; endPercent: number }> = [];\n for (let i = 0; i < buffered.length; i++) {\n const start = buffered.start(i);\n const end = buffered.end(i);\n\n // Calculate position relative to the seekable range\n const relativeStart = start - rangeStart;\n const relativeEnd = end - rangeStart;\n\n segments.push({\n startPercent: Math.min(100, Math.max(0, (relativeStart / rangeSize) * 100)),\n endPercent: Math.min(100, Math.max(0, (relativeEnd / rangeSize) * 100)),\n });\n }\n return segments;\n }, [buffered, duration, isLive, seekableStart, effectiveLiveEdge]);\n\n // Format time as MM:SS or HH:MM:SS (for VOD)\n const formatTime = useCallback((seconds: number): string => {\n if (!Number.isFinite(seconds) || seconds < 0) return \"0:00\";\n const total = Math.floor(seconds);\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const secs = total % 60;\n if (hours > 0) {\n return `${hours}:${String(minutes).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n }\n return `${minutes}:${String(secs).padStart(2, \"0\")}`;\n }, []);\n\n // Format relative time for live streams (e.g., \"-5:30\" = 5:30 behind live edge)\n const formatLiveTime = useCallback((seconds: number, edge: number): string => {\n const behindSeconds = edge - seconds;\n if (behindSeconds < 1) return \"LIVE\";\n const total = Math.floor(behindSeconds);\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const secs = total % 60;\n if (hours > 0) {\n return `-${hours}:${String(minutes).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n }\n return `-${minutes}:${String(secs).padStart(2, \"0\")}`;\n }, []);\n\n // Calculate time from mouse position\n // For live: maps position to time within DVR window\n const getTimeFromPosition = useCallback((clientX: number): number => {\n if (!trackRef.current) return 0;\n const rect = trackRef.current.getBoundingClientRect();\n const x = clientX - rect.left;\n const percent = Math.min(1, Math.max(0, x / rect.width));\n\n // Live with valid seekable window\n if (isLive && Number.isFinite(seekableWindow) && seekableWindow > 0) {\n return seekableStart + (percent * seekableWindow);\n }\n\n // VOD with finite duration\n if (Number.isFinite(duration) && duration > 0) {\n return percent * duration;\n }\n\n // Fallback: If we have liveEdge, use it even if not marked as live\n // This handles cases where duration is Infinity but we have valid seekable data\n if (Number.isFinite(liveEdge) && liveEdge > 0) {\n const start = Number.isFinite(seekableStart) ? seekableStart : 0;\n const window = liveEdge - start;\n if (window > 0) {\n return start + (percent * window);\n }\n }\n\n // Last resort: use currentTime as a baseline\n return percent * (currentTime || 1);\n }, [duration, isLive, seekableStart, seekableWindow, liveEdge, currentTime]);\n\n // Handle mouse move for hover preview\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!trackRef.current || disabled) return;\n const rect = trackRef.current.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const percent = Math.min(1, Math.max(0, x / rect.width));\n setHoverPosition(percent * 100);\n setHoverTime(getTimeFromPosition(e.clientX));\n }, [disabled, getTimeFromPosition]);\n\n // Handle click to seek\n const handleClick = useCallback((e: React.MouseEvent) => {\n if (disabled) return;\n if (!isLive && !Number.isFinite(duration)) return;\n const time = getTimeFromPosition(e.clientX);\n onSeek?.(time);\n setDragTime(null);\n dragTimeRef.current = null;\n }, [disabled, duration, isLive, getTimeFromPosition, onSeek]);\n\n // Handle drag start\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (disabled) return;\n if (!isLive && !Number.isFinite(duration)) return;\n e.preventDefault();\n setIsDragging(true);\n\n const handleDragMove = (moveEvent: MouseEvent) => {\n const time = getTimeFromPosition(moveEvent.clientX);\n if (commitOnRelease) {\n setDragTime(time);\n dragTimeRef.current = time;\n } else {\n onSeek?.(time);\n }\n };\n\n const handleDragEnd = () => {\n setIsDragging(false);\n document.removeEventListener(\"mousemove\", handleDragMove);\n document.removeEventListener(\"mouseup\", handleDragEnd);\n const pending = dragTimeRef.current;\n if (commitOnRelease && pending !== null) {\n onSeek?.(pending);\n setDragTime(null);\n dragTimeRef.current = null;\n }\n };\n\n document.addEventListener(\"mousemove\", handleDragMove);\n document.addEventListener(\"mouseup\", handleDragEnd);\n\n // Initial seek\n const time = getTimeFromPosition(e.clientX);\n if (commitOnRelease) {\n setDragTime(time);\n dragTimeRef.current = time;\n } else {\n onSeek?.(time);\n }\n }, [disabled, duration, isLive, getTimeFromPosition, onSeek, commitOnRelease]);\n\n const showThumb = isHovering || isDragging;\n const canShowTooltip = isLive ? seekableWindow > 0 : Number.isFinite(duration);\n\n return (\n <div\n ref={trackRef}\n className={cn(\n \"group relative w-full h-6 flex items-center cursor-pointer\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className\n )}\n onMouseEnter={() => !disabled && setIsHovering(true)}\n onMouseLeave={() => { setIsHovering(false); setIsDragging(false); }}\n onMouseMove={handleMouseMove}\n onClick={handleClick}\n onMouseDown={handleMouseDown}\n role=\"slider\"\n aria-label=\"Seek\"\n aria-valuemin={isLive ? seekableStart : 0}\n aria-valuemax={isLive ? effectiveLiveEdge : (duration || 100)}\n aria-valuenow={displayTime}\n aria-valuetext={isLive ? formatLiveTime(displayTime, effectiveLiveEdge) : formatTime(displayTime)}\n tabIndex={disabled ? -1 : 0}\n >\n {/* Track background */}\n <div className={cn(\n \"fw-seek-track\",\n isDragging && \"fw-seek-track--active\"\n )}>\n {/* Buffered segments - show actual buffered ranges */}\n {bufferedSegments.map((segment, index) => (\n <div\n key={index}\n className=\"fw-seek-buffered\"\n style={{\n left: `${segment.startPercent}%`,\n width: `${segment.endPercent - segment.startPercent}%`,\n }}\n />\n ))}\n {/* Playback progress */}\n <div\n className=\"fw-seek-progress\"\n style={{ width: `${progressPercent}%` }}\n />\n </div>\n\n {/* Thumb */}\n <div\n className={cn(\n \"fw-seek-thumb\",\n showThumb ? \"fw-seek-thumb--active\" : \"fw-seek-thumb--hidden\"\n )}\n style={{ left: `${progressPercent}%` }}\n />\n\n {/* Hover time tooltip */}\n {isHovering && !isDragging && canShowTooltip && (\n <div\n className=\"fw-seek-tooltip\"\n style={{ left: `${hoverPosition}%` }}\n >\n {isLive ? formatLiveTime(hoverTime, effectiveLiveEdge) : formatTime(hoverTime)}\n </div>\n )}\n </div>\n );\n};\n\nexport default SeekBar;\n","import React from 'react';\n\ninterface IconProps {\n size?: number;\n color?: string;\n className?: string;\n}\n\nexport const PlayIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M8 5v14l11-7z\"\n fill={color}\n />\n </svg>\n);\n\nexport const PauseIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" fill={color} />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" fill={color} />\n </svg>\n);\n\nexport const SkipBackIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n {/* Circular rewind arrow */}\n <path\n d=\"M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"\n fill={color}\n />\n <text x=\"12\" y=\"15\" fontSize=\"7\" fontWeight=\"bold\" fill={color} textAnchor=\"middle\">10</text>\n </svg>\n);\n\nexport const SkipForwardIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n {/* Circular forward arrow */}\n <path\n d=\"M12 5V1l5 5-5 5V7c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6h2c0 4.42-3.58 8-8 8s-8-3.58-8-8 3.58-8 8-8z\"\n fill={color}\n />\n <text x=\"12\" y=\"15\" fontSize=\"7\" fontWeight=\"bold\" fill={color} textAnchor=\"middle\">10</text>\n </svg>\n);\n\nexport const VolumeUpIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <polygon points=\"11,5 6,9 2,9 2,15 6,15 11,19\" fill={color} />\n <path\n d=\"M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const VolumeOffIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <polygon points=\"11,5 6,9 2,9 2,15 6,15 11,19\" fill={color} />\n <line x1=\"23\" y1=\"9\" x2=\"17\" y2=\"15\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" />\n <line x1=\"17\" y1=\"9\" x2=\"23\" y2=\"15\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n);\n\nexport const FullscreenIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3m8 0h3a2 2 0 0 0 2-2v-3\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const FullscreenExitIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const PictureInPictureIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\" stroke={color} strokeWidth=\"2\" fill=\"none\" />\n <rect x=\"8\" y=\"10\" width=\"10\" height=\"6\" rx=\"1\" ry=\"1\" fill={color} />\n </svg>\n);\n\nexport const ClosedCaptionsIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" ry=\"2\" stroke={color} strokeWidth=\"2\" fill=\"none\" />\n <path\n d=\"M8 10c0-.6.4-1 1-1h1c.6 0 1 .4 1 1v4c0 .6-.4 1-1 1H9c-.6 0-1-.4-1-1v-4zM14 10c0-.6.4-1 1-1h1c.6 0 1 .4 1 1v4c0 .6-.4 1-1 1h-1c-.6 0-1-.4-1-1v-4z\"\n fill={color}\n />\n </svg>\n);\n\nexport const LiveIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"3\" fill={color} />\n <path\n d=\"M12 1v6M12 17v6M4.22 4.22l4.24 4.24M15.54 15.54l4.24 4.24M1 12h6M17 12h6M4.22 19.78l4.24-4.24M15.54 8.46l4.24-4.24\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nexport const SettingsIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\n// Compound PlayPause icon that switches based on state\ninterface PlayPauseIconProps extends IconProps {\n isPlaying?: boolean;\n}\n\nexport const PlayPauseIcon: React.FC<PlayPauseIconProps> = ({ isPlaying, ...props }) => {\n return isPlaying ? <PauseIcon {...props} /> : <PlayIcon {...props} />;\n};\n\n// Volume icon that switches based on mute state\ninterface VolumeIconProps extends IconProps {\n isMuted?: boolean;\n}\n\nexport const VolumeIcon: React.FC<VolumeIconProps> = ({ isMuted, ...props }) => {\n return isMuted ? <VolumeOffIcon {...props} /> : <VolumeUpIcon {...props} />;\n};\n\n// Fullscreen icon that switches based on fullscreen state\ninterface FullscreenToggleIconProps extends IconProps {\n isFullscreen?: boolean;\n}\n\nexport const FullscreenToggleIcon: React.FC<FullscreenToggleIconProps> = ({ isFullscreen, ...props }) => {\n return isFullscreen ? <FullscreenExitIcon {...props} /> : <FullscreenIcon {...props} />;\n};\n\n// Stats icon (bar chart style - recognizable for \"stats for nerds\")\nexport const StatsIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"4\" y=\"13\" width=\"4\" height=\"7\" fill={color} />\n <rect x=\"10\" y=\"9\" width=\"4\" height=\"11\" fill={color} />\n <rect x=\"16\" y=\"4\" width=\"4\" height=\"16\" fill={color} />\n </svg>\n);\n\n// Seek to live/end icon (skip-to-end style: play triangle + bar)\nexport const SeekToLiveIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n {/* Play triangle */}\n <path d=\"M5 5v14l11-7z\" fill={color} />\n {/* End bar */}\n <rect x=\"17\" y=\"5\" width=\"3\" height=\"14\" fill={color} />\n </svg>\n);","import React, { useEffect, useMemo, useState, useRef, useCallback } from \"react\";\nimport { usePlayerContextOptional } from \"../context/PlayerContext\";\nimport {\n cn,\n // Seeking utilities from core\n SPEED_PRESETS,\n getLatencyTier,\n isMediaStreamSource,\n supportsPlaybackRate as coreSupportsPlaybackRate,\n calculateSeekableRange,\n canSeekStream,\n calculateLiveThresholds,\n calculateIsNearLive,\n isLiveContent,\n // Time formatting from core\n formatTime,\n formatTimeDisplay,\n} from \"@livepeer-frameworks/player-core\";\nimport { Slider } from \"../ui/slider\";\nimport SeekBar from \"./SeekBar\";\nimport {\n ClosedCaptionsIcon,\n FullscreenToggleIcon,\n LiveIcon,\n PlayPauseIcon,\n SeekToLiveIcon,\n SkipBackIcon,\n SkipForwardIcon,\n StatsIcon,\n VolumeIcon,\n SettingsIcon\n} from \"./Icons\";\nimport type { MistStreamInfo, PlaybackMode } from \"../types\";\n\ninterface PlayerControlsProps {\n currentTime: number;\n duration: number;\n isVisible?: boolean;\n className?: string;\n onSeek?: (time: number) => void;\n showStatsButton?: boolean;\n isStatsOpen?: boolean;\n onStatsToggle?: () => void;\n /** Live MistServer stream info - drives control visibility based on server metadata */\n mistStreamInfo?: MistStreamInfo;\n /** Disable all controls (e.g., while player is initializing) */\n disabled?: boolean;\n /** Current playback mode */\n playbackMode?: PlaybackMode;\n /** Callback when playback mode changes */\n onModeChange?: (mode: PlaybackMode) => void;\n /** Current source protocol type (e.g., 'whep', 'ws/video/mp4', 'html5/application/vnd.apple.mpegurl') */\n sourceType?: string;\n /** Content-type based live flag (for mode selector visibility, separate from seek bar isLive) */\n isContentLive?: boolean;\n /** Video element - passed from parent hook */\n videoElement?: HTMLVideoElement | null;\n /** Available quality levels - passed from parent hook */\n qualities?: Array<{ id: string; label: string; bitrate?: number; width?: number; height?: number; isAuto?: boolean; active?: boolean }>;\n /** Callback to select quality */\n onSelectQuality?: (id: string) => void;\n /** Is player muted */\n isMuted?: boolean;\n /** Current volume (0-1) */\n volume?: number;\n /** Callback for volume change */\n onVolumeChange?: (volume: number) => void;\n /** Toggle mute callback */\n onToggleMute?: () => void;\n /** Is playing */\n isPlaying?: boolean;\n /** Toggle play/pause callback */\n onTogglePlay?: () => void;\n /** Toggle fullscreen callback */\n onToggleFullscreen?: () => void;\n /** Is fullscreen */\n isFullscreen?: boolean;\n /** Is loop enabled */\n isLoopEnabled?: boolean;\n /** Toggle loop callback */\n onToggleLoop?: () => void;\n}\n\n\nconst PlayerControls: React.FC<PlayerControlsProps> = ({\n currentTime,\n duration,\n isVisible = true,\n className,\n onSeek,\n mistStreamInfo,\n disabled = false,\n playbackMode = 'auto',\n onModeChange,\n sourceType,\n isContentLive,\n videoElement: propVideoElement,\n qualities: propQualities = [],\n onSelectQuality,\n isMuted: propIsMuted,\n volume: propVolume,\n onVolumeChange,\n onToggleMute,\n isPlaying: propIsPlaying,\n onTogglePlay,\n onToggleFullscreen,\n isFullscreen: propIsFullscreen,\n isLoopEnabled: propIsLoopEnabled,\n onToggleLoop,\n}) => {\n // Context fallback - prefer props passed from parent over context\n // Context provides UsePlayerControllerReturn which has state.videoElement and controller\n const ctx = usePlayerContextOptional();\n const contextVideo = ctx?.state?.videoElement;\n const player = ctx?.controller;\n\n // Robust video element detection - prefer prop, then context, then DOM query\n const [video, setVideo] = useState<HTMLVideoElement | null>(null);\n const videoCheckIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const findVideoElement = useCallback((): HTMLVideoElement | null => {\n if (propVideoElement) return propVideoElement;\n if (contextVideo) return contextVideo;\n if (player?.getVideoElement?.()) return player.getVideoElement();\n const domVideo = document.querySelector('.fw-player-video') as HTMLVideoElement | null\n ?? document.querySelector('[data-player-container=\"true\"] video') as HTMLVideoElement | null\n ?? document.querySelector('.fw-player-container video') as HTMLVideoElement | null;\n return domVideo;\n }, [propVideoElement, contextVideo, player]);\n\n useEffect(() => {\n const updateVideo = () => {\n const v = findVideoElement();\n if (v && v !== video) {\n setVideo(v);\n }\n };\n updateVideo();\n if (!video) {\n videoCheckIntervalRef.current = setInterval(() => {\n const v = findVideoElement();\n if (v) {\n setVideo(v);\n if (videoCheckIntervalRef.current) {\n clearInterval(videoCheckIntervalRef.current);\n videoCheckIntervalRef.current = null;\n }\n }\n }, 100);\n setTimeout(() => {\n if (videoCheckIntervalRef.current) {\n clearInterval(videoCheckIntervalRef.current);\n videoCheckIntervalRef.current = null;\n }\n }, 5000);\n }\n return () => {\n if (videoCheckIntervalRef.current) {\n clearInterval(videoCheckIntervalRef.current);\n videoCheckIntervalRef.current = null;\n }\n };\n }, [contextVideo, player, findVideoElement, video]);\n\n const mistTracks = mistStreamInfo?.meta?.tracks;\n\n // Quality selection priority:\n // 1. Player-provided qualities (HLS.js/DASH.js levels with correct numeric indices)\n // 2. Mist track metadata (for players that don't provide quality API)\n // This fixes a critical bug where Mist track IDs (e.g., \"a1\", \"v0\") were passed to\n // HLS/DASH players which expect numeric indices (e.g., \"0\", \"1\", \"2\")\n // Quality levels - prefer props, then player API, then Mist tracks\n const qualities = useMemo(() => {\n // Priority 1: Props from parent (usePlayerController hook)\n if (propQualities && propQualities.length > 0) {\n return propQualities;\n }\n\n // Priority 2: Player's quality API\n const playerQualities = player?.getQualities?.();\n if (playerQualities && playerQualities.length > 0) {\n return playerQualities;\n }\n\n // Fallback to Mist track metadata for players without quality API\n if (mistTracks) {\n return Object.entries(mistTracks)\n .filter(([, t]) => t.type === 'video')\n .map(([id, t]) => ({\n id,\n label: t.height ? `${t.height}p` : t.codec,\n width: t.width,\n height: t.height,\n bitrate: t.bps,\n }))\n .sort((a, b) => (b.height || 0) - (a.height || 0));\n }\n return [];\n }, [propQualities, player, mistTracks]);\n\n const textTracks = player?.getTextTracks?.() ?? [];\n\n // Internal state - used as fallback when props not provided\n const [internalIsPlaying, setInternalIsPlaying] = useState(false);\n const [internalIsMuted, setInternalIsMuted] = useState(false);\n const [internalIsFullscreen, setInternalIsFullscreen] = useState(false);\n const [hasAudio, setHasAudio] = useState(true);\n const [buffered, setBuffered] = useState<TimeRanges | undefined>(undefined);\n const [internalVolume, setInternalVolume] = useState<number>(() => {\n if (!video) return 100;\n return Math.round(video.volume * 100);\n });\n const [playbackRate, setPlaybackRate] = useState<number>(() => video?.playbackRate ?? 1);\n\n // Derived state - prefer props over internal state\n const isPlaying = propIsPlaying ?? internalIsPlaying;\n const isMuted = propIsMuted ?? internalIsMuted;\n const isFullscreen = propIsFullscreen ?? internalIsFullscreen;\n const volumeValue = propVolume !== undefined ? Math.round(propVolume * 100) : internalVolume;\n const [qualityValue, setQualityValue] = useState<string>(\"auto\");\n const [captionValue, setCaptionValue] = useState<string>(\"none\");\n const [isSettingsOpen, setIsSettingsOpen] = useState(false);\n // Hysteresis state for Live badge - prevents flip-flopping\n const [isNearLiveState, setIsNearLiveState] = useState(true);\n\n // Close settings menu when clicking outside\n useEffect(() => {\n if (!isSettingsOpen) return;\n\n const handleWindowClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (target && !target.closest('.fw-settings-menu')) {\n setIsSettingsOpen(false);\n }\n };\n\n // Use setTimeout to avoid immediate close from the same click that opened it\n const timeoutId = setTimeout(() => {\n window.addEventListener('click', handleWindowClick);\n }, 0);\n\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener('click', handleWindowClick);\n };\n }, [isSettingsOpen]);\n\n // Core utility-based calculations\n const bufferWindowMs = mistStreamInfo?.meta?.buffer_window;\n\n const isLive = useMemo(() => isLiveContent(isContentLive, mistStreamInfo, duration),\n [isContentLive, mistStreamInfo, duration]);\n\n const isWebRTC = useMemo(() => isMediaStreamSource(video), [video]);\n\n const supportsPlaybackRate = useMemo(() => coreSupportsPlaybackRate(video), [video]);\n\n // Seekable range using core calculation (allow controller override)\n const { seekableStart: calcSeekableStart, liveEdge: calcLiveEdge } = useMemo(() => calculateSeekableRange({\n isLive,\n video,\n mistStreamInfo,\n currentTime,\n duration,\n }), [isLive, video, mistStreamInfo, currentTime, duration]);\n const controllerSeekableStart = player?.getSeekableStart?.();\n const controllerLiveEdge = player?.getLiveEdge?.();\n const useControllerRange = Number.isFinite(controllerSeekableStart) &&\n Number.isFinite(controllerLiveEdge) &&\n (controllerLiveEdge as number) >= (controllerSeekableStart as number) &&\n ((controllerLiveEdge as number) > 0 || (controllerSeekableStart as number) > 0);\n const seekableStart = useControllerRange ? (controllerSeekableStart as number) : calcSeekableStart;\n const liveEdge = useControllerRange ? (controllerLiveEdge as number) : calcLiveEdge;\n\n const hasDvrWindow = isLive && Number.isFinite(liveEdge) && Number.isFinite(seekableStart) && liveEdge > seekableStart;\n const commitOnRelease = isLive;\n\n // Live thresholds with buffer window scaling\n const liveThresholds = useMemo(() =>\n calculateLiveThresholds(sourceType, isWebRTC, bufferWindowMs),\n [sourceType, isWebRTC, bufferWindowMs]);\n\n // Can seek - prefer PlayerController's computed value (includes player-specific canSeek)\n // Fall back to utility function when controller not available\n const canSeek = useMemo(() => {\n // PlayerController already computes canSeek with player-specific logic\n if (player && typeof (player as any).canSeekStream === 'function') {\n return (player as any).canSeekStream();\n }\n // Fallback when no controller\n return canSeekStream({\n video,\n isLive,\n duration,\n bufferWindowMs,\n });\n }, [video, isLive, duration, bufferWindowMs, player]);\n\n // Hysteresis for live badge - using core calculation\n useEffect(() => {\n if (!isLive) {\n setIsNearLiveState(true);\n return;\n }\n const newState = calculateIsNearLive(currentTime, liveEdge, liveThresholds, isNearLiveState);\n if (newState !== isNearLiveState) {\n setIsNearLiveState(newState);\n }\n }, [isLive, liveEdge, currentTime, liveThresholds, isNearLiveState]);\n\n // Track if we've already seeked to live on initial playback\n const hasSeekToLiveRef = useRef(false);\n\n // Sync internal state from video element (only when props not provided)\n useEffect(() => {\n if (!video) return;\n const updatePlayingState = () => setInternalIsPlaying(!video.paused);\n const updateMutedState = () => {\n const muted = video.muted || video.volume === 0;\n setInternalIsMuted(muted);\n setInternalVolume(Math.round(video.volume * 100));\n };\n const updateFullscreenState = () => {\n if (typeof document !== \"undefined\") setInternalIsFullscreen(!!document.fullscreenElement);\n };\n const updatePlaybackRate = () => setPlaybackRate(video.playbackRate);\n\n updatePlayingState();\n updateMutedState();\n updateFullscreenState();\n updatePlaybackRate();\n\n video.addEventListener(\"play\", updatePlayingState);\n video.addEventListener(\"pause\", updatePlayingState);\n video.addEventListener(\"playing\", updatePlayingState);\n video.addEventListener(\"volumechange\", updateMutedState);\n video.addEventListener(\"ratechange\", updatePlaybackRate);\n if (typeof document !== \"undefined\") document.addEventListener(\"fullscreenchange\", updateFullscreenState);\n\n return () => {\n video.removeEventListener(\"play\", updatePlayingState);\n video.removeEventListener(\"pause\", updatePlayingState);\n video.removeEventListener(\"playing\", updatePlayingState);\n video.removeEventListener(\"volumechange\", updateMutedState);\n video.removeEventListener(\"ratechange\", updatePlaybackRate);\n if (typeof document !== \"undefined\") document.removeEventListener(\"fullscreenchange\", updateFullscreenState);\n };\n }, [video, isLive]);\n\n // Reset the seek-to-live flag when video element changes (new stream)\n useEffect(() => {\n hasSeekToLiveRef.current = false;\n }, [video]);\n\n useEffect(() => {\n const activeTrack = textTracks.find((track) => track.active);\n setCaptionValue(activeTrack ? activeTrack.id : \"none\");\n }, [textTracks]);\n\n // Track buffered ranges for SeekBar\n useEffect(() => {\n if (!video) return;\n const updateBuffered = () => {\n const next = player?.getBufferedRanges?.() ?? video.buffered;\n setBuffered(next);\n };\n updateBuffered();\n video.addEventListener(\"progress\", updateBuffered);\n video.addEventListener(\"loadeddata\", updateBuffered);\n return () => {\n video.removeEventListener(\"progress\", updateBuffered);\n video.removeEventListener(\"loadeddata\", updateBuffered);\n };\n }, [video]);\n\n useEffect(() => {\n if (!video) { setHasAudio(true); return; }\n const checkAudio = () => {\n if (video.srcObject instanceof MediaStream) {\n const audioTracks = video.srcObject.getAudioTracks();\n setHasAudio(audioTracks.length > 0);\n return;\n }\n const videoAny = video as any;\n if (videoAny.audioTracks && videoAny.audioTracks.length !== undefined) {\n setHasAudio(videoAny.audioTracks.length > 0);\n return;\n }\n setHasAudio(true);\n };\n checkAudio();\n video.addEventListener(\"loadedmetadata\", checkAudio);\n return () => video.removeEventListener(\"loadedmetadata\", checkAudio);\n }, [video]);\n\n const handlePlayPause = () => {\n if (disabled) return;\n // Prefer prop callback from usePlayerController\n if (onTogglePlay) {\n onTogglePlay();\n return;\n }\n // Fallback: direct video/player manipulation\n if (!video && !player) return;\n const isPaused = player?.isPaused?.() ?? video?.paused ?? true;\n if (isPaused) {\n if (player?.play) player.play().catch(() => {});\n else if (video) video.play().catch(() => {});\n } else {\n if (player?.pause) player.pause();\n else if (video) video.pause();\n }\n };\n\n const handleSkipBack = () => {\n const newTime = Math.max(0, currentTime - 10);\n if (onSeek) {\n onSeek(newTime);\n return;\n }\n const v = findVideoElement();\n if (v) v.currentTime = newTime;\n };\n\n const handleSkipForward = () => {\n const maxTime = Number.isFinite(duration) ? duration : currentTime + 10;\n const newTime = Math.min(maxTime, currentTime + 10);\n if (onSeek) {\n onSeek(newTime);\n return;\n }\n const v = findVideoElement();\n if (v) v.currentTime = newTime;\n };\n\n const handleMute = () => {\n if (disabled) return;\n // Prefer prop callback from usePlayerController\n if (onToggleMute) {\n onToggleMute();\n return;\n }\n // Fallback: direct video/player manipulation\n const v = video ?? document.querySelector('.fw-player-video') as HTMLVideoElement | null;\n if (!v) return;\n const nextMuted = !(player?.isMuted?.() ?? v.muted);\n player?.setMuted?.(nextMuted);\n v.muted = nextMuted;\n setInternalIsMuted(nextMuted);\n if (nextMuted) setInternalVolume(0);\n else setInternalVolume(Math.round(v.volume * 100));\n };\n\n const handleVolumeChange = (value: number[]) => {\n if (disabled) return;\n const next = Math.max(0, Math.min(100, value[0] ?? 0));\n // Prefer prop callback from usePlayerController\n if (onVolumeChange) {\n onVolumeChange(next / 100);\n return;\n }\n // Fallback: direct video manipulation\n const v = video ?? document.querySelector('.fw-player-video') as HTMLVideoElement | null;\n if (!v) return;\n v.volume = next / 100;\n v.muted = next === 0;\n setInternalVolume(next);\n setInternalIsMuted(next === 0);\n };\n\n const handleFullscreen = () => {\n if (disabled) return;\n // Prefer prop callback from usePlayerController\n if (onToggleFullscreen) {\n onToggleFullscreen();\n return;\n }\n // Fallback: direct DOM manipulation\n if (typeof document === \"undefined\") return;\n const container = document.querySelector('[data-player-container=\"true\"]') as HTMLElement | null;\n if (!container) return;\n if (document.fullscreenElement) document.exitFullscreen().catch(() => {});\n else container.requestFullscreen().catch(() => {});\n };\n\n const handleGoLive = () => {\n if (disabled) return;\n player?.jumpToLive?.();\n };\n\n const handleSpeedChange = (value: string) => {\n if (disabled) return;\n const rate = Number(value);\n setPlaybackRate(rate);\n // Use player API if available, fall back to direct video element\n if (player?.setPlaybackRate) {\n player.setPlaybackRate(rate);\n } else {\n const v = findVideoElement();\n if (v) v.playbackRate = rate;\n }\n };\n\n const handleQualityChange = (value: string) => {\n if (disabled) return;\n setQualityValue(value);\n // Prefer prop callback from usePlayerController\n if (onSelectQuality) {\n onSelectQuality(value);\n return;\n }\n // Fallback: direct player manipulation\n player?.selectQuality?.(value);\n };\n\n const handleCaptionChange = (value: string) => {\n if (disabled) return;\n setCaptionValue(value);\n if (value === \"none\") player?.selectTextTrack?.(null);\n else player?.selectTextTrack?.(value);\n };\n\n // Time display - using core formatTimeDisplay\n const timeDisplay = useMemo(() => formatTimeDisplay({\n isLive,\n currentTime,\n duration,\n liveEdge,\n seekableStart,\n unixoffset: mistStreamInfo?.unixoffset,\n }), [isLive, currentTime, duration, liveEdge, seekableStart, mistStreamInfo?.unixoffset]);\n\n const [isVolumeHovered, setIsVolumeHovered] = useState(false);\n const [isVolumeFocused, setIsVolumeFocused] = useState(false);\n const isVolumeExpanded = isVolumeHovered || isVolumeFocused;\n\n return (\n <div className={cn(\n \"fw-player-surface fw-controls-wrapper\",\n isVisible ? \"fw-controls-wrapper--visible\" : \"fw-controls-wrapper--hidden\"\n )}>\n {/* Bottom Row: Controls with SeekBar on top */}\n <div\n className=\"fw-control-bar pointer-events-auto\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* SeekBar - sits directly on top of control buttons */}\n {canSeek && (\n <div className=\"fw-seek-wrapper\">\n <SeekBar\n currentTime={currentTime}\n duration={duration}\n buffered={buffered}\n disabled={disabled}\n isLive={isLive}\n seekableStart={seekableStart}\n liveEdge={liveEdge}\n commitOnRelease={commitOnRelease}\n onSeek={(time) => {\n if (onSeek) {\n onSeek(time);\n } else if (video) {\n video.currentTime = time;\n }\n }}\n />\n </div>\n )}\n\n {/* Control buttons row */}\n <div className=\"fw-controls-row\">\n {/* Left: Controls & Time */}\n <div className=\"fw-controls-left\">\n <div className=\"fw-control-group\">\n <button type=\"button\" className=\"fw-btn-flush\" aria-label={isPlaying ? \"Pause\" : \"Play\"} onClick={handlePlayPause}>\n <PlayPauseIcon isPlaying={isPlaying} size={18} />\n </button>\n {canSeek && (\n <>\n <button type=\"button\" className=\"fw-btn-flush hidden sm:flex\" aria-label=\"Skip back 10 seconds\" onClick={handleSkipBack}>\n <SkipBackIcon size={16} />\n </button>\n <button type=\"button\" className=\"fw-btn-flush hidden sm:flex\" aria-label=\"Skip forward 10 seconds\" onClick={handleSkipForward}>\n <SkipForwardIcon size={16} />\n </button>\n </>\n )}\n </div>\n\n {/* Volume pill - cohesive hover element (slab style) */}\n <div\n className={cn(\n \"fw-volume-group\",\n isVolumeExpanded && \"fw-volume-group--expanded\",\n !hasAudio && \"fw-volume-group--disabled\"\n )}\n onMouseEnter={() => hasAudio && setIsVolumeHovered(true)}\n onMouseLeave={() => {\n setIsVolumeHovered(false);\n setIsVolumeFocused(false);\n }}\n onFocusCapture={() => hasAudio && setIsVolumeFocused(true)}\n onBlurCapture={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsVolumeFocused(false);\n }}\n onClick={(e) => {\n // Click on the pill (not slider) toggles mute\n if (hasAudio && e.target === e.currentTarget) {\n handleMute();\n }\n }}\n >\n {/* Volume icon - part of the pill */}\n <button\n type=\"button\"\n className=\"fw-volume-btn\"\n aria-label={!hasAudio ? \"No audio\" : (isMuted ? \"Unmute\" : \"Mute\")}\n onClick={hasAudio ? handleMute : undefined}\n disabled={!hasAudio}\n >\n <VolumeIcon isMuted={isMuted || !hasAudio} size={16} />\n </button>\n {/* Slider - expands within the pill */}\n <div className={cn(\n \"fw-volume-slider-wrapper\",\n isVolumeExpanded ? \"fw-volume-slider-wrapper--expanded\" : \"fw-volume-slider-wrapper--collapsed\"\n )}>\n <Slider\n orientation=\"horizontal\"\n aria-label=\"Volume\"\n max={100}\n step={1}\n value={[volumeValue]}\n onValueChange={handleVolumeChange}\n className=\"w-full\"\n disabled={!hasAudio}\n />\n </div>\n </div>\n\n <div className=\"fw-control-group\">\n <span className=\"fw-time-display\">\n {timeDisplay}\n </span>\n </div>\n\n {isLive && (\n <div className=\"fw-control-group\">\n <button\n type=\"button\"\n onClick={handleGoLive}\n disabled={!hasDvrWindow || isNearLiveState}\n className={cn(\n \"fw-live-badge\",\n (!hasDvrWindow || isNearLiveState) ? \"fw-live-badge--active\" : \"fw-live-badge--behind\",\n !hasDvrWindow && \"fw-live-badge--nodvr\"\n )}\n title={!hasDvrWindow ? \"Live only (DVR disabled)\" : (isNearLiveState ? \"At live edge\" : \"Jump to live\")}\n >\n LIVE\n {!hasDvrWindow && <span className=\"fw-live-badge__nodvr\">NO DVR</span>}\n {!isNearLiveState && hasDvrWindow && <SeekToLiveIcon size={10} />}\n </button>\n </div>\n )}\n </div>\n\n {/* Right Group: Settings, Fullscreen */}\n <div className=\"fw-controls-right\">\n <div className=\"fw-control-group relative\">\n <button\n type=\"button\"\n className={cn(\"fw-btn-flush group\", isSettingsOpen && \"fw-btn-flush--active\")}\n aria-label=\"Settings\"\n title=\"Settings\"\n onClick={() => setIsSettingsOpen(!isSettingsOpen)}\n >\n <SettingsIcon size={16} className=\"transition-transform group-hover:rotate-90\" />\n </button>\n\n {/* Settings Popup */}\n {isSettingsOpen && (\n <div className=\"fw-player-surface fw-settings-menu\">\n {/* Playback Mode - only show for live content (not VOD/clips) */}\n {onModeChange && isContentLive !== false && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Mode</div>\n <div className=\"fw-settings-options\">\n {(['auto', 'low-latency', 'quality'] as const).map((mode) => (\n <button\n key={mode}\n className={cn(\n \"fw-settings-btn\",\n playbackMode === mode && \"fw-settings-btn--active\"\n )}\n onClick={() => { onModeChange(mode); setIsSettingsOpen(false); }}\n >\n {mode === 'low-latency' ? 'Fast' : mode === 'quality' ? 'Stable' : 'Auto'}\n </button>\n ))}\n </div>\n </div>\n )}\n {supportsPlaybackRate && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Speed</div>\n <div className=\"fw-settings-options fw-settings-options--wrap\">\n {SPEED_PRESETS.map((rate) => (\n <button\n key={rate}\n className={cn(\n \"fw-settings-btn\",\n playbackRate === rate && \"fw-settings-btn--active\"\n )}\n onClick={() => { handleSpeedChange(String(rate)); setIsSettingsOpen(false); }}\n >\n {rate}x\n </button>\n ))}\n </div>\n </div>\n )}\n {qualities.length > 0 && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Quality</div>\n <div className=\"fw-settings-list\">\n <button\n className={cn(\n \"fw-settings-list-item\",\n qualityValue === 'auto' && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleQualityChange('auto'); setIsSettingsOpen(false); }}\n >\n Auto\n </button>\n {qualities.map((q) => (\n <button\n key={q.id}\n className={cn(\n \"fw-settings-list-item\",\n qualityValue === q.id && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleQualityChange(q.id); setIsSettingsOpen(false); }}\n >\n {q.label}\n </button>\n ))}\n </div>\n </div>\n )}\n {textTracks.length > 0 && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Captions</div>\n <div className=\"fw-settings-list\">\n <button\n className={cn(\n \"fw-settings-list-item\",\n captionValue === 'none' && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleCaptionChange('none'); setIsSettingsOpen(false); }}\n >\n Off\n </button>\n {textTracks.map((t) => (\n <button\n key={t.id}\n className={cn(\n \"fw-settings-list-item\",\n captionValue === t.id && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleCaptionChange(t.id); setIsSettingsOpen(false); }}\n >\n {t.label || t.id}\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"fw-control-group\">\n <button type=\"button\" className=\"fw-btn-flush\" aria-label=\"Toggle fullscreen\" onClick={handleFullscreen}>\n <FullscreenToggleIcon isFullscreen={isFullscreen} size={16} />\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default PlayerControls;\n","import React, { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport {\n cn,\n globalPlayerManager,\n QualityMonitor,\n type StreamInfo,\n type MistStreamInfo,\n type PlaybackMode,\n} from \"@livepeer-frameworks/player-core\";\n\n/** Short labels for source types */\nconst SOURCE_TYPE_LABELS: Record<string, string> = {\n \"html5/application/vnd.apple.mpegurl\": \"HLS\",\n \"dash/video/mp4\": \"DASH\",\n \"html5/video/mp4\": \"MP4\",\n \"html5/video/webm\": \"WebM\",\n \"whep\": \"WHEP\",\n \"mist/html\": \"Mist\",\n \"mist/legacy\": \"Auto\",\n \"ws/video/mp4\": \"MEWS\",\n};\n\nexport interface DevModePanelProps {\n /** Callback when user selects a combo (one-shot selection) */\n onSettingsChange: (settings: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n }) => void;\n /** Current playback mode */\n playbackMode?: PlaybackMode;\n /** Callback when playback mode changes */\n onModeChange?: (mode: PlaybackMode) => void;\n /** Callback to force player reload */\n onReload?: () => void;\n /** Stream info for getting all combinations (sources + tracks from MistServer) */\n streamInfo?: StreamInfo | null;\n /** MistServer stream metadata including tracks */\n mistStreamInfo?: MistStreamInfo | null;\n /** Current player info */\n currentPlayer?: {\n name: string;\n shortname: string;\n } | null;\n /** Current source info */\n currentSource?: {\n url: string;\n type: string;\n } | null;\n /** Video element for stats */\n videoElement?: HTMLVideoElement | null;\n /** Protocol/node info */\n protocol?: string;\n nodeId?: string;\n /** Whether the panel toggle is visible (hover state) */\n isVisible?: boolean;\n /** Controlled open state (if provided, component is controlled) */\n isOpen?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (isOpen: boolean) => void;\n}\n\n/**\n * DevModePanel - Advanced Settings overlay for testing player configurations\n * Similar to MistPlayer's skin: \"dev\" mode\n */\nconst DevModePanel: React.FC<DevModePanelProps> = ({\n onSettingsChange,\n playbackMode = 'auto',\n onModeChange,\n onReload,\n streamInfo,\n mistStreamInfo,\n currentPlayer,\n currentSource,\n videoElement,\n protocol,\n nodeId,\n isVisible = true,\n isOpen: controlledIsOpen,\n onOpenChange,\n}) => {\n // Support both controlled and uncontrolled modes\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = useCallback((value: boolean) => {\n if (onOpenChange) {\n onOpenChange(value);\n } else {\n setInternalIsOpen(value);\n }\n }, [onOpenChange]);\n const [activeTab, setActiveTab] = useState<\"config\" | \"stats\">(\"config\");\n const [currentComboIndex, setCurrentComboIndex] = useState(0);\n const [hoveredComboIndex, setHoveredComboIndex] = useState<number | null>(null);\n const [tooltipAbove, setTooltipAbove] = useState(false);\n const [showDisabledPlayers, setShowDisabledPlayers] = useState(false);\n const comboListRef = useRef<HTMLDivElement>(null);\n\n // Quality monitoring for playback score\n const qualityMonitorRef = useRef<QualityMonitor | null>(null);\n const [playbackScore, setPlaybackScore] = useState<number>(1.0);\n const [qualityScore, setQualityScore] = useState<number>(100);\n const [stallCount, setStallCount] = useState<number>(0);\n const [frameDropRate, setFrameDropRate] = useState<number>(0);\n\n // Player-specific stats (from getStats())\n const [playerStats, setPlayerStats] = useState<any>(null);\n const statsIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // Start/stop quality monitoring based on video element\n useEffect(() => {\n if (videoElement && isOpen) {\n if (!qualityMonitorRef.current) {\n qualityMonitorRef.current = new QualityMonitor({\n sampleInterval: 500,\n onSample: (quality) => {\n setQualityScore(quality.score);\n setStallCount(quality.stallCount);\n setFrameDropRate(quality.frameDropRate);\n // Get playback score from monitor\n if (qualityMonitorRef.current) {\n setPlaybackScore(qualityMonitorRef.current.getPlaybackScore());\n }\n },\n });\n }\n qualityMonitorRef.current.start(videoElement);\n }\n\n return () => {\n if (qualityMonitorRef.current) {\n qualityMonitorRef.current.stop();\n }\n };\n }, [videoElement, isOpen]);\n\n // Poll player-specific stats when stats tab is open\n useEffect(() => {\n if (isOpen && activeTab === \"stats\") {\n const pollStats = async () => {\n try {\n const player = globalPlayerManager.getCurrentPlayer();\n if (player && player.getStats) {\n const stats = await player.getStats();\n if (stats) {\n setPlayerStats(stats);\n }\n }\n } catch (e) {\n // Ignore errors\n }\n };\n\n // Poll immediately and then every 500ms\n pollStats();\n statsIntervalRef.current = setInterval(pollStats, 500);\n\n return () => {\n if (statsIntervalRef.current) {\n clearInterval(statsIntervalRef.current);\n statsIntervalRef.current = null;\n }\n };\n }\n }, [isOpen, activeTab]);\n\n // Get all player-source combinations with scores (including incompatible)\n // Uses cached results from PlayerManager - won't recompute if data unchanged\n const allCombinations = useMemo(() => {\n if (!streamInfo) return [];\n try {\n // getAllCombinations now includes all combos (compatible + incompatible)\n // and uses content-based caching - won't spam on every render\n return globalPlayerManager.getAllCombinations(streamInfo, playbackMode);\n } catch {\n return [];\n }\n }, [streamInfo, playbackMode]);\n\n // For backward compatibility (Next Option only cycles compatible)\n const combinations = useMemo(() => {\n return allCombinations.filter(c => c.compatible);\n }, [allCombinations]);\n\n // Find current active combo index based on current player/source (in allCombinations)\n const activeComboIndex = useMemo(() => {\n if (!currentPlayer || !currentSource || allCombinations.length === 0) return -1;\n return allCombinations.findIndex(\n (c) => c.player === currentPlayer.shortname && c.sourceType === currentSource.type\n );\n }, [currentPlayer, currentSource, allCombinations]);\n\n // Find index in compatible-only list for Next Option cycling\n const activeCompatibleIndex = useMemo(() => {\n if (!currentPlayer || !currentSource || combinations.length === 0) return -1;\n return combinations.findIndex(\n (c) => c.player === currentPlayer.shortname && c.sourceType === currentSource.type\n );\n }, [currentPlayer, currentSource, combinations]);\n\n const handleReload = useCallback(() => {\n // Just trigger reload - controller manages the state\n onReload?.();\n }, [onReload]);\n\n const handleNextCombo = useCallback(() => {\n if (combinations.length === 0) return;\n\n // Start from active combo or 0, then move to next (only cycles compatible)\n const startIdx = activeCompatibleIndex >= 0 ? activeCompatibleIndex : -1;\n const nextIdx = (startIdx + 1) % combinations.length;\n const combo = combinations[nextIdx];\n\n setCurrentComboIndex(nextIdx);\n onSettingsChange({\n forcePlayer: combo.player,\n forceType: combo.sourceType,\n forceSource: combo.sourceIndex,\n });\n }, [combinations, activeCompatibleIndex, onSettingsChange]);\n\n const handleSelectCombo = useCallback((index: number) => {\n const combo = allCombinations[index];\n if (!combo) return;\n\n // Allow selecting even incompatible combos in dev mode (for testing)\n setCurrentComboIndex(index);\n onSettingsChange({\n forcePlayer: combo.player,\n forceType: combo.sourceType,\n forceSource: combo.sourceIndex,\n });\n }, [allCombinations, onSettingsChange]);\n\n // Video stats - poll periodically when stats tab is open\n const [stats, setStats] = useState<{\n resolution: string;\n buffered: string;\n playbackRate: string;\n currentTime: string;\n duration: string;\n readyState: number;\n networkState: number;\n } | null>(null);\n\n useEffect(() => {\n if (!isOpen || activeTab !== \"stats\") return;\n\n const updateStats = () => {\n // Get fresh video element from player manager\n const player = globalPlayerManager.getCurrentPlayer();\n const v = player?.getVideoElement() || videoElement;\n if (!v) {\n setStats(null);\n return;\n }\n setStats({\n resolution: `${v.videoWidth}x${v.videoHeight}`,\n buffered:\n v.buffered.length > 0\n ? (v.buffered.end(v.buffered.length - 1) - v.currentTime).toFixed(1)\n : \"0\",\n playbackRate: v.playbackRate.toFixed(2),\n currentTime: v.currentTime.toFixed(1),\n duration: isFinite(v.duration) ? v.duration.toFixed(1) : \"live\",\n readyState: v.readyState,\n networkState: v.networkState,\n });\n };\n\n updateStats();\n const interval = setInterval(updateStats, 500);\n return () => clearInterval(interval);\n }, [isOpen, activeTab, videoElement]);\n\n // Toggle button (when closed)\n if (!isOpen) {\n return (\n <button\n type=\"button\"\n onClick={() => setIsOpen(true)}\n className={cn(\n \"fw-dev-toggle\",\n !isVisible && \"fw-dev-toggle--hidden\"\n )}\n title=\"Advanced Settings\"\n aria-label=\"Open advanced settings panel\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\" />\n </svg>\n </button>\n );\n }\n\n return (\n <div className=\"fw-dev-panel\">\n {/* Header with tabs */}\n <div className=\"fw-dev-header\">\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"config\")}\n className={cn(\"fw-dev-tab\", activeTab === \"config\" && \"fw-dev-tab--active\")}\n >\n Config\n </button>\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"stats\")}\n className={cn(\"fw-dev-tab\", activeTab === \"stats\" && \"fw-dev-tab--active\")}\n >\n Stats\n </button>\n <div className=\"fw-dev-spacer\" />\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n className=\"fw-dev-close\"\n aria-label=\"Close dev mode panel\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path d=\"M2 2l8 8M10 2l-8 8\" />\n </svg>\n </button>\n </div>\n\n {/* Config Tab */}\n {activeTab === \"config\" && (\n <div ref={comboListRef} className=\"fw-dev-body\">\n {/* Current State */}\n <div className=\"fw-dev-section\">\n <div className=\"fw-dev-label\">Active</div>\n <div className=\"fw-dev-value\">\n {currentPlayer?.name || \"None\"}{\" \"}\n <span className=\"fw-dev-value-arrow\">→</span>{\" \"}\n {SOURCE_TYPE_LABELS[currentSource?.type || \"\"] || currentSource?.type || \"—\"}\n </div>\n {nodeId && (\n <div className=\"fw-dev-value-muted\">Node: {nodeId}</div>\n )}\n </div>\n\n {/* Playback Mode Selector */}\n <div className=\"fw-dev-section\">\n <div className=\"fw-dev-label\">Playback Mode</div>\n <div className=\"fw-dev-mode-group\">\n {(['auto', 'low-latency', 'quality'] as const).map((mode) => (\n <button\n key={mode}\n type=\"button\"\n onClick={() => onModeChange?.(mode)}\n className={cn(\n \"fw-dev-mode-btn\",\n playbackMode === mode && \"fw-dev-mode-btn--active\"\n )}\n >\n {mode === 'low-latency' ? 'Low Lat' : mode.charAt(0).toUpperCase() + mode.slice(1)}\n </button>\n ))}\n </div>\n <div className=\"fw-dev-mode-desc\">\n {playbackMode === 'auto' && 'Balanced: MP4/WS → WHEP → HLS'}\n {playbackMode === 'low-latency' && 'WHEP/WebRTC first (<1s delay)'}\n {playbackMode === 'quality' && 'MP4/WS first, HLS fallback'}\n </div>\n </div>\n\n {/* Action buttons */}\n <div className=\"fw-dev-actions\">\n <button\n type=\"button\"\n onClick={handleReload}\n className=\"fw-dev-action-btn\"\n >\n Reload\n </button>\n <button\n type=\"button\"\n onClick={handleNextCombo}\n className=\"fw-dev-action-btn\"\n >\n Next Option\n </button>\n </div>\n\n {/* Combo list */}\n <div className=\"fw-dev-section\" style={{ padding: 0, borderBottom: 0 }}>\n <div className=\"fw-dev-list-header\">\n <span className=\"fw-dev-list-title\">\n Player Options ({combinations.length})\n </span>\n {allCombinations.length > combinations.length && (\n <button\n type=\"button\"\n onClick={() => setShowDisabledPlayers(!showDisabledPlayers)}\n className=\"fw-dev-list-toggle\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className={cn(\"fw-dev-chevron\", showDisabledPlayers && \"fw-dev-chevron--open\")}\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n {showDisabledPlayers ? \"Hide\" : \"Show\"} disabled ({allCombinations.length - combinations.length})\n </button>\n )}\n </div>\n {allCombinations.length === 0 ? (\n <div className=\"fw-dev-list-empty\">\n No stream info available\n </div>\n ) : (\n <div>\n {allCombinations.map((combo, index) => {\n // Codec-incompatible items always show (with warning), MIME-incompatible hide in \"disabled\"\n const isCodecIncompat = (combo as any).codecIncompatible === true;\n if (!combo.compatible && !isCodecIncompat && !showDisabledPlayers) return null;\n\n const isActive = activeComboIndex === index;\n const typeLabel = SOURCE_TYPE_LABELS[combo.sourceType] || combo.sourceType.split(\"/\").pop();\n\n // Determine score class\n const getScoreClass = () => {\n if (!combo.compatible && !isCodecIncompat) return \"fw-dev-combo-score--disabled\";\n if (isCodecIncompat) return \"fw-dev-combo-score--low\";\n if (combo.score >= 2) return \"fw-dev-combo-score--high\";\n if (combo.score >= 1.5) return \"fw-dev-combo-score--mid\";\n return \"fw-dev-combo-score--low\";\n };\n\n // Determine rank class\n const getRankClass = () => {\n if (isActive) return \"fw-dev-combo-rank--active\";\n if (!combo.compatible && !isCodecIncompat) return \"fw-dev-combo-rank--disabled\";\n if (isCodecIncompat) return \"fw-dev-combo-rank--warn\";\n return \"\";\n };\n\n // Determine type class\n const getTypeClass = () => {\n if (!combo.compatible && !isCodecIncompat) return \"fw-dev-combo-type--disabled\";\n if (isCodecIncompat) return \"fw-dev-combo-type--warn\";\n return \"\";\n };\n\n return (\n <div\n key={`${combo.player}-${combo.sourceType}`}\n onMouseEnter={(e) => {\n setHoveredComboIndex(index);\n if (comboListRef.current) {\n const container = comboListRef.current;\n const row = e.currentTarget;\n const containerRect = container.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const relativePosition = (rowRect.top - containerRect.top) / containerRect.height;\n setTooltipAbove(relativePosition > 0.6);\n }\n }}\n onMouseLeave={() => setHoveredComboIndex(null)}\n className=\"fw-dev-combo\"\n >\n <button\n type=\"button\"\n onClick={() => handleSelectCombo(index)}\n className={cn(\n \"fw-dev-combo-btn\",\n isActive && \"fw-dev-combo-btn--active\",\n !combo.compatible && !isCodecIncompat && \"fw-dev-combo-btn--disabled\",\n isCodecIncompat && \"fw-dev-combo-btn--codec-warn\"\n )}\n >\n {/* Rank */}\n <span className={cn(\"fw-dev-combo-rank\", getRankClass())}>\n {combo.compatible ? index + 1 : isCodecIncompat ? \"⚠\" : \"—\"}\n </span>\n {/* Player + Protocol */}\n <span className=\"fw-dev-combo-name\">\n {combo.playerName}{\" \"}\n <span className=\"fw-dev-combo-arrow\">→</span>{\" \"}\n <span className={cn(\"fw-dev-combo-type\", getTypeClass())}>{typeLabel}</span>\n </span>\n {/* Score */}\n <span className={cn(\"fw-dev-combo-score\", getScoreClass())}>\n {combo.score.toFixed(2)}\n </span>\n </button>\n\n {/* Score breakdown tooltip */}\n {hoveredComboIndex === index && (\n <div className={cn(\n \"fw-dev-tooltip\",\n tooltipAbove ? \"fw-dev-tooltip--above\" : \"fw-dev-tooltip--below\"\n )}>\n {/* Full player/source info */}\n <div className=\"fw-dev-tooltip-header\">\n <div className=\"fw-dev-tooltip-title\">{combo.playerName}</div>\n <div className=\"fw-dev-tooltip-subtitle\">{combo.sourceType}</div>\n {combo.scoreBreakdown?.trackTypes && combo.scoreBreakdown.trackTypes.length > 0 && (\n <div className=\"fw-dev-tooltip-tracks\">\n Tracks: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.trackTypes.join(', ')}</span>\n </div>\n )}\n </div>\n {combo.compatible && combo.scoreBreakdown ? (\n <>\n <div className=\"fw-dev-tooltip-score\">Score: {combo.score.toFixed(2)}</div>\n <div className=\"fw-dev-tooltip-row\">\n Tracks [{combo.scoreBreakdown.trackTypes.join(', ')}]: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.trackScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.tracks}</span>\n </div>\n <div className=\"fw-dev-tooltip-row\">\n Priority: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.priorityScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.priority}</span>\n </div>\n <div className=\"fw-dev-tooltip-row\">\n Source: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.sourceScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.source}</span>\n </div>\n {combo.scoreBreakdown.reliabilityScore !== undefined && (\n <div className=\"fw-dev-tooltip-row\">\n Reliability: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.reliabilityScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.reliability ?? 0}</span>\n </div>\n )}\n {combo.scoreBreakdown.modeBonus !== undefined && combo.scoreBreakdown.modeBonus !== 0 && (\n <div className=\"fw-dev-tooltip-row\">\n Mode ({playbackMode}): <span className=\"fw-dev-tooltip-bonus\">+{combo.scoreBreakdown.modeBonus.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.mode ?? 0}</span>\n </div>\n )}\n {combo.scoreBreakdown.routingBonus !== undefined && combo.scoreBreakdown.routingBonus !== 0 && (\n <div className=\"fw-dev-tooltip-row\">\n Routing: <span className={combo.scoreBreakdown.routingBonus > 0 ? \"fw-dev-tooltip-bonus\" : \"fw-dev-tooltip-penalty\"}>{combo.scoreBreakdown.routingBonus > 0 ? '+' : ''}{combo.scoreBreakdown.routingBonus.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.routing ?? 0}</span>\n </div>\n )}\n </>\n ) : (\n <div className=\"fw-dev-tooltip-error\">{combo.incompatibleReason || 'Incompatible'}</div>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Stats Tab */}\n {activeTab === \"stats\" && (\n <div className=\"fw-dev-body\">\n {/* Playback Rate */}\n <div className=\"fw-dev-section\">\n <div className=\"fw-dev-label\">Playback Rate</div>\n <div className=\"fw-dev-rate\">\n <div className={cn(\n \"fw-dev-rate-value\",\n playbackScore >= 0.95 && playbackScore <= 1.05 ? \"fw-dev-stat-value--good\" :\n playbackScore > 1.05 ? \"fw-dev-stat-value--accent\" :\n playbackScore >= 0.75 ? \"fw-dev-stat-value--warn\" :\n \"fw-dev-stat-value--bad\"\n )}>\n {playbackScore.toFixed(2)}×\n </div>\n <div className=\"fw-dev-rate-status\">\n {playbackScore >= 0.95 && playbackScore <= 1.05 ? \"realtime\" :\n playbackScore > 1.05 ? \"catching up\" :\n playbackScore >= 0.75 ? \"slightly slow\" :\n \"stalling\"}\n </div>\n </div>\n <div className=\"fw-dev-rate-stats\">\n <span className={qualityScore >= 75 ? \"fw-dev-stat-value--good\" : \"fw-dev-stat-value--bad\"}>\n Quality: {qualityScore}/100\n </span>\n <span className={stallCount === 0 ? \"fw-dev-stat-value--good\" : \"fw-dev-stat-value--warn\"}>\n Stalls: {stallCount}\n </span>\n <span className={frameDropRate < 1 ? \"fw-dev-stat-value--good\" : \"fw-dev-stat-value--bad\"}>\n Drops: {frameDropRate.toFixed(1)}%\n </span>\n </div>\n </div>\n\n {/* Video Stats */}\n {stats ? (\n <div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Resolution</span>\n <span className=\"fw-dev-stat-value\">{stats.resolution}</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Buffer</span>\n <span className=\"fw-dev-stat-value\">{stats.buffered}s</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Playback Rate</span>\n <span className=\"fw-dev-stat-value\">{stats.playbackRate}x</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Time</span>\n <span className=\"fw-dev-stat-value\">\n {stats.currentTime} / {stats.duration}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Ready State</span>\n <span className=\"fw-dev-stat-value\">{stats.readyState}</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Network State</span>\n <span className=\"fw-dev-stat-value\">{stats.networkState}</span>\n </div>\n {protocol && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Protocol</span>\n <span className=\"fw-dev-stat-value\">{protocol}</span>\n </div>\n )}\n {nodeId && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Node ID</span>\n <span className=\"fw-dev-stat-value truncate\" style={{ maxWidth: '150px' }}>\n {nodeId}\n </span>\n </div>\n )}\n </div>\n ) : (\n <div className=\"fw-dev-list-empty\">\n No video element available\n </div>\n )}\n\n {/* Player-specific Stats (HLS.js / WebRTC) */}\n {playerStats && (\n <div>\n <div className=\"fw-dev-list-header fw-dev-section-header\">\n <span className=\"fw-dev-list-title\">\n {playerStats.type === 'hls' ? 'HLS.js Stats' :\n playerStats.type === 'webrtc' ? 'WebRTC Stats' : 'Player Stats'}\n </span>\n </div>\n\n {/* HLS-specific stats */}\n {playerStats.type === 'hls' && (\n <>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Bitrate</span>\n <span className=\"fw-dev-stat-value--accent\">\n {playerStats.currentBitrate > 0\n ? `${Math.round(playerStats.currentBitrate / 1000)} kbps`\n : 'N/A'}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Bandwidth Est.</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.bandwidthEstimate > 0\n ? `${Math.round(playerStats.bandwidthEstimate / 1000)} kbps`\n : 'N/A'}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Level</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.currentLevel >= 0 ? playerStats.currentLevel : 'Auto'} / {playerStats.levels?.length || 0}\n </span>\n </div>\n {playerStats.latency !== undefined && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Latency</span>\n <span className={playerStats.latency > 5000 ? \"fw-dev-stat-value--warn\" : \"fw-dev-stat-value\"}>\n {Math.round(playerStats.latency)} ms\n </span>\n </div>\n )}\n </>\n )}\n\n {/* WebRTC-specific stats */}\n {playerStats.type === 'webrtc' && (\n <>\n {playerStats.video && (\n <>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Video Bitrate</span>\n <span className=\"fw-dev-stat-value--accent\">\n {playerStats.video.bitrate > 0\n ? `${Math.round(playerStats.video.bitrate / 1000)} kbps`\n : 'N/A'}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">FPS</span>\n <span className=\"fw-dev-stat-value\">\n {Math.round(playerStats.video.framesPerSecond || 0)}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Frames</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.video.framesDecoded} decoded,{' '}\n <span className={playerStats.video.frameDropRate > 1 ? \"fw-dev-stat-value--bad\" : \"fw-dev-stat-value--good\"}>\n {playerStats.video.framesDropped} dropped\n </span>\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Packet Loss</span>\n <span className={playerStats.video.packetLossRate > 1 ? \"fw-dev-stat-value--bad\" : \"fw-dev-stat-value--good\"}>\n {playerStats.video.packetLossRate.toFixed(2)}%\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Jitter</span>\n <span className={playerStats.video.jitter > 30 ? \"fw-dev-stat-value--warn\" : \"fw-dev-stat-value\"}>\n {playerStats.video.jitter.toFixed(1)} ms\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Jitter Buffer</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.video.jitterBufferDelay.toFixed(1)} ms\n </span>\n </div>\n </>\n )}\n {playerStats.network && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">RTT</span>\n <span className={playerStats.network.rtt > 200 ? \"fw-dev-stat-value--warn\" : \"fw-dev-stat-value\"}>\n {Math.round(playerStats.network.rtt)} ms\n </span>\n </div>\n )}\n </>\n )}\n </div>\n )}\n\n {/* MistServer Track Info */}\n {mistStreamInfo?.meta?.tracks && Object.keys(mistStreamInfo.meta.tracks).length > 0 && (\n <div>\n <div className=\"fw-dev-list-header fw-dev-section-header\">\n <span className=\"fw-dev-list-title\">\n Tracks ({Object.keys(mistStreamInfo.meta.tracks).length})\n </span>\n </div>\n {Object.entries(mistStreamInfo.meta.tracks).map(([id, track]) => (\n <div key={id} className=\"fw-dev-track\">\n <div className=\"fw-dev-track-header\">\n <span className={cn(\n \"fw-dev-track-badge\",\n track.type === 'video' ? \"fw-dev-track-badge--video\" :\n track.type === 'audio' ? \"fw-dev-track-badge--audio\" :\n \"fw-dev-track-badge--other\"\n )}>\n {track.type}\n </span>\n <span className=\"fw-dev-track-codec\">{track.codec}</span>\n <span className=\"fw-dev-track-id\">#{id}</span>\n </div>\n <div className=\"fw-dev-track-meta\">\n {track.type === 'video' && track.width && track.height && (\n <span>{track.width}×{track.height}</span>\n )}\n {track.bps && (\n <span>{Math.round(track.bps / 1000)} kbps</span>\n )}\n {track.fpks && (\n <span>{Math.round(track.fpks / 1000)} fps</span>\n )}\n {track.type === 'audio' && track.channels && (\n <span>{track.channels}ch</span>\n )}\n {track.type === 'audio' && track.rate && (\n <span>{track.rate} Hz</span>\n )}\n {track.lang && (\n <span>{track.lang}</span>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Debug: Show if mistStreamInfo is missing tracks */}\n {mistStreamInfo && (!mistStreamInfo.meta?.tracks || Object.keys(mistStreamInfo.meta.tracks).length === 0) && (\n <div className=\"fw-dev-no-tracks\">\n <span className=\"fw-dev-no-tracks-text\">\n No track data available\n {mistStreamInfo.type && <span className=\"fw-dev-no-tracks-type\">({mistStreamInfo.type})</span>}\n </span>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default DevModePanel;\n","import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface SpeedIndicatorProps {\n isVisible: boolean;\n speed: number;\n className?: string;\n}\n\n/**\n * Speed indicator overlay that appears when holding for fast-forward.\n * Shows the current playback speed (e.g., \"2x\") in a pill overlay.\n */\nconst SpeedIndicator: React.FC<SpeedIndicatorProps> = ({\n isVisible,\n speed,\n className,\n}) => {\n return (\n <div\n className={cn(\n \"fw-speed-indicator absolute inset-0 z-30 pointer-events-none\",\n \"flex items-center justify-center\",\n \"transition-opacity duration-150\",\n isVisible ? \"opacity-100\" : \"opacity-0\",\n className\n )}\n >\n <div\n className={cn(\n \"bg-black/80 text-white px-4 py-2 rounded-full\",\n \"text-lg font-semibold tabular-nums\",\n \"flex items-center gap-2\",\n \"backdrop-blur-sm border border-white/20\",\n \"transform transition-transform duration-150\",\n isVisible ? \"scale-100\" : \"scale-90\"\n )}\n >\n <FastForwardIcon className=\"w-5 h-5\" />\n <span>{speed}x</span>\n </div>\n </div>\n );\n};\n\n// Simple fast-forward icon\nconst FastForwardIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\" />\n </svg>\n);\n\nexport default SpeedIndicator;\n","import React, { useEffect, useState } from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nexport type SkipDirection = \"back\" | \"forward\" | null;\n\ninterface SkipIndicatorProps {\n direction: SkipDirection;\n seconds?: number;\n className?: string;\n onHide?: () => void;\n}\n\n/**\n * Skip indicator overlay that appears when double-tapping to skip.\n * Shows the skip direction and amount (e.g., \"-10s\" or \"+10s\") with a ripple effect.\n */\nconst SkipIndicator: React.FC<SkipIndicatorProps> = ({\n direction,\n seconds = 10,\n className,\n onHide,\n}) => {\n const [isAnimating, setIsAnimating] = useState(false);\n\n useEffect(() => {\n if (direction) {\n setIsAnimating(true);\n const timer = setTimeout(() => {\n setIsAnimating(false);\n onHide?.();\n }, 600);\n return () => clearTimeout(timer);\n }\n }, [direction, onHide]);\n\n if (!direction) return null;\n\n const isBack = direction === \"back\";\n\n return (\n <div\n className={cn(\n \"fw-skip-indicator absolute inset-0 z-30 pointer-events-none\",\n \"flex items-center\",\n isBack ? \"justify-start pl-8\" : \"justify-end pr-8\",\n className\n )}\n >\n {/* Ripple background */}\n <div\n className={cn(\n \"absolute top-0 bottom-0 w-1/3\",\n isBack ? \"left-0\" : \"right-0\",\n \"bg-white/10\",\n isAnimating && \"animate-pulse\"\n )}\n />\n\n {/* Skip content */}\n <div\n className={cn(\n \"relative flex flex-col items-center gap-1 text-white\",\n \"transition-all duration-200\",\n isAnimating ? \"opacity-100 scale-100\" : \"opacity-0 scale-75\"\n )}\n >\n {/* Icon */}\n <div className=\"flex\">\n {isBack ? (\n <>\n <RewindIcon className=\"w-8 h-8\" />\n <RewindIcon className=\"w-8 h-8 -ml-4\" />\n </>\n ) : (\n <>\n <FastForwardIcon className=\"w-8 h-8\" />\n <FastForwardIcon className=\"w-8 h-8 -ml-4\" />\n </>\n )}\n </div>\n\n {/* Text */}\n <span className=\"text-sm font-semibold tabular-nums\">\n {isBack ? `-${seconds}s` : `+${seconds}s`}\n </span>\n </div>\n </div>\n );\n};\n\nconst RewindIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\" />\n </svg>\n);\n\nconst FastForwardIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\" />\n </svg>\n);\n\nexport default SkipIndicator;\n","import * as React from \"react\"\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\"\nimport { Check, ChevronRight, Circle } from \"lucide-react\"\nimport { cn } from \"@livepeer-frameworks/player-core\"\n\nconst ContextMenu = ContextMenuPrimitive.Root\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup\n\nconst ContextMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <ContextMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"fw-context-menu-item\",\n inset && \"fw-context-menu-item--inset\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto h-4 w-4\" />\n </ContextMenuPrimitive.SubTrigger>\n))\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName\n\nconst ContextMenuSubContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.SubContent\n ref={ref}\n className={cn(\"fw-player-surface fw-context-menu\", className)}\n {...props}\n />\n))\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName\n\nconst ContextMenuContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\n>(({ className, style, ...props }, ref) => (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n ref={ref}\n className={cn(\"fw-player-surface fw-context-menu\", className)}\n style={{\n // Inline styles for portal elements (rendered outside .fw-player-root)\n // These ensure styles work even without CSS variable inheritance\n backgroundColor: 'hsl(235 19% 13%)',\n color: 'hsl(229 35% 75%)',\n border: '1px solid rgba(90, 96, 127, 0.3)',\n ...style\n }}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n))\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName\n\nconst ContextMenuItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"fw-context-menu-item\",\n inset && \"fw-context-menu-item--inset\",\n className\n )}\n {...props}\n />\n))\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <ContextMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\"fw-context-menu-checkbox\", className)}\n checked={checked}\n {...props}\n >\n <span className=\"fw-context-menu-indicator\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n))\nContextMenuCheckboxItem.displayName =\n ContextMenuPrimitive.CheckboxItem.displayName\n\nconst ContextMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <ContextMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\"fw-context-menu-checkbox\", className)}\n {...props}\n >\n <span className=\"fw-context-menu-indicator\">\n <ContextMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n))\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName\n\nconst ContextMenuLabel = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"fw-context-menu-label\",\n inset && \"fw-context-menu-item--inset\",\n className\n )}\n {...props}\n />\n))\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName\n\nconst ContextMenuSeparator = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Separator\n ref={ref}\n className={cn(\"fw-context-menu-separator\", className)}\n {...props}\n />\n))\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName\n\nconst ContextMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\nContextMenuShortcut.displayName = \"ContextMenuShortcut\"\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n}\n","import React, { useState, useCallback, useMemo } from \"react\";\nimport IdleScreen from \"./IdleScreen\";\nimport ThumbnailOverlay from \"./ThumbnailOverlay\";\nimport TitleOverlay from \"./TitleOverlay\";\nimport StatsPanel from \"./StatsPanel\";\nimport PlayerControls from \"./PlayerControls\";\nimport DevModePanel from \"./DevModePanel\";\nimport SpeedIndicator from \"./SpeedIndicator\";\nimport SkipIndicator, { SkipDirection } from \"./SkipIndicator\";\nimport { StatsIcon, SettingsIcon, PictureInPictureIcon } from \"./Icons\";\nimport { PlayerProps } from \"../types\";\nimport { usePlayerController } from \"../hooks/usePlayerController\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\nimport type { PlaybackMode, EndpointInfo } from \"@livepeer-frameworks/player-core\";\nimport {\n ContextMenu,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuSeparator,\n ContextMenuTrigger,\n} from \"../ui/context-menu\";\n\n/**\n * Inner player component that uses PlayerController via hook\n */\nconst PlayerInner: React.FC<PlayerProps> = ({\n contentId,\n contentType,\n thumbnailUrl = null,\n options,\n endpoints: propsEndpoints,\n onStateChange\n}) => {\n // ============================================================================\n // UI-only State (stays in wrapper)\n // ============================================================================\n const [isStatsOpen, setIsStatsOpen] = useState(false);\n const [isDevPanelOpen, setIsDevPanelOpen] = useState(false);\n const [skipDirection, setSkipDirection] = useState<SkipDirection>(null);\n\n // Playback mode preference (persistent)\n const [devPlaybackMode, setDevPlaybackMode] = useState<PlaybackMode>(options?.playbackMode || 'auto');\n\n // ============================================================================\n // PlayerController Hook - ALL business logic\n // ============================================================================\n const {\n containerRef,\n state,\n controller,\n togglePlay,\n toggleMute,\n toggleLoop,\n toggleFullscreen,\n togglePiP,\n setVolume,\n selectQuality,\n clearError,\n retry,\n reload,\n handleMouseEnter,\n handleMouseLeave,\n handleMouseMove,\n setDevModeOptions,\n } = usePlayerController({\n contentId,\n contentType,\n endpoints: propsEndpoints,\n gatewayUrl: options?.gatewayUrl,\n mistUrl: options?.mistUrl,\n authToken: options?.authToken,\n autoplay: options?.autoplay !== false,\n muted: options?.muted !== false,\n controls: options?.stockControls === true,\n poster: thumbnailUrl || undefined,\n debug: options?.debug,\n onStateChange: (playerState) => {\n onStateChange?.(playerState);\n },\n onError: (error) => {\n console.warn('[Player] Error:', error);\n },\n });\n\n // ============================================================================\n // Dev Mode Callbacks\n // ============================================================================\n const handleDevSettingsChange = useCallback((settings: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n }) => {\n // One-shot selection - controller handles the state\n setDevModeOptions({\n forcePlayer: settings.forcePlayer,\n forceType: settings.forceType,\n forceSource: settings.forceSource,\n });\n }, [setDevModeOptions]);\n\n const handleModeChange = useCallback((mode: PlaybackMode) => {\n setDevPlaybackMode(mode);\n // Mode is a persistent preference\n setDevModeOptions({ playbackMode: mode });\n }, [setDevModeOptions]);\n\n const handleReload = useCallback(() => {\n clearError();\n reload();\n }, [clearError, reload]);\n\n const handleStatsToggle = useCallback(() => {\n setIsStatsOpen(prev => !prev);\n }, []);\n\n // Clear skip indicator after animation\n const handleSkipIndicatorHide = useCallback(() => {\n setSkipDirection(null);\n }, []);\n\n // ============================================================================\n // Derived Values\n // ============================================================================\n const primaryEndpoint = state.endpoints?.primary as EndpointInfo | undefined;\n const isLegacyPlayer = state.currentPlayerInfo?.shortname === 'mist-legacy';\n const useStockControls = options?.stockControls === true || isLegacyPlayer;\n\n // Title overlay visibility: show on hover or when paused\n const showTitleOverlay = (state.isHovering || state.isPaused) &&\n !state.shouldShowIdleScreen && !state.isBuffering && !state.error;\n\n // Buffering spinner: only during active playback\n const showBufferingSpinner = !state.shouldShowIdleScreen &&\n state.isBuffering && !state.error && state.hasPlaybackStarted;\n\n // Click-to-play overlay support\n const supportsOverlay = false;\n\n // ============================================================================\n // Waiting for Endpoint (shown as overlay, not early return)\n // ============================================================================\n const showWaitingForEndpoint = !state.endpoints?.primary && state.state !== 'booting';\n const waitingMessage = options?.gatewayUrl\n ? (state.state === 'gateway_loading' ? 'Resolving viewing endpoint...' : 'Waiting for endpoint...')\n : 'Waiting for endpoint...';\n\n // ============================================================================\n // Render\n // ============================================================================\n return (\n <ContextMenu>\n <ContextMenuTrigger asChild>\n <div\n className={cn(\n \"fw-player-surface fw-player-root w-full h-full overflow-hidden\",\n options?.devMode && \"flex\"\n )}\n data-player-container=\"true\"\n tabIndex={0}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseMove={handleMouseMove}\n >\n {/* Player area */}\n <div className={cn(\n \"relative\",\n options?.devMode ? \"flex-1 min-w-0\" : \"w-full h-full\"\n )}>\n {/* Video container - PlayerController attaches here */}\n <div ref={containerRef} className=\"fw-player-container\" />\n\n {/* Title/Description overlay */}\n <TitleOverlay\n title={state.metadata?.title}\n description={state.metadata?.description}\n isVisible={showTitleOverlay}\n />\n\n {/* Stats panel */}\n <StatsPanel\n isOpen={isStatsOpen}\n onClose={handleStatsToggle}\n metadata={state.metadata}\n streamState={state.streamState?.isOnline ? {\n status: state.streamState.status,\n viewers: state.metadata?.viewers,\n tracks: state.streamState.streamInfo?.meta?.tracks\n ? Object.values(state.streamState.streamInfo.meta.tracks).map(t => ({\n type: t.type,\n codec: t.codec,\n width: t.width,\n height: t.height,\n bps: t.bps,\n }))\n : [],\n } : null}\n quality={state.playbackQuality}\n videoElement={state.videoElement}\n protocol={primaryEndpoint?.protocol}\n nodeId={primaryEndpoint?.nodeId}\n geoDistance={primaryEndpoint?.geoDistance}\n />\n\n {/* Dev Mode Panel toggle */}\n {options?.devMode && !isDevPanelOpen && (\n <DevModePanel\n onSettingsChange={handleDevSettingsChange}\n playbackMode={devPlaybackMode}\n onModeChange={handleModeChange}\n onReload={handleReload}\n streamInfo={state.streamInfo}\n mistStreamInfo={state.streamState?.streamInfo}\n currentPlayer={state.currentPlayerInfo}\n currentSource={state.currentSourceInfo}\n videoElement={state.videoElement}\n protocol={primaryEndpoint?.protocol}\n nodeId={primaryEndpoint?.nodeId}\n isVisible={false}\n isOpen={false}\n onOpenChange={setIsDevPanelOpen}\n />\n )}\n\n {/* Speed indicator */}\n {state.isHoldingSpeed && (\n <SpeedIndicator isVisible={true} speed={state.holdSpeed} />\n )}\n\n {/* Skip indicator */}\n <SkipIndicator\n direction={skipDirection}\n seconds={10}\n onHide={handleSkipIndicatorHide}\n />\n\n {/* Waiting for endpoint overlay */}\n {showWaitingForEndpoint && (\n <IdleScreen status=\"OFFLINE\" message={waitingMessage} />\n )}\n\n {/* Idle screen */}\n {!showWaitingForEndpoint && state.shouldShowIdleScreen && (\n <IdleScreen\n status={state.isEffectivelyLive ? state.streamState?.status : undefined}\n message={state.isEffectivelyLive ? state.streamState?.message : 'Loading video...'}\n percentage={state.isEffectivelyLive ? state.streamState?.percentage : undefined}\n />\n )}\n\n {/* Buffering spinner */}\n {showBufferingSpinner && (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"fw-player-surface absolute inset-0 flex items-center justify-center bg-black/40 backdrop-blur-sm z-20\"\n >\n <div className=\"flex items-center gap-3 rounded-lg border border-white/10 bg-black/70 px-4 py-3 text-sm text-white shadow-lg\">\n <div className=\"w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin\"></div>\n <span>Buffering...</span>\n </div>\n </div>\n )}\n\n {/* Error overlay */}\n {!state.shouldShowIdleScreen && state.error && (\n <div\n role=\"alert\"\n aria-live=\"assertive\"\n className={cn(\n \"fw-error-overlay\",\n state.isPassiveError ? \"fw-error-overlay--passive\" : \"fw-error-overlay--fullscreen\"\n )}\n >\n <div className={cn(\n \"fw-error-popup\",\n state.isPassiveError ? \"fw-error-popup--passive\" : \"fw-error-popup--fullscreen\"\n )}>\n <div className={cn(\n \"fw-error-header\",\n state.isPassiveError ? \"fw-error-header--warning\" : \"fw-error-header--error\"\n )}>\n <span className={cn(\n \"fw-error-title\",\n state.isPassiveError ? \"fw-error-title--warning\" : \"fw-error-title--error\"\n )}>\n {state.isPassiveError ? \"Warning\" : \"Error\"}\n </span>\n <button\n type=\"button\"\n className=\"fw-error-close\"\n onClick={clearError}\n aria-label=\"Dismiss\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M9 3L3 9M3 3L9 9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n </svg>\n </button>\n </div>\n <div className=\"fw-error-body\">\n <p className=\"fw-error-message\">Playback issue</p>\n </div>\n <div className=\"fw-error-actions\">\n <button\n type=\"button\"\n className=\"fw-error-btn\"\n aria-label=\"Retry playback\"\n onClick={() => { clearError(); retry(); }}\n >\n Retry\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Player controls */}\n {!useStockControls && (\n <PlayerControls\n currentTime={state.currentTime}\n duration={state.duration}\n isVisible={state.shouldShowControls}\n onSeek={(t) => controller?.seek(t)}\n showStatsButton={false}\n isStatsOpen={isStatsOpen}\n onStatsToggle={handleStatsToggle}\n mistStreamInfo={state.streamState?.streamInfo}\n disabled={!state.videoElement}\n playbackMode={devPlaybackMode}\n onModeChange={handleModeChange}\n sourceType={state.currentSourceInfo?.type}\n isContentLive={state.isEffectivelyLive}\n // Props from usePlayerController hook\n videoElement={state.videoElement}\n qualities={state.qualities}\n onSelectQuality={selectQuality}\n isMuted={state.isMuted}\n volume={state.volume}\n onVolumeChange={setVolume}\n onToggleMute={toggleMute}\n isPlaying={state.isPlaying}\n onTogglePlay={togglePlay}\n onToggleFullscreen={toggleFullscreen}\n isFullscreen={state.isFullscreen}\n isLoopEnabled={state.isLoopEnabled}\n onToggleLoop={toggleLoop}\n />\n )}\n </div>\n\n {/* Dev Mode Panel - side panel */}\n {options?.devMode && isDevPanelOpen && (\n <DevModePanel\n onSettingsChange={handleDevSettingsChange}\n playbackMode={devPlaybackMode}\n onModeChange={handleModeChange}\n onReload={handleReload}\n streamInfo={state.streamInfo}\n mistStreamInfo={state.streamState?.streamInfo}\n currentPlayer={state.currentPlayerInfo}\n currentSource={state.currentSourceInfo}\n videoElement={state.videoElement}\n protocol={primaryEndpoint?.protocol}\n nodeId={primaryEndpoint?.nodeId}\n isVisible={true}\n isOpen={true}\n onOpenChange={setIsDevPanelOpen}\n />\n )}\n </div>\n </ContextMenuTrigger>\n\n {/* Context menu */}\n <ContextMenuContent>\n <ContextMenuItem onClick={handleStatsToggle} className=\"gap-2\">\n <StatsIcon size={14} className=\"opacity-70 flex-shrink-0\" />\n <span>{isStatsOpen ? \"Hide Stats\" : \"Stats\"}</span>\n </ContextMenuItem>\n {options?.devMode && (\n <>\n <ContextMenuSeparator />\n <ContextMenuItem onClick={() => setIsDevPanelOpen(!isDevPanelOpen)} className=\"gap-2\">\n <SettingsIcon size={14} className=\"opacity-70 flex-shrink-0\" />\n <span>{isDevPanelOpen ? \"Hide Settings\" : \"Settings\"}</span>\n </ContextMenuItem>\n </>\n )}\n <ContextMenuSeparator />\n <ContextMenuItem onClick={togglePiP} className=\"gap-2\">\n <PictureInPictureIcon size={14} className=\"opacity-70 flex-shrink-0\" />\n <span>Picture-in-Picture</span>\n </ContextMenuItem>\n <ContextMenuItem onClick={toggleLoop} className=\"gap-2\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"opacity-70 flex-shrink-0\">\n <polyline points=\"17 1 21 5 17 9\"></polyline>\n <path d=\"M3 11V9a4 4 0 0 1 4-4h14\"></path>\n <polyline points=\"7 23 3 19 7 15\"></polyline>\n <path d=\"M21 13v2a4 4 0 0 1-4 4H3\"></path>\n </svg>\n <span>{state.isLoopEnabled ? \"Disable Loop\" : \"Enable Loop\"}</span>\n </ContextMenuItem>\n </ContextMenuContent>\n </ContextMenu>\n );\n};\n\n/**\n * Main Player component.\n *\n * Note: PlayerProvider is available if you need to use context-based access\n * across multiple components. PlayerInner manages its own PlayerController\n * via usePlayerController hook.\n */\nconst Player: React.FC<PlayerProps> = (props) => {\n return <PlayerInner {...props} />;\n};\n\nexport default Player;\n","import React, { useRef, useEffect, useState } from \"react\";\nimport DvdLogo from \"./DvdLogo\";\nimport logomarkAsset from \"../assets/logomark.svg\";\n\ninterface AnimatedBubbleProps {\n index: number;\n}\n\nconst AnimatedBubble: React.FC<AnimatedBubbleProps> = ({ index }) => {\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const [size, setSize] = useState(40);\n const [opacity, setOpacity] = useState(0);\n\n const getRandomPosition = () => ({\n top: Math.random() * 80 + 10, // 10% to 90%\n left: Math.random() * 80 + 10, // 10% to 90%\n });\n\n const getRandomSize = () => Math.random() * 60 + 30; // 30px to 90px\n\n useEffect(() => {\n // Initial random position and size\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n\n const animationCycle = () => {\n // Fade in\n setOpacity(0.15);\n\n setTimeout(() => {\n // Fade out\n setOpacity(0);\n\n setTimeout(() => {\n // Move to new random position with new size while invisible\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n // Start next cycle after a brief delay to ensure position change is complete\n setTimeout(() => {\n animationCycle();\n }, 200);\n }, 1500); // Wait for fade out to complete\n }, 4000 + Math.random() * 3000); // Stay visible for 4-7 seconds (was 2-4)\n };\n\n // Start the animation cycle with staggered timing\n const timeout = setTimeout(animationCycle, index * 500);\n\n return () => {\n clearTimeout(timeout);\n };\n }, [index]);\n\n // Tokyo Night inspired pastel colors\n const bubbleColors = [\n \"rgba(122, 162, 247, 0.2)\", // Terminal Blue\n \"rgba(187, 154, 247, 0.2)\", // Terminal Magenta\n \"rgba(158, 206, 106, 0.2)\", // Strings/CSS classes \n \"rgba(115, 218, 202, 0.2)\", // Terminal Green\n \"rgba(125, 207, 255, 0.2)\", // Terminal Cyan\n \"rgba(247, 118, 142, 0.2)\", // Keywords/Terminal Red\n \"rgba(224, 175, 104, 0.2)\", // Terminal Yellow\n \"rgba(42, 195, 222, 0.2)\", // Language functions\n ];\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: `${position.top}%`,\n left: `${position.left}%`,\n width: `${size}px`,\n height: `${size}px`,\n borderRadius: \"50%\",\n background: bubbleColors[index % bubbleColors.length],\n opacity: opacity,\n transition: \"opacity 1s ease-in-out\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n } as React.CSSProperties}\n />\n );\n};\n\ninterface CenterLogoProps {\n containerRef: React.RefObject<HTMLDivElement>;\n scale?: number;\n onHitmarker?: (e: { clientX: number; clientY: number }) => void;\n}\n\nconst CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHitmarker }) => {\n const [logoSize, setLogoSize] = useState(100);\n const [offset, setOffset] = useState({ x: 0, y: 0 });\n const [isHovered, setIsHovered] = useState(false);\n\n useEffect(() => {\n if (containerRef.current) {\n const containerWidth = containerRef.current.clientWidth;\n const containerHeight = containerRef.current.clientHeight;\n const minDimension = Math.min(containerWidth, containerHeight);\n setLogoSize(minDimension * scale);\n }\n }, [containerRef, scale]);\n\n const handleLogoClick = (e: React.MouseEvent) => {\n e.stopPropagation(); // Prevent event bubbling to container\n if (onHitmarker) {\n // Get the exact click position on the logo\n onHitmarker({ clientX: e.clientX, clientY: e.clientY });\n }\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n\n const mouseX = e.clientX;\n const mouseY = e.clientY;\n\n // Calculate distance from center\n const deltaX = mouseX - centerX;\n const deltaY = mouseY - centerY;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n // If mouse is close to logo, move it away\n const maxDistance = logoSize * 1.5; // Detection radius\n if (distance < maxDistance && distance > 0) {\n const pushStrength = (maxDistance - distance) / maxDistance;\n const pushDistance = 50 * pushStrength; // Max push distance\n\n // Normalize direction and apply push\n const pushX = -(deltaX / distance) * pushDistance;\n const pushY = -(deltaY / distance) * pushDistance;\n\n setOffset({ x: pushX, y: pushY });\n setIsHovered(true);\n } else {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n }\n };\n\n const handleMouseLeave = () => {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n };\n\n useEffect(() => {\n if (containerRef.current) {\n const container = containerRef.current;\n container.addEventListener('mousemove', handleMouseMove);\n container.addEventListener('mouseleave', handleMouseLeave);\n\n return () => {\n container.removeEventListener('mousemove', handleMouseMove);\n container.removeEventListener('mouseleave', handleMouseLeave);\n };\n }\n }, [logoSize, containerRef]);\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: `translate(-50%, -50%) translate(${offset.x}px, ${offset.y}px)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10,\n transition: \"transform 0.3s ease-out\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n }}\n >\n {/* Pulsing circle background */}\n <div\n style={{\n position: \"absolute\",\n width: `${logoSize * 1.4}px`,\n height: `${logoSize * 1.4}px`,\n borderRadius: \"50%\",\n background: \"rgba(122, 162, 247, 0.15)\",\n animation: isHovered ? \"logoPulse 1s ease-in-out infinite\" : \"logoPulse 3s ease-in-out infinite\",\n transform: isHovered ? \"scale(1.2)\" : \"scale(1)\",\n transition: \"transform 0.3s ease-out\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n pointerEvents: \"none\",\n }}\n />\n\n {/* Logo - only the SVG is clickable */}\n <img\n src={logomarkAsset}\n alt=\"FrameWorks Logo\"\n onClick={handleLogoClick}\n style={{\n width: `${logoSize}px`,\n height: `${logoSize}px`,\n position: \"relative\",\n zIndex: 1,\n filter: isHovered\n ? \"drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1)\"\n : \"drop-shadow(0 4px 8px rgba(36, 40, 59, 0.3))\",\n transform: isHovered ? \"scale(1.1)\" : \"scale(1)\",\n transition: \"all 0.3s ease-out\",\n cursor: isHovered ? \"pointer\" : \"default\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n WebkitUserDrag: \"none\",\n WebkitTouchCallout: \"none\",\n } as React.CSSProperties}\n />\n </div>\n );\n};\n\ninterface LoadingScreenProps {\n message?: string;\n}\n\ninterface Hitmarker {\n id: number;\n x: number;\n y: number;\n}\n\nconst LoadingScreen: React.FC<LoadingScreenProps> = ({ message = \"Waiting for source...\" }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [hitmarkers, setHitmarkers] = useState<Hitmarker[]>([]);\n\n const playHitmarkerSound = () => {\n try {\n // Embedded hitmarker sound as base64 data URL\n const hitmarkerDataUrl = 'data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA' +\n 'AAD/+1QAAAAAAAAAAAAAAAAAAAAA' +\n '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' +\n 'qqqqqqqqqqqqqqqqqqqqqqqqqqo=';\n \n const audio = new Audio(hitmarkerDataUrl);\n audio.volume = 0.3;\n audio.play().catch(() => {\n // Fallback to synthetic sound if data URL fails\n createSyntheticHitmarkerSound();\n });\n } catch (error) {\n // Fallback to synthetic sound\n createSyntheticHitmarkerSound();\n }\n };\n\n const createSyntheticHitmarkerSound = () => {\n try {\n const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\n \n // Create a more realistic hitmarker sound with noise and metallic ring\n const oscillator1 = audioContext.createOscillator();\n const oscillator2 = audioContext.createOscillator();\n const noiseBuffer = audioContext.createBuffer(1, audioContext.sampleRate * 0.1, audioContext.sampleRate);\n const noiseSource = audioContext.createBufferSource();\n \n // Generate white noise for the initial \"crack\"\n const noiseData = noiseBuffer.getChannelData(0);\n for (let i = 0; i < noiseData.length; i++) {\n noiseData[i] = Math.random() * 2 - 1;\n }\n noiseSource.buffer = noiseBuffer;\n \n const gainNode1 = audioContext.createGain();\n const gainNode2 = audioContext.createGain();\n const noiseGain = audioContext.createGain();\n const masterGain = audioContext.createGain();\n \n // Connect everything\n oscillator1.connect(gainNode1);\n oscillator2.connect(gainNode2);\n noiseSource.connect(noiseGain);\n \n gainNode1.connect(masterGain);\n gainNode2.connect(masterGain);\n noiseGain.connect(masterGain);\n masterGain.connect(audioContext.destination);\n \n // Sharp metallic frequencies\n oscillator1.frequency.setValueAtTime(1800, audioContext.currentTime);\n oscillator1.frequency.exponentialRampToValueAtTime(900, audioContext.currentTime + 0.08);\n \n oscillator2.frequency.setValueAtTime(3600, audioContext.currentTime);\n oscillator2.frequency.exponentialRampToValueAtTime(1800, audioContext.currentTime + 0.04);\n \n oscillator1.type = 'triangle';\n oscillator2.type = 'sine';\n \n // Sharp attack, quick decay\n gainNode1.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode1.gain.linearRampToValueAtTime(0.4, audioContext.currentTime + 0.002);\n gainNode1.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.12);\n \n gainNode2.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode2.gain.linearRampToValueAtTime(0.3, audioContext.currentTime + 0.001);\n gainNode2.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.06);\n \n // Noise burst for the initial crack\n noiseGain.gain.setValueAtTime(0, audioContext.currentTime);\n noiseGain.gain.linearRampToValueAtTime(0.2, audioContext.currentTime + 0.001);\n noiseGain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.01);\n \n masterGain.gain.setValueAtTime(0.5, audioContext.currentTime);\n \n const startTime = audioContext.currentTime;\n const stopTime = startTime + 0.15;\n \n oscillator1.start(startTime);\n oscillator2.start(startTime);\n noiseSource.start(startTime);\n \n oscillator1.stop(stopTime);\n oscillator2.stop(stopTime);\n noiseSource.stop(startTime + 0.02);\n \n } catch (error) {\n console.log('Audio context not available');\n }\n };\n\n const createHitmarker = (e: { clientX: number; clientY: number }) => {\n if (!containerRef.current) return;\n \n const rect = containerRef.current.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n const newHitmarker: Hitmarker = {\n id: Date.now() + Math.random(),\n x,\n y,\n };\n \n setHitmarkers(prev => [...prev, newHitmarker]);\n \n // Play sound\n playHitmarkerSound();\n \n // Remove hitmarker after animation\n setTimeout(() => {\n setHitmarkers(prev => prev.filter(h => h.id !== newHitmarker.id));\n }, 600);\n };\n\n // Inject CSS animations\n useEffect(() => {\n const styleId = 'loading-screen-animations';\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes fadeInOut {\n 0%, 100% {\n opacity: 0.6;\n }\n 50% {\n opacity: 0.9;\n }\n }\n\n @keyframes logoPulse {\n 0%, 100% {\n opacity: 0.15;\n transform: scale(1);\n }\n 50% {\n opacity: 0.25;\n transform: scale(1.05);\n }\n }\n\n @keyframes shimmer {\n 0% {\n background-position: -200px 0;\n }\n 100% {\n background-position: calc(200px + 100%) 0;\n }\n }\n\n @keyframes floatUp {\n 0% {\n transform: translateY(100vh) rotate(0deg);\n opacity: 0;\n }\n 10% {\n opacity: 0.6;\n }\n 90% {\n opacity: 0.6;\n }\n 100% {\n transform: translateY(-100px) rotate(360deg);\n opacity: 0;\n }\n }\n\n @keyframes gradientShift {\n 0%, 100% {\n background-position: 0% 50%;\n }\n 50% {\n background-position: 100% 50%;\n }\n }\n\n @keyframes hitmarkerFade {\n 0% {\n opacity: 1;\n transform: scale(0.5);\n }\n 20% {\n opacity: 1;\n transform: scale(1.2);\n }\n 100% {\n opacity: 0;\n transform: scale(1);\n }\n }\n\n @keyframes hitmarkerFade45 {\n 0% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(45deg) scale(0.5);\n }\n 20% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(45deg) scale(1.2);\n }\n 100% {\n opacity: 0;\n transform: translate(-50%, -50%) rotate(45deg) scale(1);\n }\n }\n\n @keyframes hitmarkerFadeNeg45 {\n 0% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(-45deg) scale(0.5);\n }\n 20% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(-45deg) scale(1.2);\n }\n 100% {\n opacity: 0;\n transform: translate(-50%, -50%) rotate(-45deg) scale(1);\n }\n }\n `;\n document.head.appendChild(style);\n }\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"fw-player-root\"\n style={{\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n minHeight: \"300px\",\n background: `\n linear-gradient(135deg,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,\n hsl(var(--tn-bg, 233 23% 17%)) 25%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,\n hsl(var(--tn-bg, 233 23% 17%)) 75%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 100%\n )\n `,\n backgroundSize: \"400% 400%\",\n animation: \"gradientShift 16s ease-in-out infinite\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderRadius: \"0\", /* Slab - no rounded corners */\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n } as React.CSSProperties}\n >\n {/* Hitmarkers */}\n {hitmarkers.map(hitmarker => (\n <div\n key={hitmarker.id}\n style={{\n position: \"absolute\",\n left: `${hitmarker.x}px`,\n top: `${hitmarker.y}px`,\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\",\n zIndex: 100,\n width: \"40px\",\n height: \"40px\",\n }}\n >\n {/* Top-left diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"25%\",\n left: \"25%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(45deg)\",\n animation: \"hitmarkerFade45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n {/* Top-right diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"25%\",\n left: \"75%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(-45deg)\",\n animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n {/* Bottom-left diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"75%\",\n left: \"25%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(-45deg)\",\n animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n {/* Bottom-right diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"75%\",\n left: \"75%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(45deg)\",\n animation: \"hitmarkerFade45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n </div>\n ))}\n\n {/* Floating particles */}\n {[...Array(12)].map((_, index) => (\n <div\n key={`particle-${index}`}\n style={{\n position: \"absolute\",\n left: `${Math.random() * 100}%`,\n width: `${Math.random() * 4 + 2}px`,\n height: `${Math.random() * 4 + 2}px`,\n borderRadius: \"50%\",\n background: [\n \"#7aa2f7\", // Terminal Blue\n \"#bb9af7\", // Terminal Magenta \n \"#9ece6a\", // Strings/CSS classes\n \"#73daca\", // Terminal Green\n \"#7dcfff\", // Terminal Cyan\n \"#f7768e\", // Keywords/Terminal Red\n \"#e0af68\", // Terminal Yellow\n \"#2ac3de\", // Language functions\n ][index % 8],\n opacity: 0,\n animation: `floatUp ${8 + Math.random() * 4}s linear infinite`,\n animationDelay: `${Math.random() * 8}s`,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n ))}\n\n {/* Animated bubbles with Tokyo Night colors */}\n {[...Array(8)].map((_, index) => (\n <AnimatedBubble key={index} index={index} />\n ))}\n\n {/* Center logo */}\n <CenterLogo containerRef={containerRef as React.RefObject<HTMLDivElement>} onHitmarker={createHitmarker} />\n\n {/* Bouncing DVD Logo */}\n <DvdLogo parentRef={containerRef as React.RefObject<HTMLDivElement>} scale={0.08} />\n\n {/* Message */}\n <div\n style={{\n position: \"absolute\",\n bottom: \"20%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n color: \"#a9b1d6\",\n fontSize: \"16px\",\n fontWeight: \"500\",\n textAlign: \"center\",\n animation: \"fadeInOut 2s ease-in-out infinite\",\n textShadow: \"0 2px 4px rgba(36, 40, 59, 0.5)\",\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n pointerEvents: \"none\",\n }}\n >\n {message}\n </div>\n\n {/* Subtle overlay texture */}\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: `\n radial-gradient(circle at 20% 80%, rgba(122, 162, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(187, 154, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(158, 206, 106, 0.02) 0%, transparent 50%)\n `,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n </div>\n );\n};\n\nexport default LoadingScreen; \n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n outline: \"border border-border bg-transparent hover:bg-accent hover:text-accent-foreground\",\n destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n subtle: \"bg-muted text-muted-foreground hover:bg-muted/80\",\n link: \"text-primary underline-offset-4 hover:underline\"\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-9 w-9\"\n }\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\"\n }\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;\n }\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import React from 'react';\nimport type { StreamStatus } from '../types';\n\nexport interface StreamStateOverlayProps {\n /** Current stream status */\n status: StreamStatus;\n /** Human-readable message */\n message: string;\n /** Processing percentage (for INITIALIZING state) */\n percentage?: number;\n /** Callback for retry button */\n onRetry?: () => void;\n /** Whether to show the overlay */\n visible?: boolean;\n /** Additional className */\n className?: string;\n}\n\n/**\n * Get status icon based on stream state\n */\nfunction StatusIcon({ status }: { status: StreamStatus }) {\n const iconClass = \"w-5 h-5\";\n\n switch (status) {\n case 'ONLINE':\n return (\n <svg className={`${iconClass} fw-status-online`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n );\n\n case 'OFFLINE':\n return (\n <svg className={`${iconClass} fw-status-offline`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414\" />\n </svg>\n );\n\n case 'INITIALIZING':\n case 'BOOTING':\n case 'WAITING_FOR_DATA':\n return (\n <svg className={`${iconClass} fw-status-warning animate-spin`} fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n );\n\n case 'SHUTTING_DOWN':\n return (\n <svg className={`${iconClass} fw-status-warning`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n );\n\n case 'ERROR':\n case 'INVALID':\n default:\n return (\n <svg className={`${iconClass} fw-status-offline`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n );\n }\n}\n\n/**\n * Get status label for header\n */\nfunction getStatusLabel(status: StreamStatus): string {\n switch (status) {\n case 'ONLINE': return 'ONLINE';\n case 'OFFLINE': return 'OFFLINE';\n case 'INITIALIZING': return 'INITIALIZING';\n case 'BOOTING': return 'STARTING';\n case 'WAITING_FOR_DATA': return 'WAITING';\n case 'SHUTTING_DOWN': return 'ENDING';\n case 'ERROR': return 'ERROR';\n case 'INVALID': return 'INVALID';\n default: return 'STATUS';\n }\n}\n\n/**\n * StreamStateOverlay - Shows stream status when not playable\n *\n * Slab-based design with header/body/actions zones.\n * Uses Tokyo Night color palette and seam-based layout.\n */\nexport const StreamStateOverlay: React.FC<StreamStateOverlayProps> = ({\n status,\n message,\n percentage,\n onRetry,\n visible = true,\n className = '',\n}) => {\n if (!visible || status === 'ONLINE') {\n return null;\n }\n\n const showRetry = status === 'ERROR' || status === 'INVALID' || status === 'OFFLINE';\n const showProgress = status === 'INITIALIZING' && percentage !== undefined;\n\n return (\n <div\n className={`absolute inset-0 z-20 flex items-center justify-center ${className}`}\n style={{ backgroundColor: 'hsl(var(--tn-bg-dark) / 0.8)', backdropFilter: 'blur(4px)' }}\n role=\"status\"\n aria-live=\"polite\"\n >\n {/* Slab container - no rounded corners, seam borders */}\n <div\n className=\"fw-slab w-[280px] max-w-[90%]\"\n style={{ backgroundColor: 'hsl(var(--tn-bg) / 0.95)' }}\n >\n {/* Slab header - status label with icon */}\n <div className=\"fw-slab-header flex items-center gap-2\">\n <StatusIcon status={status} />\n <span>{getStatusLabel(status)}</span>\n </div>\n\n {/* Slab body - message and progress */}\n <div className=\"fw-slab-body\">\n <p className=\"text-sm\" style={{ color: 'hsl(var(--tn-fg))' }}>\n {message}\n </p>\n\n {showProgress && (\n <div className=\"mt-3\">\n {/* Progress bar - no rounded corners */}\n <div\n className=\"h-1.5 w-full overflow-hidden\"\n style={{ backgroundColor: 'hsl(var(--tn-bg-visual))' }}\n >\n <div\n className=\"h-full transition-all duration-300\"\n style={{\n width: `${Math.min(100, percentage)}%`,\n backgroundColor: 'hsl(var(--tn-yellow))',\n }}\n />\n </div>\n <p\n className=\"mt-1.5 text-xs font-mono\"\n style={{ color: 'hsl(var(--tn-fg-dark))' }}\n >\n {Math.round(percentage)}%\n </p>\n </div>\n )}\n\n {status === 'OFFLINE' && (\n <p className=\"mt-2 text-xs\" style={{ color: 'hsl(var(--tn-fg-dark))' }}>\n The stream will start when the broadcaster goes live\n </p>\n )}\n\n {(status === 'BOOTING' || status === 'WAITING_FOR_DATA') && (\n <p className=\"mt-2 text-xs\" style={{ color: 'hsl(var(--tn-fg-dark))' }}>\n Please wait while the stream prepares...\n </p>\n )}\n\n {/* Polling indicator for non-error states */}\n {!showRetry && (\n <div\n className=\"mt-3 flex items-center gap-2 text-xs\"\n style={{ color: 'hsl(var(--tn-fg-dark))' }}\n >\n <span\n className=\"h-1.5 w-1.5 animate-pulse\"\n style={{ backgroundColor: 'hsl(var(--tn-cyan))' }}\n />\n <span>Checking stream status...</span>\n </div>\n )}\n </div>\n\n {/* Slab actions - flush retry button */}\n {showRetry && onRetry && (\n <div className=\"fw-slab-actions\">\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"fw-btn-flush py-2.5 text-xs font-medium uppercase tracking-wide\"\n style={{ color: 'hsl(var(--tn-blue))' }}\n aria-label=\"Retry connection\"\n >\n Retry Connection\n </button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default StreamStateOverlay;\n","import React, { Component, ErrorInfo, ReactNode } from 'react';\nimport { Button } from '../ui/button';\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n onRetry?: () => void;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary to catch and handle player errors gracefully.\n * Prevents player errors from crashing the parent application.\n */\nclass PlayerErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n console.error('[PlayerErrorBoundary] Caught error:', error, errorInfo);\n this.props.onError?.(error, errorInfo);\n }\n\n handleRetry = (): void => {\n this.setState({ hasError: false, error: null });\n this.props.onRetry?.();\n };\n\n render(): ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div className=\"fw-player-error flex min-h-[280px] flex-col items-center justify-center gap-4 rounded-xl bg-slate-950 p-6 text-center text-white\">\n <div className=\"text-lg font-semibold text-red-400\">\n Playback Error\n </div>\n <p className=\"max-w-sm text-sm text-slate-400\">\n {this.state.error?.message || 'An unexpected error occurred while loading the player.'}\n </p>\n <Button\n type=\"button\"\n variant=\"secondary\"\n onClick={this.handleRetry}\n className=\"mt-2\"\n >\n Try Again\n </Button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\nexport default PlayerErrorBoundary;\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-full border border-transparent px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ring-offset-background\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n outline: \"border-border text-foreground\"\n }\n },\n defaultVariants: {\n variant: \"default\"\n }\n }\n);\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return <div className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","import { useEffect, useState, useRef, useCallback } from 'react';\nimport type {\n UseStreamStateOptions,\n StreamState,\n StreamStatus,\n MistStreamInfo,\n} from '../types';\n\n/**\n * Parse MistServer error string into StreamStatus enum\n */\nfunction parseErrorToStatus(error: string): StreamStatus {\n const lowerError = error.toLowerCase();\n\n if (lowerError.includes('offline')) return 'OFFLINE';\n if (lowerError.includes('initializing')) return 'INITIALIZING';\n if (lowerError.includes('booting')) return 'BOOTING';\n if (lowerError.includes('waiting for data')) return 'WAITING_FOR_DATA';\n if (lowerError.includes('shutting down')) return 'SHUTTING_DOWN';\n if (lowerError.includes('invalid')) return 'INVALID';\n\n return 'ERROR';\n}\n\n/**\n * Get human-readable message for stream status\n */\nfunction getStatusMessage(status: StreamStatus, percentage?: number): string {\n switch (status) {\n case 'ONLINE':\n return 'Stream is online';\n case 'OFFLINE':\n return 'Stream is offline';\n case 'INITIALIZING':\n return percentage !== undefined\n ? `Initializing... ${Math.round(percentage * 10) / 10}%`\n : 'Stream is initializing';\n case 'BOOTING':\n return 'Stream is starting up';\n case 'WAITING_FOR_DATA':\n return 'Waiting for stream data';\n case 'SHUTTING_DOWN':\n return 'Stream is shutting down';\n case 'INVALID':\n return 'Stream status is invalid';\n case 'ERROR':\n default:\n return 'Stream error';\n }\n}\n\n/**\n * Initial stream state\n */\nconst initialState: StreamState = {\n status: 'OFFLINE',\n isOnline: false,\n message: 'Connecting...',\n lastUpdate: 0,\n};\n\n/**\n * Hook to poll MistServer for stream status via WebSocket or HTTP\n *\n * Uses native MistServer protocol:\n * - WebSocket: ws://{baseUrl}/json_{streamName}.js\n * - HTTP fallback: GET {baseUrl}/json_{streamName}.js\n *\n * @example\n * ```tsx\n * const { status, isOnline, message } = useStreamState({\n * mistBaseUrl: 'https://mist.example.com',\n * streamName: 'my-stream',\n * pollInterval: 3000,\n * });\n * ```\n */\nexport interface UseStreamStateReturn extends StreamState {\n /** Manual refetch function */\n refetch: () => void;\n /** WebSocket reference for sharing with MistReporter */\n socketRef: React.RefObject<WebSocket | null>;\n /** True when WebSocket is connected and ready (triggers re-render) */\n socketReady: boolean;\n}\n\nexport function useStreamState(options: UseStreamStateOptions): UseStreamStateReturn {\n const {\n mistBaseUrl,\n streamName,\n pollInterval = 3000,\n enabled = true,\n useWebSocket = true,\n debug = false,\n } = options;\n\n const [state, setState] = useState<StreamState>(initialState);\n const [socketReady, setSocketReady] = useState(false);\n const wsRef = useRef<WebSocket | null>(null);\n const pollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wsTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const mountedRef = useRef(true);\n\n // MistPlayer-style WebSocket timeout (5 seconds)\n const WS_TIMEOUT_MS = 5000;\n\n /**\n * Process MistServer response data\n */\n const processStreamInfo = useCallback((data: MistStreamInfo) => {\n if (!mountedRef.current) return;\n\n if (data.error) {\n // Stream has an error state - preserve previous streamInfo (track data)\n const status = parseErrorToStatus(data.error);\n const message = data.on_error || getStatusMessage(status, data.perc);\n\n setState(prev => ({\n status,\n isOnline: false,\n message,\n percentage: data.perc,\n lastUpdate: Date.now(),\n error: data.error,\n streamInfo: prev.streamInfo, // Preserve track data through error states\n }));\n } else {\n // Stream is online with valid metadata\n // Merge new data with existing streamInfo to preserve source/tracks from initial fetch\n // WebSocket updates may not include source array - only status updates\n setState(prev => {\n const mergedStreamInfo: MistStreamInfo = {\n ...prev.streamInfo, // Keep existing source/meta if present\n ...data, // Override with new data\n // Explicitly preserve source if not in new data\n source: data.source || prev.streamInfo?.source,\n // Merge meta to preserve tracks\n meta: {\n ...prev.streamInfo?.meta,\n ...data.meta,\n // Preserve tracks if not in new data\n tracks: data.meta?.tracks || prev.streamInfo?.meta?.tracks,\n },\n };\n\n return {\n status: 'ONLINE',\n isOnline: true,\n message: 'Stream is online',\n lastUpdate: Date.now(),\n streamInfo: mergedStreamInfo,\n };\n });\n }\n }, []);\n\n /**\n * HTTP polling fallback\n * Adds metaeverywhere=1 and inclzero=1 like MistPlayer\n */\n const pollHttp = useCallback(async () => {\n if (!mountedRef.current || !enabled) return;\n\n try {\n // Build URL with MistPlayer-style params\n const baseUrl = `${mistBaseUrl.replace(/\\/$/, '')}/json_${encodeURIComponent(streamName)}.js`;\n const url = `${baseUrl}?metaeverywhere=1&inclzero=1`;\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n // MistServer returns JSON with potential JSONP wrapper\n let text = await response.text();\n // Strip JSONP callback if present (use [\\s\\S]* instead of /s flag for ES5 compat)\n const jsonpMatch = text.match(/^[^(]+\\(([\\s\\S]*)\\);?$/);\n if (jsonpMatch) {\n text = jsonpMatch[1];\n }\n\n const data = JSON.parse(text) as MistStreamInfo;\n processStreamInfo(data);\n } catch (error) {\n if (!mountedRef.current) return;\n\n setState(prev => ({\n ...prev,\n status: 'ERROR',\n isOnline: false,\n message: error instanceof Error ? error.message : 'Connection failed',\n lastUpdate: Date.now(),\n error: error instanceof Error ? error.message : 'Unknown error',\n }));\n }\n\n // Schedule next poll\n if (mountedRef.current && enabled && !useWebSocket) {\n pollTimeoutRef.current = setTimeout(pollHttp, pollInterval);\n }\n }, [mistBaseUrl, streamName, enabled, useWebSocket, pollInterval, processStreamInfo]);\n\n /**\n * WebSocket connection with MistPlayer-style 5-second timeout\n */\n const connectWebSocket = useCallback(() => {\n if (!mountedRef.current || !enabled || !useWebSocket) return;\n\n // Clean up existing connection and timeout\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n if (wsRef.current) {\n wsRef.current.close();\n wsRef.current = null;\n }\n\n try {\n // Convert http(s) to ws(s)\n const wsUrl = mistBaseUrl\n .replace(/^http:/, 'ws:')\n .replace(/^https:/, 'wss:')\n .replace(/\\/$/, '');\n\n // Build URL with MistPlayer-style params\n const url = `${wsUrl}/json_${encodeURIComponent(streamName)}.js?metaeverywhere=1&inclzero=1`;\n const ws = new WebSocket(url);\n wsRef.current = ws;\n\n // MistPlayer-style timeout: if no message within 5 seconds, fall back to HTTP\n wsTimeoutRef.current = setTimeout(() => {\n if (ws.readyState <= WebSocket.OPEN) {\n if (debug) {\n console.debug('[useStreamState] WebSocket timeout (5s), falling back to HTTP polling');\n }\n ws.close();\n pollHttp();\n }\n }, WS_TIMEOUT_MS);\n\n ws.onopen = () => {\n if (debug) {\n console.debug('[useStreamState] WebSocket connected');\n }\n setSocketReady(true);\n };\n\n ws.onmessage = (event) => {\n // Clear timeout on first message\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n\n try {\n const data = JSON.parse(event.data) as MistStreamInfo;\n processStreamInfo(data);\n } catch (e) {\n console.warn('[useStreamState] Failed to parse WebSocket message:', e);\n }\n };\n\n ws.onerror = (event) => {\n console.warn('[useStreamState] WebSocket error, falling back to HTTP polling');\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n ws.close();\n };\n\n ws.onclose = () => {\n wsRef.current = null;\n setSocketReady(false);\n\n if (!mountedRef.current || !enabled) return;\n\n // Fallback to HTTP polling or reconnect\n if (debug) {\n console.debug('[useStreamState] WebSocket closed, starting HTTP polling');\n }\n pollHttp();\n };\n } catch (error) {\n console.warn('[useStreamState] WebSocket connection failed:', error);\n // Fallback to HTTP polling\n pollHttp();\n }\n }, [mistBaseUrl, streamName, enabled, useWebSocket, debug, processStreamInfo, pollHttp]);\n\n /**\n * Manual refetch function\n */\n const refetch = useCallback(() => {\n if (useWebSocket && wsRef.current?.readyState === WebSocket.OPEN) {\n // WebSocket will receive updates automatically\n return;\n }\n pollHttp();\n }, [useWebSocket, pollHttp]);\n\n /**\n * Setup connection on mount and when options change\n * Always do initial HTTP poll to get full stream info (including sources),\n * then connect WebSocket for real-time status updates.\n * MistServer WebSocket updates may not include source array.\n */\n useEffect(() => {\n mountedRef.current = true;\n\n if (!enabled || !mistBaseUrl || !streamName) {\n setState(initialState);\n return;\n }\n\n // Reset state when stream changes\n setState({\n ...initialState,\n message: 'Connecting...',\n lastUpdate: Date.now(),\n });\n\n // Always do initial HTTP poll to get full data (including sources)\n // Then connect WebSocket for real-time updates\n const initializeConnection = async () => {\n // First HTTP poll to get complete stream info\n await pollHttp();\n\n // Then connect WebSocket for status updates (if enabled)\n if (useWebSocket && mountedRef.current) {\n connectWebSocket();\n }\n };\n\n initializeConnection();\n\n return () => {\n // Set mounted=false FIRST before any other cleanup\n mountedRef.current = false;\n if (debug) {\n console.debug('[useStreamState] cleanup starting, mountedRef set to false');\n }\n\n // Cleanup WebSocket timeout\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n\n // Cleanup WebSocket - remove handlers BEFORE closing to prevent onclose callback\n if (wsRef.current) {\n // Detach handlers first to prevent onclose from triggering pollHttp\n wsRef.current.onclose = null;\n wsRef.current.onerror = null;\n wsRef.current.onmessage = null;\n wsRef.current.onopen = null;\n wsRef.current.close();\n wsRef.current = null;\n }\n\n // Cleanup polling timeout\n if (pollTimeoutRef.current) {\n clearTimeout(pollTimeoutRef.current);\n pollTimeoutRef.current = null;\n }\n };\n }, [enabled, mistBaseUrl, streamName, useWebSocket, debug, connectWebSocket, pollHttp]);\n\n return {\n ...state,\n refetch,\n socketRef: wsRef,\n socketReady,\n };\n}\n\nexport default useStreamState;\n","import { useEffect, useState, useRef } from 'react';\nimport type { ContentType } from '@livepeer-frameworks/player-core';\nimport type { ContentEndpoints } from '../types';\n\nconst MAX_RETRIES = 3;\nconst INITIAL_DELAY_MS = 500;\n\ninterface Params {\n gatewayUrl: string;\n contentType: ContentType;\n contentId: string;\n authToken?: string;\n}\n\nasync function fetchWithRetry(\n url: string,\n options: RequestInit,\n maxRetries: number = MAX_RETRIES,\n initialDelay: number = INITIAL_DELAY_MS\n): Promise<Response> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n return response;\n } catch (e) {\n lastError = e instanceof Error ? e : new Error('Fetch failed');\n\n // Don't retry on abort\n if (options.signal?.aborted) {\n throw lastError;\n }\n\n // Wait before retrying (exponential backoff)\n if (attempt < maxRetries - 1) {\n const delay = initialDelay * Math.pow(2, attempt);\n console.warn(`[useViewerEndpoints] Retry ${attempt + 1}/${maxRetries - 1} after ${delay}ms`);\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n throw lastError ?? new Error('Gateway unreachable after retries');\n}\n\nexport function useViewerEndpoints({ gatewayUrl, contentType, contentId, authToken }: Params) {\n const [endpoints, setEndpoints] = useState<ContentEndpoints | null>(null);\n const [status, setStatus] = useState<'idle' | 'loading' | 'ready' | 'error'>('idle');\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => {\n if (!gatewayUrl || !contentType || !contentId) return;\n setStatus('loading');\n setError(null);\n abortRef.current?.abort();\n const ac = new AbortController();\n abortRef.current = ac;\n\n (async () => {\n try {\n const graphqlEndpoint = gatewayUrl.replace(/\\/$/, '');\n const query = `\n query ResolveViewer($contentType: String!, $contentId: String!) {\n resolveViewerEndpoint(contentType: $contentType, contentId: $contentId) {\n primary { nodeId baseUrl protocol url geoDistance loadScore outputs }\n fallbacks { nodeId baseUrl protocol url geoDistance loadScore outputs }\n metadata { contentType contentId title description durationSeconds status isLive viewers recordingSizeBytes clipSource createdAt }\n }\n }\n `;\n const res = await fetchWithRetry(graphqlEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n },\n body: JSON.stringify({ query, variables: { contentType, contentId } }),\n signal: ac.signal,\n });\n if (!res.ok) throw new Error(`Gateway GQL error ${res.status}`);\n const payload = await res.json();\n if (payload.errors?.length) throw new Error(payload.errors[0]?.message || 'GraphQL error');\n const resp = payload.data?.resolveViewerEndpoint;\n const primary = resp?.primary;\n const fallbacks = Array.isArray(resp?.fallbacks) ? resp.fallbacks : [];\n if (!primary) throw new Error('No endpoints');\n\n // Parse outputs JSON string (GraphQL returns JSON scalar as string)\n if (primary.outputs && typeof primary.outputs === 'string') {\n try { primary.outputs = JSON.parse(primary.outputs); } catch {}\n }\n if (fallbacks) {\n fallbacks.forEach((fb: any) => {\n if (fb.outputs && typeof fb.outputs === 'string') {\n try { fb.outputs = JSON.parse(fb.outputs); } catch {}\n }\n });\n }\n\n setEndpoints({ primary, fallbacks, metadata: resp?.metadata });\n setStatus('ready');\n } catch (e) {\n if (ac.signal.aborted) return;\n const message = e instanceof Error ? e.message : 'Unknown gateway error';\n console.error('[useViewerEndpoints] Gateway resolution failed:', message);\n setError(message);\n setStatus('error');\n }\n })();\n\n return () => ac.abort();\n }, [gatewayUrl, contentType, contentId, authToken]);\n\n return { endpoints, status, error };\n}\n\nexport default useViewerEndpoints;\n\n","import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\nimport { Button } from \"../ui/button\";\nimport type { ThumbnailOverlayProps } from \"../types\";\n\nconst ThumbnailOverlay: React.FC<ThumbnailOverlayProps> = ({\n thumbnailUrl,\n onPlay,\n message,\n showUnmuteMessage = false,\n style,\n className\n}) => {\n const handleClick = (e: React.MouseEvent | React.KeyboardEvent) => {\n e.stopPropagation();\n onPlay?.();\n };\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick(event);\n }\n }}\n style={style}\n className={cn(\n \"fw-player-thumbnail relative flex h-full min-h-[280px] w-full cursor-pointer items-center justify-center overflow-hidden rounded-xl bg-slate-950 text-foreground outline-none transition focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n , className)}\n >\n {thumbnailUrl && (\n <div\n className=\"absolute inset-0 bg-cover bg-center\"\n style={{ backgroundImage: `url(${thumbnailUrl})` }}\n />\n )}\n\n <div\n className={cn(\n \"absolute inset-0 bg-slate-950/70\",\n !thumbnailUrl && \"bg-gradient-to-br from-slate-900 via-slate-950 to-slate-900\"\n )}\n />\n\n <div className=\"relative z-10 flex max-w-[320px] flex-col items-center gap-4 px-6 text-center text-sm sm:gap-6\">\n {showUnmuteMessage ? (\n <div className=\"w-full rounded-lg border border-white/15 bg-black/80 p-4 text-sm text-white shadow-lg backdrop-blur\">\n <div className=\"mb-1 flex items-center justify-center gap-2 text-base font-semibold text-primary\">\n <span aria-hidden=\"true\">🔇</span> Click to unmute\n </div>\n <p className=\"text-xs text-white/80\">Stream is playing muted — tap to enable sound.</p>\n </div>\n ) : (\n <>\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n className=\"h-20 w-20 rounded-full bg-primary/90 text-primary-foreground shadow-lg shadow-primary/40 transition hover:bg-primary focus-visible:bg-primary\"\n aria-label=\"Play stream\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"ml-0.5 h-8 w-8\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n </Button>\n <div className=\"w-full rounded-lg border border-white/10 bg-black/70 p-5 text-white shadow-inner backdrop-blur\">\n <p className=\"text-base font-semibold text-primary\">\n {message ?? \"Click to play\"}\n </p>\n <p className=\"mt-1 text-xs text-white/70\">\n {message ? \"Start streaming instantly\" : \"Jump into the live feed\"}\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n );\n};\n\nexport default ThumbnailOverlay;\n","import { useEffect, useState, useRef, useCallback } from 'react';\nimport { MetaTrackManager, type MetaTrackSubscription, type MetaTrackEvent } from '@livepeer-frameworks/player-core';\nimport type { UseMetaTrackOptions } from '../types';\n\nexport interface UseMetaTrackReturn {\n /** Whether connected to MistServer WebSocket */\n isConnected: boolean;\n /** Connection state */\n connectionState: 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n /** List of subscribed track IDs */\n subscribedTracks: string[];\n /** Subscribe to a meta track */\n subscribe: (trackId: string, callback: (event: MetaTrackEvent) => void) => () => void;\n /** Unsubscribe from a meta track */\n unsubscribe: (trackId: string, callback: (event: MetaTrackEvent) => void) => void;\n /** Manually connect */\n connect: () => void;\n /** Manually disconnect */\n disconnect: () => void;\n /** Update playback time for timed event dispatch (call on video timeupdate) */\n setPlaybackTime: (timeInSeconds: number) => void;\n /** Handle seek event (call on video seeking/seeked) */\n onSeek: (newTimeInSeconds: number) => void;\n}\n\n/**\n * Hook for subscribing to real-time metadata from MistServer\n *\n * Uses native MistServer WebSocket protocol for low-latency metadata delivery:\n * - Subtitles/captions\n * - Live scores\n * - Timed events\n * - Chapter markers\n *\n * @example\n * ```tsx\n * const { isConnected, subscribe } = useMetaTrack({\n * mistBaseUrl: 'https://mist.example.com',\n * streamName: 'my-stream',\n * enabled: true,\n * });\n *\n * useEffect(() => {\n * if (!isConnected) return;\n *\n * const unsubscribe = subscribe('1', (event) => {\n * if (event.type === 'subtitle') {\n * setSubtitle(event.data as SubtitleCue);\n * }\n * });\n *\n * return unsubscribe;\n * }, [isConnected, subscribe]);\n * ```\n */\nexport function useMetaTrack(options: UseMetaTrackOptions): UseMetaTrackReturn {\n const {\n mistBaseUrl,\n streamName,\n subscriptions: initialSubscriptions,\n enabled = true,\n } = options;\n\n const [isConnected, setIsConnected] = useState(false);\n const [connectionState, setConnectionState] = useState<'disconnected' | 'connecting' | 'connected' | 'reconnecting'>('disconnected');\n const [subscribedTracks, setSubscribedTracks] = useState<string[]>([]);\n const managerRef = useRef<MetaTrackManager | null>(null);\n\n // Create manager instance\n useEffect(() => {\n if (!enabled || !mistBaseUrl || !streamName) {\n if (managerRef.current) {\n managerRef.current.disconnect();\n managerRef.current = null;\n }\n setIsConnected(false);\n setConnectionState('disconnected');\n return;\n }\n\n managerRef.current = new MetaTrackManager({\n mistBaseUrl,\n streamName,\n subscriptions: initialSubscriptions,\n debug: false,\n });\n\n // Start polling connection state\n const pollState = () => {\n if (managerRef.current) {\n const state = managerRef.current.getState();\n setConnectionState(state);\n setIsConnected(state === 'connected');\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n };\n\n const pollInterval = setInterval(pollState, 500);\n\n // Connect\n managerRef.current.connect();\n pollState();\n\n return () => {\n clearInterval(pollInterval);\n if (managerRef.current) {\n managerRef.current.disconnect();\n managerRef.current = null;\n }\n setIsConnected(false);\n setConnectionState('disconnected');\n };\n }, [enabled, mistBaseUrl, streamName, initialSubscriptions]);\n\n /**\n * Subscribe to a meta track\n */\n const subscribe = useCallback((trackId: string, callback: (event: MetaTrackEvent) => void): () => void => {\n if (!managerRef.current) {\n return () => {};\n }\n\n const unsubscribe = managerRef.current.subscribe(trackId, callback);\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n\n return () => {\n unsubscribe();\n if (managerRef.current) {\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n };\n }, []);\n\n /**\n * Unsubscribe from a meta track\n */\n const unsubscribe = useCallback((trackId: string, callback: (event: MetaTrackEvent) => void) => {\n if (managerRef.current) {\n managerRef.current.unsubscribe(trackId, callback);\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n }, []);\n\n /**\n * Manually connect\n */\n const connect = useCallback(() => {\n managerRef.current?.connect();\n }, []);\n\n /**\n * Manually disconnect\n */\n const disconnect = useCallback(() => {\n managerRef.current?.disconnect();\n }, []);\n\n /**\n * Update playback time for timed event dispatch\n * Call this on video timeupdate events to keep subtitle/chapter timing in sync\n */\n const setPlaybackTime = useCallback((timeInSeconds: number) => {\n managerRef.current?.setPlaybackTime(timeInSeconds);\n }, []);\n\n /**\n * Handle seek event - clears buffered events and resets state\n * Call this on video seeking/seeked events\n */\n const onSeek = useCallback((newTimeInSeconds: number) => {\n managerRef.current?.onSeek(newTimeInSeconds);\n }, []);\n\n return {\n isConnected,\n connectionState,\n subscribedTracks,\n subscribe,\n unsubscribe,\n connect,\n disconnect,\n setPlaybackTime,\n onSeek,\n };\n}\n\nexport default useMetaTrack;\n","import { useEffect, useState, useRef, useCallback } from 'react';\nimport { QualityMonitor, type PlaybackQuality } from '@livepeer-frameworks/player-core';\nimport type { UsePlaybackQualityOptions } from '../types';\n\n/**\n * Hook to monitor video playback quality\n *\n * Tracks:\n * - Buffer health (seconds ahead)\n * - Stall count\n * - Frame drop rate\n * - Estimated bitrate\n * - Latency (live streams)\n * - Composite quality score (0-100)\n *\n * @example\n * ```tsx\n * const { quality, isMonitoring } = usePlaybackQuality({\n * videoElement,\n * enabled: true,\n * thresholds: { minScore: 60 },\n * onQualityDegraded: (q) => console.log('Quality dropped:', q.score),\n * });\n *\n * return <div>Quality: {quality?.score ?? '--'}</div>;\n * ```\n */\nexport function usePlaybackQuality(options: UsePlaybackQualityOptions) {\n const {\n videoElement,\n enabled = true,\n sampleInterval = 500,\n thresholds,\n onQualityDegraded,\n } = options;\n\n const [quality, setQuality] = useState<PlaybackQuality | null>(null);\n const [isMonitoring, setIsMonitoring] = useState(false);\n const monitorRef = useRef<QualityMonitor | null>(null);\n\n // Create/update monitor instance\n useEffect(() => {\n monitorRef.current = new QualityMonitor({\n sampleInterval,\n thresholds,\n onQualityDegraded,\n onSample: setQuality,\n });\n\n return () => {\n monitorRef.current?.stop();\n monitorRef.current = null;\n };\n }, [sampleInterval, thresholds, onQualityDegraded]);\n\n // Start/stop monitoring based on videoElement and enabled state\n useEffect(() => {\n if (!enabled || !videoElement || !monitorRef.current) {\n monitorRef.current?.stop();\n setIsMonitoring(false);\n return;\n }\n\n monitorRef.current.start(videoElement);\n setIsMonitoring(true);\n\n return () => {\n monitorRef.current?.stop();\n setIsMonitoring(false);\n };\n }, [videoElement, enabled]);\n\n /**\n * Get current quality snapshot\n */\n const getCurrentQuality = useCallback((): PlaybackQuality | null => {\n return monitorRef.current?.getCurrentQuality() ?? null;\n }, []);\n\n /**\n * Get rolling average quality\n */\n const getAverageQuality = useCallback((): PlaybackQuality | null => {\n return monitorRef.current?.getAverageQuality() ?? null;\n }, []);\n\n /**\n * Get quality history\n */\n const getHistory = useCallback((): PlaybackQuality[] => {\n return monitorRef.current?.getHistory() ?? [];\n }, []);\n\n /**\n * Reset stall counters\n */\n const resetStallCounters = useCallback(() => {\n monitorRef.current?.resetStallCounters();\n }, []);\n\n /**\n * Get total stall time\n */\n const getTotalStallMs = useCallback((): number => {\n return monitorRef.current?.getTotalStallMs() ?? 0;\n }, []);\n\n return {\n /** Current quality metrics */\n quality,\n /** Whether monitoring is active */\n isMonitoring,\n /** Get current quality snapshot */\n getCurrentQuality,\n /** Get rolling average quality */\n getAverageQuality,\n /** Get quality history */\n getHistory,\n /** Reset stall counters */\n resetStallCounters,\n /** Get total stall time in ms */\n getTotalStallMs,\n };\n}\n\nexport default usePlaybackQuality;\n","/**\n * usePlayerSelection\n *\n * React hook for subscribing to PlayerManager selection events.\n * Uses event-driven updates instead of polling - no render spam.\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport type {\n PlayerManager,\n PlayerSelection,\n PlayerCombination,\n StreamInfo,\n PlaybackMode,\n} from '@livepeer-frameworks/player-core';\n\nexport interface UsePlayerSelectionOptions {\n /** Stream info to compute selections for */\n streamInfo: StreamInfo | null;\n /** Playback mode override */\n playbackMode?: PlaybackMode;\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport interface UsePlayerSelectionReturn {\n /** Current best selection (null if no compatible player) */\n selection: PlayerSelection | null;\n /** All player+source combinations with scores */\n combinations: PlayerCombination[];\n /** Whether initial computation has completed */\n ready: boolean;\n /** Force recomputation (invalidates cache) */\n refresh: () => void;\n}\n\n/**\n * Subscribe to player selection changes from a PlayerManager.\n *\n * This hook uses the event system in PlayerManager, which means:\n * - Initial computation happens once when streamInfo is provided\n * - Updates only fire when selection actually changes (different player+source)\n * - No render spam from React strict mode or frequent re-renders\n *\n * @example\n * ```tsx\n * const { selection, combinations, ready } = usePlayerSelection(globalPlayerManager, {\n * streamInfo,\n * playbackMode: 'auto',\n * });\n *\n * if (!ready) return <Loading />;\n * if (!selection) return <NoPlayerAvailable />;\n *\n * return <div>Selected: {selection.player} + {selection.source.type}</div>;\n * ```\n */\nexport function usePlayerSelection(\n manager: PlayerManager,\n options: UsePlayerSelectionOptions\n): UsePlayerSelectionReturn {\n const { streamInfo, playbackMode, debug } = options;\n\n const [selection, setSelection] = useState<PlayerSelection | null>(null);\n const [combinations, setCombinations] = useState<PlayerCombination[]>([]);\n const [ready, setReady] = useState(false);\n\n // Subscribe to events\n useEffect(() => {\n const unsubSelection = manager.on('selection-changed', (sel) => {\n if (debug) {\n console.log('[usePlayerSelection] Selection changed:', sel?.player, sel?.source?.type);\n }\n setSelection(sel);\n });\n\n const unsubCombos = manager.on('combinations-updated', (combos) => {\n if (debug) {\n console.log('[usePlayerSelection] Combinations updated:', combos.length);\n }\n setCombinations(combos);\n setReady(true);\n });\n\n return () => {\n unsubSelection();\n unsubCombos();\n };\n }, [manager, debug]);\n\n // Trigger initial computation when streamInfo changes\n useEffect(() => {\n if (!streamInfo) {\n setSelection(null);\n setCombinations([]);\n setReady(false);\n return;\n }\n\n // This will use cache if available, or compute + emit events if not\n manager.getAllCombinations(streamInfo, playbackMode);\n }, [manager, streamInfo, playbackMode]);\n\n // Manual refresh function\n const refresh = useCallback(() => {\n if (!streamInfo) return;\n manager.invalidateCache();\n manager.getAllCombinations(streamInfo, playbackMode);\n }, [manager, streamInfo, playbackMode]);\n\n return {\n selection,\n combinations,\n ready,\n refresh,\n };\n}\n","import { useEffect, useRef, useCallback } from 'react';\nimport { TelemetryReporter, type TelemetryOptions, type PlaybackQuality, type ContentType } from '@livepeer-frameworks/player-core';\n\nexport interface UseTelemetryOptions extends TelemetryOptions {\n /** Video element to monitor */\n videoElement: HTMLVideoElement | null;\n /** Content ID being played */\n contentId: string;\n /** Content type */\n contentType: ContentType;\n /** Player type name */\n playerType: string;\n /** Protocol being used */\n protocol: string;\n /** Optional quality getter function */\n getQuality?: () => PlaybackQuality | null;\n}\n\n/**\n * Hook to send telemetry data to a server\n *\n * Reports playback metrics at configurable intervals:\n * - Current time and duration\n * - Buffer health\n * - Stall count and duration\n * - Quality score and bitrate\n * - Frame decode/drop stats\n * - Errors encountered\n *\n * Uses navigator.sendBeacon() for reliable reporting on page unload.\n *\n * @example\n * ```tsx\n * const { sessionId, recordError } = useTelemetry({\n * enabled: true,\n * endpoint: '/api/telemetry',\n * interval: 5000,\n * videoElement,\n * contentId: 'my-stream',\n * contentType: 'live',\n * playerType: 'hlsjs',\n * protocol: 'HLS',\n * getQuality: () => qualityMonitor.getCurrentQuality(),\n * });\n *\n * // Record custom error\n * recordError('NETWORK_ERROR', 'Connection lost');\n * ```\n */\nexport function useTelemetry(options: UseTelemetryOptions) {\n const {\n enabled,\n endpoint,\n interval,\n authToken,\n batchSize,\n videoElement,\n contentId,\n contentType,\n playerType,\n protocol,\n getQuality,\n } = options;\n\n const reporterRef = useRef<TelemetryReporter | null>(null);\n\n // Create reporter instance\n useEffect(() => {\n if (!enabled || !endpoint || !contentId) {\n reporterRef.current?.stop();\n reporterRef.current = null;\n return;\n }\n\n reporterRef.current = new TelemetryReporter({\n endpoint,\n authToken,\n interval,\n batchSize,\n contentId,\n contentType,\n playerType,\n protocol,\n });\n\n return () => {\n reporterRef.current?.stop();\n reporterRef.current = null;\n };\n }, [enabled, endpoint, authToken, interval, batchSize, contentId, contentType, playerType, protocol]);\n\n // Start/stop reporting when video element changes\n useEffect(() => {\n if (!enabled || !videoElement || !reporterRef.current) {\n return;\n }\n\n reporterRef.current.start(videoElement, getQuality);\n\n return () => {\n reporterRef.current?.stop();\n };\n }, [enabled, videoElement, getQuality]);\n\n /**\n * Record a custom error\n */\n const recordError = useCallback((code: string, message: string) => {\n reporterRef.current?.recordError(code, message);\n }, []);\n\n /**\n * Get current session ID\n */\n const getSessionId = useCallback((): string | null => {\n return reporterRef.current?.getSessionId() ?? null;\n }, []);\n\n /**\n * Check if telemetry is active\n */\n const isActive = useCallback((): boolean => {\n return reporterRef.current?.isActive() ?? false;\n }, []);\n\n return {\n /** Session ID for this playback session */\n sessionId: reporterRef.current?.getSessionId() ?? null,\n /** Record a custom error */\n recordError,\n /** Get current session ID */\n getSessionId,\n /** Check if telemetry is active */\n isActive,\n };\n}\n\nexport default useTelemetry;\n"],"names":["ASPECT_RATIO","COLORS","pickNextColor","current","length","next","Math","floor","random","DvdLogo","_ref","parentRef","_ref$scale","scale","_useState2","_slicedToArray","useState","top","left","position","setPosition","positionRef","useRef","useEffect","_useState4","width","height","dimensions","setDimensions","dimensionsRef","velocityRef","x","y","_useState6","color","setColor","recalculateDimensions","React","useCallback","parent","parentWidth","clientWidth","parentHeight","clientHeight","maxHeight","nextDimensions","max","maxTop","maxLeft","startPosition","baseSpeed","min","ResizeObserver","observer","observe","disconnect","onResize","window","addEventListener","removeEventListener","animationFrame","lastTimestamp","performance","now","animate","timestamp","dims","deltaMs","speedMultiplier","_positionRef$current","_velocityRef$current","bounced","nextPosition","requestAnimationFrame","cancelAnimationFrame","_jsx","className","style","concat","children","viewBox","fill","d","logomarkAsset","AnimatedBubble","index","size","setSize","opacity","setOpacity","getRandomPosition","getRandomSize","animationCycle","setTimeout","timeout","clearTimeout","bubbleColors","borderRadius","background","transition","pointerEvents","userSelect","CenterLogo","_ref2","containerRef","_ref2$scale","onHitmarker","_useState8","logoSize","setLogoSize","_useState0","offset","setOffset","_useState10","isHovered","setIsHovered","containerWidth","containerHeight","minDimension","handleMouseMove","e","rect","getBoundingClientRect","centerX","centerY","deltaX","clientX","deltaY","clientY","distance","sqrt","maxDistance","pushDistance","handleMouseLeave","container","_jsxs","transform","display","alignItems","justifyContent","zIndex","animation","src","alt","onClick","stopPropagation","filter","cursor","WebkitUserDrag","StatusIcon","_ref3","status","iconClass","stroke","strokeLinecap","strokeLinejoin","strokeWidth","cx","cy","r","StatusOverlay","_ref4","message","percentage","error","onRetry","showRetry","showProgress","undefined","displayMessage","bottom","flexDirection","gap","maxWidth","textAlign","fontSize","fontFamily","overflow","type","padding","border","fontWeight","onMouseEnter","currentTarget","onMouseLeave","createSyntheticHitmarkerSound","audioContext","AudioContext","webkitAudioContext","oscillator1","createOscillator","oscillator2","gainNode1","createGain","gainNode2","masterGain","connect","destination","frequency","setValueAtTime","currentTime","exponentialRampToValueAtTime","gain","linearRampToValueAtTime","startTime","stopTime","start","stop","_unused2","IdleScreen","_ref5","_ref5$message","_useState12","hitmarkers","setHitmarkers","styleId","document","getElementById","createElement","id","textContent","head","appendChild","ref","inset","backgroundSize","map","hitmarker","backgroundColor","boxShadow","_toConsumableArray","Array","_","animationDelay","newHitmarker","Date","prev","audio","Audio","volume","play","_unused","playHitmarkerSound","h","right","TitleOverlay","title","description","isVisible","cn","StatsPanel","_video$playbackRate$t","_video$playbackRate","_quality$score$toFixe","_quality$score","_quality$frameDropRat","_quality$frameDropRat2","_quality$stallCount","_streamState$viewers","_streamState$status","isOpen","onClose","metadata","streamState","quality","videoElement","protocol","nodeId","geoDistance","_streamState$tracks","video","currentRes","videoWidth","videoHeight","buffered","end","toFixed","playbackRate","qualityScore","score","bitrateKbps","bitrate","frameDropRate","stallCount","latency","round","viewers","streamStatus","stats","label","value","String","tracks","t","codec","bps","channels","join","unshift","durationSeconds","mins","secs","push","padStart","recordingSizeBytes","mb","initialState","state","endpoints","duration","NaN","isPlaying","isPaused","isBuffering","isMuted","isPassiveError","hasPlaybackStarted","isHoldingSpeed","holdSpeed","isHovering","shouldShowControls","isLoopEnabled","isFullscreen","isPiPActive","isEffectivelyLive","shouldShowIdleScreen","currentPlayerInfo","currentSourceInfo","playbackQuality","subtitlesEnabled","qualities","textTracks","streamInfo","usePlayerController","config","_config$enabled","enabled","onStateChange","onStreamStateChange","onError","onReady","controllerConfig","_objectWithoutProperties","_excluded","controllerRef","setState","configRef","controller","PlayerController","contentId","contentType","gatewayUrl","mistUrl","authToken","autoplay","muted","controls","poster","debug","unsubs","syncState","c","_objectSpread","getVolume","getPlaybackQuality","isSubtitlesEnabled","getQualities","getStreamInfo","on","newState","getEndpoints","getMetadata","getCurrentPlayerInfo","getCurrentSourceInfo","_ref6","player","source","url","_ref7","_ref8","_ref9","_ref0","isPiP","_ref1","speed","_ref10","attach","err","console","warn","forEach","fn","destroy","_asyncToGenerator","_regenerator","m","_callee","_controllerRef$curren","w","_context","n","a","pause","_controllerRef$curren2","togglePlay","_controllerRef$curren3","seek","time","_controllerRef$curren4","seekBy","delta","_controllerRef$curren5","setVolume","_controllerRef$curren6","toggleMute","_controllerRef$curren7","toggleLoop","_controllerRef$curren8","toggleFullscreen","_callee2","_controllerRef$curren9","_context2","togglePiP","_callee3","_controllerRef$curren0","_context3","togglePictureInPicture","toggleSubtitles","_controllerRef$curren1","clearError","_controllerRef$curren10","retry","_callee4","_controllerRef$curren11","_context4","reload","_callee5","_controllerRef$curren12","_context5","_controllerRef$curren13","_controllerRef$curren14","selectQuality","_controllerRef$curren15","handleMouseEnter","_controllerRef$curren16","_controllerRef$curren17","_controllerRef$curren18","handleTouchStart","_controllerRef$curren19","setDevModeOptions","_ref16","_callee6","options","_controllerRef$curren20","_context6","_x","apply","this","arguments","PlayerContext","createContext","usePlayerContextOptional","useContext","Slider","forwardRef","trackClassName","thumbClassName","_ref$showTrack","showTrack","hoverThumb","_ref$accentColor","accentColor","_ref$orientation","orientation","props","rangeColorClass","thumbColorClass","SliderPrimitive","Root","Track","Range","Thumb","displayName","SeekBar","_ref$disabled","disabled","onSeek","_ref$isLive","isLive","_ref$seekableStart","seekableStart","liveEdge","_ref$commitOnRelease","commitOnRelease","trackRef","setIsHovering","isDragging","setIsDragging","dragTime","setDragTime","dragTimeRef","hoverPosition","setHoverPosition","hoverTime","setHoverTime","effectiveLiveEdge","seekableWindow","displayTime","progressPercent","useMemo","positionInWindow","Number","isFinite","bufferedSegments","rangeStart","rangeSize","segments","i","relativeStart","relativeEnd","startPercent","endPercent","formatTime","seconds","total","hours","minutes","formatLiveTime","edge","behindSeconds","getTimeFromPosition","percent","handleClick","handleMouseDown","preventDefault","handleDragMove","moveEvent","handleDragEnd","pending","showThumb","canShowTooltip","onMouseMove","onMouseDown","role","tabIndex","segment","PlayIcon","_ref$size","_ref$color","_ref$className","PauseIcon","_ref2$size","_ref2$color","_ref2$className","SkipBackIcon","_ref3$size","_ref3$color","_ref3$className","textAnchor","SkipForwardIcon","_ref4$size","_ref4$color","_ref4$className","VolumeUpIcon","_ref5$size","_ref5$color","_ref5$className","points","VolumeOffIcon","_ref6$size","_ref6$color","_ref6$className","x1","y1","x2","y2","FullscreenIcon","_ref7$size","_ref7$color","_ref7$className","FullscreenExitIcon","_ref8$size","_ref8$color","_ref8$className","PictureInPictureIcon","_ref9$size","_ref9$color","_ref9$className","rx","ry","SettingsIcon","_ref10$size","_ref10$color","_ref10$className","PlayPauseIcon","_ref11","VolumeIcon","_ref12","_excluded2","FullscreenToggleIcon","_ref13","_excluded3","StatsIcon","_ref14","_ref14$size","_ref14$color","_ref14$className","SeekToLiveIcon","_ref15","_ref15$size","_ref15$color","_ref15$className","PlayerControls","_ctx$state","_mistStreamInfo$meta","_player$getTextTracks","_player$getTextTracks2","_mistStreamInfo$meta2","_player$getSeekableSt","_player$getLiveEdge","_ref$isVisible","mistStreamInfo","_ref$playbackMode","playbackMode","onModeChange","sourceType","isContentLive","propVideoElement","_ref$qualities","propQualities","onSelectQuality","propIsMuted","propVolume","onVolumeChange","onToggleMute","propIsPlaying","onTogglePlay","onToggleFullscreen","propIsFullscreen","onToggleLoop","ctx","contextVideo","setVideo","videoCheckIntervalRef","findVideoElement","_player$getVideoEleme","_document$querySelect","getVideoElement","call","querySelector","v","setInterval","clearInterval","mistTracks","meta","_player$getQualities","playerQualities","Object","entries","sort","b","getTextTracks","internalIsPlaying","setInternalIsPlaying","internalIsMuted","setInternalIsMuted","internalIsFullscreen","setInternalIsFullscreen","hasAudio","setHasAudio","setBuffered","internalVolume","setInternalVolume","_useState14","setPlaybackRate","volumeValue","_useState16","qualityValue","setQualityValue","_useState18","captionValue","setCaptionValue","_useState20","isSettingsOpen","setIsSettingsOpen","_useState22","isNearLiveState","setIsNearLiveState","handleWindowClick","event","target","closest","timeoutId","bufferWindowMs","buffer_window","isLiveContent","isWebRTC","isMediaStreamSource","supportsPlaybackRate","coreSupportsPlaybackRate","_useMemo","calculateSeekableRange","calcSeekableStart","calcLiveEdge","controllerSeekableStart","getSeekableStart","controllerLiveEdge","getLiveEdge","useControllerRange","hasDvrWindow","liveThresholds","calculateLiveThresholds","canSeek","canSeekStream","calculateIsNearLive","hasSeekToLiveRef","updatePlayingState","paused","updateMutedState","updateFullscreenState","fullscreenElement","updatePlaybackRate","activeTrack","find","track","active","updateBuffered","_player$getBufferedRa","_player$getBufferedRa2","getBufferedRanges","checkAudio","srcObject","MediaStream","audioTracks","getAudioTracks","videoAny","handleMute","_player$isMuted","_player$isMuted2","_player$setMuted","nextMuted","setMuted","handleQualityChange","_player$selectQuality","handleCaptionChange","_player$selectTextTra","_player$selectTextTra2","selectTextTrack","timeDisplay","formatTimeDisplay","unixoffset","_useState24","isVolumeHovered","setIsVolumeHovered","_useState26","isVolumeFocused","setIsVolumeFocused","isVolumeExpanded","_player$isPaused","_player$isPaused2","newTime","maxTime","onFocusCapture","onBlurCapture","contains","relatedTarget","step","onValueChange","_value$","_player$jumpToLive","jumpToLive","mode","SPEED_PRESETS","rate","handleSpeedChange","q","exitFullscreen","requestFullscreen","SOURCE_TYPE_LABELS","whep","DevModePanel","_playerStats$levels","onSettingsChange","onReload","currentPlayer","currentSource","controlledIsOpen","onOpenChange","internalIsOpen","setInternalIsOpen","setIsOpen","activeTab","setActiveTab","setCurrentComboIndex","hoveredComboIndex","setHoveredComboIndex","tooltipAbove","setTooltipAbove","showDisabledPlayers","setShowDisabledPlayers","comboListRef","qualityMonitorRef","playbackScore","setPlaybackScore","setQualityScore","setStallCount","setFrameDropRate","playerStats","setPlayerStats","statsIntervalRef","QualityMonitor","sampleInterval","onSample","getPlaybackScore","pollStats","_stats","p","globalPlayerManager","getCurrentPlayer","getStats","allCombinations","getAllCombinations","combinations","compatible","activeComboIndex","findIndex","shortname","activeCompatibleIndex","handleReload","handleNextCombo","nextIdx","combo","forcePlayer","forceType","forceSource","sourceIndex","handleSelectCombo","setStats","updateStats","resolution","readyState","networkState","interval","name","charAt","toUpperCase","slice","borderBottom","_combo$scoreBreakdown","_combo$scoreBreakdown2","_combo$scoreBreakdown3","_combo$scoreBreakdown4","isCodecIncompat","codecIncompatible","isActive","typeLabel","split","pop","row","containerRect","relativePosition","playerName","scoreBreakdown","trackTypes","_Fragment","trackScore","weights","priorityScore","priority","sourceScore","reliabilityScore","reliability","modeBonus","routingBonus","routing","incompatibleReason","currentBitrate","bandwidthEstimate","currentLevel","levels","framesPerSecond","framesDecoded","framesDropped","packetLossRate","jitter","jitterBufferDelay","network","rtt","keys","fpks","lang","SpeedIndicator","FastForwardIcon","SkipIndicator","direction","_ref$seconds","onHide","isAnimating","setIsAnimating","timer","isBack","RewindIcon","ContextMenu","ContextMenuPrimitive","ContextMenuTrigger","Trigger","SubTrigger","ChevronRight","SubContent","ContextMenuContent","Portal","Content","ContextMenuItem","_excluded4","Item","checked","_excluded5","CheckboxItem","ItemIndicator","Check","_excluded6","RadioItem","Circle","_excluded7","Label","ContextMenuSeparator","_excluded8","Separator","PlayerInner","_state$endpoints","_state$currentPlayerI","_state$endpoints2","_state$metadata","_state$metadata2","_state$streamState","_state$metadata3","_state$streamState$st","_state$streamState2","_state$streamState3","_state$streamState4","_state$streamState5","_state$streamState6","_state$currentSourceI","_state$streamState7","_ref$thumbnailUrl","thumbnailUrl","propsEndpoints","isStatsOpen","setIsStatsOpen","isDevPanelOpen","setIsDevPanelOpen","skipDirection","setSkipDirection","devPlaybackMode","setDevPlaybackMode","_usePlayerController","stockControls","playerState","handleDevSettingsChange","settings","handleModeChange","handleStatsToggle","handleSkipIndicatorHide","primaryEndpoint","primary","isLegacyPlayer","useStockControls","showTitleOverlay","showBufferingSpinner","showWaitingForEndpoint","waitingMessage","asChild","devMode","isOnline","values","showStatsButton","onStatsToggle","WebkitUserSelect","MozUserSelect","msUserSelect","WebkitTouchCallout","buttonVariants","cva","variants","variant","default","secondary","ghost","outline","destructive","subtle","link","sm","lg","icon","defaultVariants","Button","_ref$asChild","Comp","Slot","getStatusLabel","PlayerErrorBoundary","_this","_classCallCheck","_callSuper","handleRetry","_this$props$onRetry","_this$props","hasError","_inherits","Component","key","errorInfo","_this$props$onError","_this$props2","_this$state$error","fallback","badgeVariants","lastUpdate","fetchWithRetry","_x2","_fetchWithRetry","maxRetries","initialDelay","lastError","_loop","_ret","attempt","_args3","response","_options$signal","delay","_t2","fetch","Error","signal","aborted","pow","Promise","resolve","_regeneratorValues","_ref0$size","_ref0$color","_ref0$className","_ref1$size","_ref1$color","_ref1$className","_ref3$message","noiseBuffer","createBuffer","sampleRate","noiseSource","createBufferSource","noiseData","getChannelData","buffer","noiseGain","log","minHeight","textShadow","playerController","Provider","_ref2$visible","visible","backdropFilter","onPlay","_ref$showUnmuteMessag","showUnmuteMessage","onKeyDown","backgroundImage","mistBaseUrl","streamName","initialSubscriptions","subscriptions","_options$enabled","isConnected","setIsConnected","connectionState","setConnectionState","subscribedTracks","setSubscribedTracks","managerRef","MetaTrackManager","pollState","getState","getSubscribedTracks","pollInterval","subscribe","trackId","callback","unsubscribe","_managerRef$current","_managerRef$current2","setPlaybackTime","timeInSeconds","_managerRef$current3","newTimeInSeconds","_managerRef$current4","_options$sampleInterv","thresholds","onQualityDegraded","setQuality","isMonitoring","setIsMonitoring","monitorRef","_monitorRef$current","_monitorRef$current2","_monitorRef$current3","getCurrentQuality","_monitorRef$current$g","_monitorRef$current4","getAverageQuality","_monitorRef$current$g2","_monitorRef$current5","getHistory","_monitorRef$current$g3","_monitorRef$current6","resetStallCounters","_monitorRef$current7","getTotalStallMs","_monitorRef$current$g4","_monitorRef$current8","context","manager","selection","setSelection","setCombinations","ready","setReady","unsubSelection","sel","_sel$source","unsubCombos","combos","refresh","invalidateCache","_options$pollInterval","_options$useWebSocket","useWebSocket","_options$debug","socketReady","setSocketReady","wsRef","pollTimeoutRef","wsTimeoutRef","mountedRef","processStreamInfo","data","lowerError","toLowerCase","includes","on_error","getStatusMessage","perc","_prev$streamInfo","_prev$streamInfo2","_data$meta","_prev$streamInfo3","mergedStreamInfo","pollHttp","baseUrl","text","jsonpMatch","_t","replace","encodeURIComponent","method","headers","Accept","ok","match","JSON","parse","connectWebSocket","close","wsUrl","ws","WebSocket","OPEN","onopen","onmessage","onerror","onclose","refetch","_wsRef$current","initializeConnection","socketRef","_reporterRef$current$3","_reporterRef$current7","endpoint","batchSize","playerType","getQuality","reporterRef","_reporterRef$current","TelemetryReporter","_reporterRef$current2","_reporterRef$current3","recordError","code","_reporterRef$current4","getSessionId","_reporterRef$current$","_reporterRef$current5","_reporterRef$current$2","_reporterRef$current6","sessionId","setEndpoints","setStatus","setError","abortRef","_abortRef$current","abort","ac","AbortController","_payload$errors","_payload$errors$","_payload$data","graphqlEndpoint","res","payload","resp","fallbacks","Authorization","body","stringify","query","variables","json","errors","resolveViewerEndpoint","isArray","outputs","fb"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/components/DvdLogo.tsx","../../src/assets/logomark.svg","../../src/components/IdleScreen.tsx","../../src/components/TitleOverlay.tsx","../../src/components/StatsPanel.tsx","../../src/hooks/usePlayerController.ts","../../src/context/PlayerContext.tsx","../../src/ui/slider.tsx","../../src/components/SeekBar.tsx","../../src/components/Icons.tsx","../../src/components/PlayerControls.tsx","../../src/components/DevModePanel.tsx","../../src/components/SpeedIndicator.tsx","../../src/components/SkipIndicator.tsx","../../src/ui/context-menu.tsx","../../src/components/Player.tsx","../../src/components/LoadingScreen.tsx","../../src/ui/button.tsx","../../src/components/StreamStateOverlay.tsx","../../src/components/PlayerErrorBoundary.tsx","../../src/ui/badge.tsx","../../src/hooks/useStreamState.ts","../../src/hooks/useViewerEndpoints.ts","../../src/components/ThumbnailOverlay.tsx","../../src/hooks/useMetaTrack.ts","../../src/hooks/usePlaybackQuality.ts","../../src/hooks/usePlayerSelection.ts","../../src/hooks/useTelemetry.ts"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { DvdLogoProps } from \"../types\";\n\ntype Point = { top: number; left: number };\ntype Velocity = { x: number; y: number };\ntype Size = { width: number; height: number };\n\nconst ORIGINAL_WIDTH = 153;\nconst ORIGINAL_HEIGHT = 69;\nconst ASPECT_RATIO = ORIGINAL_WIDTH / ORIGINAL_HEIGHT;\n\nconst COLORS = [\n \"#7aa2f7\",\n \"#bb9af7\",\n \"#9ece6a\",\n \"#73daca\",\n \"#7dcfff\",\n \"#f7768e\",\n \"#e0af68\",\n \"#2ac3de\",\n];\n\nconst pickNextColor = (current?: string): string => {\n if (COLORS.length === 0) {\n return current ?? \"#ffffff\";\n }\n\n if (COLORS.length === 1) {\n return COLORS[0];\n }\n\n let next: string;\n do {\n next = COLORS[Math.floor(Math.random() * COLORS.length)];\n } while (next === current);\n\n return next;\n};\n\nconst DvdLogo: React.FC<DvdLogoProps> = ({ parentRef, scale = 0.15 }) => {\n const [position, setPosition] = useState<Point>({ top: 0, left: 0 });\n const positionRef = useRef<Point>(position);\n useEffect(() => {\n positionRef.current = position;\n }, [position]);\n\n const [dimensions, setDimensions] = useState<Size>({\n width: ORIGINAL_WIDTH,\n height: ORIGINAL_HEIGHT,\n });\n const dimensionsRef = useRef<Size>(dimensions);\n useEffect(() => {\n dimensionsRef.current = dimensions;\n }, [dimensions]);\n\n const velocityRef = useRef<Velocity>({ x: 1.8, y: 1.6 });\n const [color, setColor] = useState<string>(pickNextColor());\n\n const recalculateDimensions = React.useCallback(() => {\n const parent = parentRef.current;\n if (!parent) {\n return;\n }\n\n const parentWidth = parent.clientWidth;\n const parentHeight = parent.clientHeight;\n if (parentWidth === 0 || parentHeight === 0) {\n return;\n }\n\n const maxWidth = parentWidth * scale;\n const maxHeight = parentHeight * scale;\n\n let width = maxWidth;\n let height = width / ASPECT_RATIO;\n\n if (height > maxHeight) {\n height = maxHeight;\n width = height * ASPECT_RATIO;\n }\n\n const nextDimensions: Size = {\n width: Math.max(20, width),\n height: Math.max(20, height),\n };\n\n dimensionsRef.current = nextDimensions;\n setDimensions(nextDimensions);\n\n const maxTop = Math.max(0, parentHeight - nextDimensions.height);\n const maxLeft = Math.max(0, parentWidth - nextDimensions.width);\n\n const startPosition: Point = {\n top: Math.random() * maxTop,\n left: Math.random() * maxLeft,\n };\n\n positionRef.current = startPosition;\n setPosition(startPosition);\n\n const baseSpeed = Math.max(1.2, Math.min(nextDimensions.width, nextDimensions.height) / 70);\n velocityRef.current = {\n x: baseSpeed * (Math.random() > 0.5 ? 1 : -1),\n y: baseSpeed * (Math.random() > 0.5 ? 1 : -1),\n };\n }, [parentRef, scale]);\n\n useEffect(() => {\n if (!parentRef.current) {\n return;\n }\n\n recalculateDimensions();\n\n if (typeof ResizeObserver !== \"undefined\") {\n const observer = new ResizeObserver(() => recalculateDimensions());\n observer.observe(parentRef.current);\n return () => observer.disconnect();\n }\n\n const onResize = () => recalculateDimensions();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, [parentRef, recalculateDimensions]);\n\n useEffect(() => {\n let animationFrame: number;\n let lastTimestamp = performance.now();\n\n const animate = (timestamp: number) => {\n const parent = parentRef.current;\n const dims = dimensionsRef.current;\n\n if (!parent || dims.width === 0 || dims.height === 0) {\n animationFrame = requestAnimationFrame(animate);\n return;\n }\n\n const deltaMs = timestamp - lastTimestamp;\n lastTimestamp = timestamp;\n const speedMultiplier = Math.min(deltaMs / 16, 2);\n\n const maxTop = parent.clientHeight - dims.height;\n const maxLeft = parent.clientWidth - dims.width;\n\n let { top, left } = positionRef.current;\n let { x, y } = velocityRef.current;\n let bounced = false;\n\n top += y * speedMultiplier;\n left += x * speedMultiplier;\n\n if (top <= 0 || top >= maxTop) {\n y = -y;\n top = Math.max(0, Math.min(maxTop, top));\n bounced = true;\n }\n\n if (left <= 0 || left >= maxLeft) {\n x = -x;\n left = Math.max(0, Math.min(maxLeft, left));\n bounced = true;\n }\n\n velocityRef.current = { x, y };\n const nextPosition = { top, left };\n positionRef.current = nextPosition;\n setPosition(nextPosition);\n\n if (bounced) {\n setColor((current) => pickNextColor(current));\n }\n\n animationFrame = requestAnimationFrame(animate);\n };\n\n animationFrame = requestAnimationFrame(animate);\n\n return () => cancelAnimationFrame(animationFrame);\n }, [parentRef]);\n\n return (\n <div\n className=\"fw-player-dvd\"\n style={{\n top: `${position.top}px`,\n left: `${position.left}px`,\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n }}\n >\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 153 69\" fill={color} className=\"select-none\">\n <g>\n <path d=\"M140.186,63.52h-1.695l-0.692,5.236h-0.847l0.77-5.236h-1.693l0.076-0.694h4.158L140.186,63.52L140.186,63.52z M146.346,68.756h-0.848v-4.545l0,0l-2.389,4.545l-1-4.545l0,0l-1.462,4.545h-0.771l1.924-5.931h0.695l0.924,4.006l2.078-4.006 h0.848V68.756L146.346,68.756z M126.027,0.063H95.352c0,0-8.129,9.592-9.654,11.434c-8.064,9.715-9.523,12.32-9.779,13.02 c0.063-0.699-0.256-3.304-3.686-13.148C71.282,8.7,68.359,0.062,68.359,0.062H57.881V0L32.35,0.063H13.169l-1.97,8.131 l14.543,0.062h3.365c9.336,0,15.055,3.747,13.467,10.354c-1.717,7.24-9.91,10.416-18.545,10.416h-3.24l4.191-17.783H10.502 L4.34,37.219h20.578c15.432,0,30.168-8.13,32.709-18.608c0.508-1.906,0.443-6.67-0.764-9.527c0-0.127-0.063-0.191-0.127-0.444 c-0.064-0.063-0.127-0.509,0.127-0.571c0.128-0.062,0.383,0.189,0.445,0.254c0.127,0.317,0.19,0.57,0.19,0.57l13.083,36.965 l33.344-37.6h14.1h3.365c9.337,0,15.055,3.747,13.528,10.354c-1.778,7.24-9.972,10.416-18.608,10.416h-3.238l4.191-17.783h-14.481 l-6.159,25.976h20.576c15.434,0,30.232-8.13,32.709-18.608C152.449,8.193,141.523,0.063,126.027,0.063L126.027,0.063z M71.091,45.981c-39.123,0-70.816,4.512-70.816,10.035c0,5.59,31.693,10.034,70.816,10.034c39.121,0,70.877-4.444,70.877-10.034 C141.968,50.493,110.212,45.981,71.091,45.981L71.091,45.981z M68.55,59.573c-8.956,0-16.196-1.523-16.196-3.365 c0-1.84,7.239-3.303,16.196-3.303c8.955,0,16.195,1.463,16.195,3.303C84.745,58.050,77.505,59.573,68.55,59.573L68.55,59.573z\" />\n </g>\n </svg>\n </div>\n );\n};\n\nexport default DvdLogo;\n","export default \"data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20standalone%3D%22no%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%2015806%2015806%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20xml%3Aspace%3D%22preserve%22%20xmlns%3Aserif%3D%22http%3A%2F%2Fwww.serif.com%2F%22%20style%3D%22fill-rule%3Aevenodd%3Bclip-rule%3Aevenodd%3Bstroke-linejoin%3Around%3Bstroke-miterlimit%3A2%3B%22%3E%20%20%20%20%3Cg%20transform%3D%22matrix%285.55556%2C0%2C0%2C5.55556%2C0%2C0%29%22%3E%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%288.31462%2C0%2C0%2C8.31462%2C8.22267e-14%2C-6.49389e-14%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M488.82%2C596.09C489.36%2C595.2%20489.89%2C594.31%20490.41%2C593.41C490.5%2C593.25%20490.59%2C593.09%20490.68%2C592.93C499.43%2C577.56%20504.8%2C560.03%20505.8%2C541.33C505.82%2C541.05%20505.83%2C540.77%20505.85%2C540.49C505.88%2C539.79%20505.91%2C539.09%20505.93%2C538.38C505.96%2C537.46%20505.97%2C536.54%20505.98%2C535.61C505.98%2C535.41%20505.99%2C535.2%20505.99%2C535L505.99%2C534.72C505.99%2C469.43%20453.06%2C416.51%20387.78%2C416.51C322.5%2C416.51%20269.57%2C469.44%20269.57%2C534.72C269.57%2C582.95%20298.45%2C624.43%20339.86%2C642.81C342.17%2C641.83%20344.82%2C641.6%20347.6%2C642.5C347.71%2C642.48%20348.06%2C642.58%20348.8%2C642.93C349.87%2C642.59%20351.08%2C642.46%20352.17%2C642.22C354.63%2C641.68%20357.12%2C641.33%20359.58%2C640.81C365.15%2C639.64%20370.59%2C637.89%20376.16%2C636.73C382.32%2C635.45%20388.69%2C638.46%20390.44%2C644.84C391.16%2C647.46%20390.81%2C650.38%20389.65%2C652.91C430.42%2C652.28%20466.17%2C631.01%20486.93%2C599.09C487.1%2C598.83%20487.27%2C598.57%20487.44%2C598.31C487.91%2C597.57%20488.37%2C596.83%20488.83%2C596.09L488.82%2C596.09Z%22%20style%3D%22fill%3Argb%2826%2C26%2C26%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M398.87%2C484.2L399.88%2C505.89L410.28%2C509.55L395.52%2C509.55L394.43%2C479.48L415.2%2C479.48L398.87%2C484.2Z%22%20style%3D%22fill%3Argb%2877%2C77%2C77%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M407.52%2C632.43L407.52%2C632.37L405.83%2C567.81L405.91%2C560.75L420.81%2C555.3L399.31%2C556L402.95%2C630.22C404.49%2C630.89%20406.02%2C631.62%20407.53%2C632.42L407.52%2C632.43Z%22%20style%3D%22fill%3Argb%2877%2C77%2C77%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M315.75%2C435.86L315.75%2C445.19C315.75%2C445.19%20343.09%2C444.1%20343.09%2C467.32L343.09%2C491.12L366.17%2C476.2L467.27%2C476.2C473.14%2C476.2%20478.98%2C477.27%20484.41%2C479.5C489.4%2C481.55%20494.15%2C484.61%20494.15%2C488.82L494.15%2C442.41L406.24%2C442.41L406.24%2C435.92L315.75%2C435.86Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M384.52%2C549.53C383%2C549.84%20374.5%2C554.81%20372.41%2C555.99C361.06%2C562.39%20350.66%2C570.29%20340.56%2C578.47L343.55%2C511.3C357.29%2C499.76%20372.89%2C489.71%20389.69%2C483.46L391.34%2C511.85L380.41%2C515.68L465.05%2C515.68L465.05%2C549.54L384.51%2C549.54L384.52%2C549.53Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M384.62%2C620.15C386.3%2C618.47%20388.78%2C617.44%20391.15%2C617.44C392.32%2C617.44%20393.42%2C617.66%20394.43%2C618.05L391.53%2C561.24C376.44%2C568.54%20361.62%2C576.78%20348.45%2C587.23C346.53%2C588.75%20339.44%2C594.3%20338.53%2C595.88C338.16%2C596.53%20338.08%2C596.77%20337.99%2C597.52C336.15%2C611.29%20341.68%2C626.24%20327.48%2C635.06C325.4%2C636.35%20322.28%2C637.18%20320.41%2C638.36C319.72%2C638.79%20319.26%2C638.87%20319.46%2C639.87L357.68%2C640.77L357.68%2C621.03C357.68%2C620.82%20358.79%2C618.46%20359.07%2C618.05C362%2C613.76%20368.64%2C613.05%20372.45%2C616.63C373.18%2C617.32%20375.15%2C620.84%20375.15%2C621.57L375.15%2C626.68C376.32%2C626.01%20377.56%2C625.46%20378.87%2C625.04C380.03%2C624.43%20381.23%2C623.94%20382.45%2C623.58C382.94%2C622.27%20383.71%2C621.04%20384.62%2C620.14L384.62%2C620.15Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%22336.59%22%20y%3D%22428.82%22%20width%3D%2255.13%22%20height%3D%228.66%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M370.43%2C405.41L381.28%2C405.41L381.28%2C428.82L347.02%2C428.82C347.02%2C415.9%20357.51%2C405.41%20370.43%2C405.41Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M375.15%2C621.59L375.15%2C646.4L399.31%2C643.32L393.82%2C606.12%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M434.95%2C641.77C427.45%2C636.79%20420.54%2C630.98%20414.13%2C624.68C378.86%2C650.1%20331.68%2C660.51%20289.92%2C645.24C276.7%2C656.38%20260.2%2C663.03%20243.21%2C666.13C245.28%2C668.42%20247.17%2C670.85%20249%2C673.36C259.11%2C673.75%20269.41%2C673.79%20279.47%2C672.94C316.6%2C669.77%20351.78%2C651.88%20389.38%2C653.26C420.31%2C654.4%20448.46%2C670.95%20479.26%2C673.24C493.74%2C674.31%20510.78%2C671.04%20524.28%2C665.72C524.6%2C665.6%20525.17%2C665.63%20525.1%2C665.2C493.55%2C667.12%20461.22%2C659.22%20434.94%2C641.78L434.95%2C641.77Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M431.64%2C681.28C431.71%2C681.82%20430.99%2C681.55%20430.67%2C681.5C428.7%2C681.19%20426.49%2C680.36%20424.48%2C679.92C400.81%2C674.72%20375.35%2C672.69%20351.2%2C675.65C341.11%2C676.89%20331.28%2C679.62%20321.24%2C681.22C300.45%2C684.53%20278.62%2C685.74%20257.83%2C682.01C273.85%2C682.14%20289.66%2C680.16%20305.21%2C676.54C319.99%2C673.09%20334.95%2C667.38%20350.01%2C665.52C377.55%2C662.11%20406.29%2C671.7%20431.64%2C681.28Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M376.31%2C636.41L367.67%2C639.94C342.05%2C648.2%20314.13%2C646.84%20288.76%2C638.37C280.1%2C644.46%20271.14%2C650.64%20260.82%2C653.56L267.06%2C649.22C276.19%2C642.22%20285.08%2C634.65%20291.47%2C624.98C294.79%2C626.43%20297.92%2C628.31%20301.23%2C629.78C323.76%2C639.82%20352.12%2C642.31%20376.31%2C636.41Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M496.44%2C679.79L493.62%2C680.99C455.11%2C696.09%20422.32%2C666.01%20385.12%2C661.7L374.61%2C660.13C397.05%2C658.33%20419.03%2C663.62%20440.24%2C670.18C445.86%2C671.92%20451.4%2C674.13%20457.03%2C675.77C469.67%2C679.46%20483.33%2C681.19%20496.45%2C679.8L496.44%2C679.79Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M502.72%2C658.04L499.89%2C658.33C480.42%2C655.87%20461.58%2C649.56%20444.59%2C639.91C442.86%2C638.93%20440.96%2C637.83%20439.42%2C636.58C447.9%2C638.94%20456.77%2C635.92%20464.33%2C632.12C472.21%2C646.13%20487.36%2C654.62%20502.73%2C658.03L502.72%2C658.04Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M440%2C690.82C440.07%2C691.36%20439.35%2C691.09%20439.03%2C691.04C435.69%2C690.51%20432.35%2C689.64%20429.02%2C689.11C398.16%2C684.21%20366.77%2C684.02%20335.64%2C686.06C335.32%2C686.08%20334.23%2C686.27%20334.29%2C685.75C369.06%2C676.79%20406.04%2C680.41%20440%2C690.82Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M313.56%2C572.87L313.69%2C572.14L313.94%2C572.49L313.56%2C572.87Z%22%20style%3D%22fill%3Argb%282%2C38%2C43%29%3Bfill-opacity%3A0.6%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M539.06%2C620.51C542.62%2C613.83%20545.72%2C606.95%20548.35%2C599.91C560.45%2C567.54%20562.63%2C531.85%20554.01%2C497.83C553.56%2C496.03%20551.73%2C494.94%20549.93%2C495.4C548.14%2C495.85%20547.05%2C497.68%20547.5%2C499.47C555.79%2C532.17%20553.69%2C566.46%20542.08%2C597.56C539.98%2C603.18%20537.56%2C608.71%20534.84%2C614.1C532.63%2C618.48%20530.21%2C622.77%20527.59%2C626.96C527.3%2C627.44%20527%2C627.91%20526.69%2C628.38C525.42%2C630.39%20524.1%2C632.37%20522.71%2C634.32C522.05%2C635.28%20521.36%2C636.24%20520.66%2C637.19C519.76%2C638.42%20518.84%2C639.63%20517.89%2C640.84C512.56%2C647.71%20506.62%2C654.2%20500.09%2C660.26C498.25%2C661.96%20496.36%2C663.64%20494.43%2C665.27C490.48%2C668.61%20486.33%2C671.8%20482%2C674.81C478.57%2C677.19%20474.88%2C679.59%20471.13%2C681.77C467.82%2C683.69%20464.47%2C685.45%20461.2%2C686.92C461.06%2C686.99%20460.92%2C687.06%20460.79%2C687.14L460.76%2C687.16L460.74%2C687.16L460.58%2C687.29L460.43%2C687.41L460.37%2C687.45L460.3%2C687.51L460.11%2C687.7L460.07%2C687.75L460.05%2C687.77L460.03%2C687.8L460%2C687.83C459.77%2C688.11%20459.57%2C688.43%20459.44%2C688.79C459.3%2C689.15%20459.23%2C689.53%20459.22%2C689.9L459.22%2C690.26L459.25%2C690.42L459.29%2C690.67L459.35%2C690.9C459.39%2C691.06%20459.45%2C691.21%20459.51%2C691.36C459.58%2C691.5%20459.65%2C691.64%20459.73%2C691.77L459.75%2C691.79L459.77%2C691.82L459.88%2C691.98L460%2C692.13L460.04%2C692.19L460.34%2C692.49L460.36%2C692.49L460.42%2C692.56C460.7%2C692.79%20461.02%2C692.98%20461.38%2C693.12L483.09%2C701.39L504.75%2C709.65C504.94%2C709.72%20505.13%2C709.78%20505.34%2C709.82C506.31%2C710.21%20507.44%2C710.1%20508.32%2C709.48C508.49%2C709.37%20508.64%2C709.23%20508.79%2C709.08L556.35%2C659.8C557.38%2C658.73%20557.5%2C657.12%20556.75%2C655.92L539.06%2C620.51Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M427.7%2C697.67C395%2C705.96%20360.71%2C703.86%20329.62%2C692.24C313.96%2C686.39%20299.11%2C678.13%20285.67%2C667.54C283.67%2C665.98%20281.69%2C664.35%20279.75%2C662.67C272.21%2C656.14%20265.17%2C648.83%20258.77%2C640.77C257.46%2C639.14%20256.18%2C637.46%20254.94%2C635.76C254.57%2C635.27%20254.21%2C634.78%20253.85%2C634.28C253.35%2C633.58%20252.85%2C632.88%20252.36%2C632.17C249.98%2C628.73%20247.59%2C625.05%20245.4%2C621.29C243.51%2C618.05%20241.78%2C614.76%20240.33%2C611.54C240.3%2C611.48%20240.28%2C611.43%20240.25%2C611.37C240.25%2C611.35%20240.23%2C611.32%20240.22%2C611.3C240.16%2C611.18%20240.1%2C611.07%20240.03%2C610.96L240.01%2C610.93L240.01%2C610.9L239.89%2C610.74L239.77%2C610.6L239.72%2C610.54L239.66%2C610.47L239.56%2C610.36L239.47%2C610.28L239.43%2C610.24L239.4%2C610.22L239.38%2C610.19L239.34%2C610.17C239.29%2C610.13%20239.24%2C610.09%20239.19%2C610.05C238.95%2C609.87%20238.68%2C609.72%20238.39%2C609.61C238.02%2C609.47%20237.65%2C609.4%20237.28%2C609.39L236.91%2C609.39L236.75%2C609.42L236.51%2C609.46L236.27%2C609.52C236.12%2C609.56%20235.97%2C609.62%20235.81%2C609.68C235.67%2C609.75%20235.54%2C609.82%20235.41%2C609.9L235.35%2C609.94L235.19%2C610.05L234.99%2C610.21L234.92%2C610.27L234.73%2C610.46L234.69%2C610.51L234.61%2C610.59C234.38%2C610.87%20234.19%2C611.19%20234.05%2C611.55L225.78%2C633.25L217.53%2C654.92C217.45%2C655.11%20217.39%2C655.3%20217.35%2C655.51C216.96%2C656.48%20217.08%2C657.61%20217.69%2C658.49C217.8%2C658.66%20217.94%2C658.81%20218.09%2C658.96L267.38%2C706.52C268.44%2C707.55%20270.05%2C707.67%20271.25%2C706.92L306.67%2C689.23C313.34%2C692.79%20320.22%2C695.89%20327.26%2C698.52C359.63%2C710.62%20395.32%2C712.8%20429.34%2C704.18C431.14%2C703.72%20432.23%2C701.9%20431.78%2C700.1C431.32%2C698.31%20429.5%2C697.22%20427.7%2C697.67Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M222.39%2C582.08C222.84%2C583.87%20224.67%2C584.96%20226.46%2C584.51C228.26%2C584.05%20229.35%2C582.23%20228.89%2C580.43C220.61%2C547.74%20222.7%2C513.44%20234.32%2C482.35C240.43%2C466.01%20249.16%2C450.55%20260.42%2C436.66C266.85%2C428.7%20274.11%2C421.26%20282.17%2C414.47C286.06%2C411.19%20290.14%2C408.06%20294.4%2C405.1C297.83%2C402.71%20301.52%2C400.32%20305.27%2C398.13C308.57%2C396.21%20311.92%2C394.45%20315.2%2C392.98C315.34%2C392.92%20315.48%2C392.84%20315.61%2C392.76L315.63%2C392.74L315.66%2C392.74L315.82%2C392.62L315.97%2C392.5L316.03%2C392.45L316.09%2C392.39L316.2%2C392.29L316.28%2C392.2L316.33%2C392.16L316.35%2C392.13L316.37%2C392.11L316.4%2C392.07C316.63%2C391.79%20316.82%2C391.48%20316.96%2C391.12C317.1%2C390.75%20317.17%2C390.38%20317.18%2C390.01L317.18%2C389.78L317.17%2C389.64L317.15%2C389.48L317.11%2C389.24L317.05%2C389C317.01%2C388.85%20316.95%2C388.7%20316.88%2C388.55C316.82%2C388.4%20316.74%2C388.27%20316.66%2C388.14L316.64%2C388.11L316.64%2C388.08L316.52%2C387.92L316.4%2C387.77L316.35%2C387.72L316.29%2C387.65L316.06%2C387.42L316.03%2C387.4L316.01%2C387.37L315.97%2C387.35C315.69%2C387.11%20315.37%2C386.92%20315.02%2C386.79L293.31%2C378.51L271.65%2C370.26C271.46%2C370.18%20271.26%2C370.12%20271.06%2C370.08C270.08%2C369.7%20268.96%2C369.81%20268.08%2C370.42C267.91%2C370.54%20267.75%2C370.67%20267.61%2C370.82L220.05%2C420.11C219.02%2C421.18%20218.89%2C422.78%20219.65%2C423.98L237.33%2C459.4C233.77%2C466.07%20230.67%2C472.95%20228.04%2C480C215.95%2C512.36%20213.77%2C548.05%20222.39%2C582.08Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20transform%3D%22matrix%281%2C0%2C0%2C1%2C-217.125%2C-368.902%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M519.68%2C441.65C520.78%2C443.12%20521.85%2C444.61%20522.91%2C446.13C525.3%2C449.56%20527.69%2C453.25%20529.88%2C457C531.8%2C460.3%20533.56%2C463.65%20535.03%2C466.93C535.09%2C467.07%20535.17%2C467.21%20535.25%2C467.34L535.27%2C467.36L535.27%2C467.39L535.39%2C467.55L535.51%2C467.7L535.56%2C467.76L535.62%2C467.82L535.72%2C467.93L535.81%2C468.01L535.85%2C468.05L535.88%2C468.07L535.9%2C468.1L535.94%2C468.13C536.22%2C468.36%20536.54%2C468.55%20536.89%2C468.69C537.26%2C468.83%20537.63%2C468.89%20538%2C468.9L538.37%2C468.9L538.53%2C468.88L538.77%2C468.84L539.01%2C468.78C539.16%2C468.73%20539.31%2C468.68%20539.46%2C468.61C539.61%2C468.54%20539.74%2C468.47%20539.87%2C468.39L539.9%2C468.37L539.93%2C468.37L540.09%2C468.25L540.24%2C468.13L540.29%2C468.08L540.36%2C468.02L540.59%2C467.79L540.61%2C467.76L540.64%2C467.74L540.66%2C467.7C540.9%2C467.42%20541.09%2C467.1%20541.22%2C466.74L549.5%2C445.04L557.75%2C423.38C557.83%2C423.19%20557.89%2C422.99%20557.93%2C422.79C558.32%2C421.81%20558.2%2C420.69%20557.59%2C419.81C557.47%2C419.64%20557.34%2C419.48%20557.19%2C419.33L507.9%2C371.78C506.84%2C370.75%20505.23%2C370.62%20504.03%2C371.38L468.61%2C389.06C461.94%2C385.5%20455.06%2C382.4%20448.01%2C379.77C415.65%2C367.68%20379.96%2C365.5%20345.93%2C374.12C344.14%2C374.57%20343.05%2C376.4%20343.5%2C378.19C343.96%2C379.98%20345.78%2C381.08%20347.58%2C380.62C380.27%2C372.34%20414.57%2C374.43%20445.66%2C386.05C461.19%2C391.85%20475.94%2C400.04%20489.29%2C410.5C500.52%2C419.29%20510.77%2C429.7%20519.68%2C441.65Z%22%20style%3D%22fill%3Argb%28242%2C242%2C242%29%3Bfill-rule%3Anonzero%3B%22%2F%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%3C%2Fg%3E%3C%2Fsvg%3E\"","import React, { useRef, useEffect, useState } from \"react\";\nimport DvdLogo from \"./DvdLogo\";\nimport logomarkAsset from \"../assets/logomark.svg\";\nimport type { StreamStatus } from \"../types\";\n\n// ============================================================================\n// AnimatedBubble Component\n// ============================================================================\n\ninterface AnimatedBubbleProps {\n index: number;\n}\n\nconst AnimatedBubble: React.FC<AnimatedBubbleProps> = ({ index }) => {\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const [size, setSize] = useState(40);\n const [opacity, setOpacity] = useState(0);\n\n const getRandomPosition = () => ({\n top: Math.random() * 80 + 10,\n left: Math.random() * 80 + 10,\n });\n\n const getRandomSize = () => Math.random() * 60 + 30;\n\n useEffect(() => {\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n\n const animationCycle = () => {\n setOpacity(0.15);\n setTimeout(() => {\n setOpacity(0);\n setTimeout(() => {\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n setTimeout(() => {\n animationCycle();\n }, 200);\n }, 1500);\n }, 4000 + Math.random() * 3000);\n };\n\n const timeout = setTimeout(animationCycle, index * 500);\n return () => clearTimeout(timeout);\n }, [index]);\n\n const bubbleColors = [\n \"rgba(122, 162, 247, 0.2)\",\n \"rgba(187, 154, 247, 0.2)\",\n \"rgba(158, 206, 106, 0.2)\",\n \"rgba(115, 218, 202, 0.2)\",\n \"rgba(125, 207, 255, 0.2)\",\n \"rgba(247, 118, 142, 0.2)\",\n \"rgba(224, 175, 104, 0.2)\",\n \"rgba(42, 195, 222, 0.2)\",\n ];\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: `${position.top}%`,\n left: `${position.left}%`,\n width: `${size}px`,\n height: `${size}px`,\n borderRadius: \"50%\",\n background: bubbleColors[index % bubbleColors.length],\n opacity,\n transition: \"opacity 1s ease-in-out\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n } as React.CSSProperties}\n />\n );\n};\n\n// ============================================================================\n// CenterLogo Component\n// ============================================================================\n\ninterface CenterLogoProps {\n containerRef: React.RefObject<HTMLDivElement>;\n scale?: number;\n onHitmarker?: (e: { clientX: number; clientY: number }) => void;\n}\n\nconst CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHitmarker }) => {\n const [logoSize, setLogoSize] = useState(100);\n const [offset, setOffset] = useState({ x: 0, y: 0 });\n const [isHovered, setIsHovered] = useState(false);\n\n useEffect(() => {\n if (containerRef.current) {\n const containerWidth = containerRef.current.clientWidth;\n const containerHeight = containerRef.current.clientHeight;\n const minDimension = Math.min(containerWidth, containerHeight);\n setLogoSize(minDimension * scale);\n }\n }, [containerRef, scale]);\n\n const handleLogoClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onHitmarker) {\n onHitmarker({ clientX: e.clientX, clientY: e.clientY });\n }\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const deltaX = e.clientX - centerX;\n const deltaY = e.clientY - centerY;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n const maxDistance = logoSize * 1.5;\n if (distance < maxDistance && distance > 0) {\n const pushStrength = (maxDistance - distance) / maxDistance;\n const pushDistance = 50 * pushStrength;\n const pushX = -(deltaX / distance) * pushDistance;\n const pushY = -(deltaY / distance) * pushDistance;\n setOffset({ x: pushX, y: pushY });\n setIsHovered(true);\n } else {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n }\n };\n\n const handleMouseLeave = () => {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n };\n\n useEffect(() => {\n if (containerRef.current) {\n const container = containerRef.current;\n container.addEventListener('mousemove', handleMouseMove);\n container.addEventListener('mouseleave', handleMouseLeave);\n return () => {\n container.removeEventListener('mousemove', handleMouseMove);\n container.removeEventListener('mouseleave', handleMouseLeave);\n };\n }\n }, [logoSize, containerRef]);\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: `translate(-50%, -50%) translate(${offset.x}px, ${offset.y}px)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10,\n transition: \"transform 0.3s ease-out\",\n userSelect: \"none\",\n }}\n >\n <div\n style={{\n position: \"absolute\",\n width: `${logoSize * 1.4}px`,\n height: `${logoSize * 1.4}px`,\n borderRadius: \"50%\",\n background: \"rgba(122, 162, 247, 0.15)\",\n animation: isHovered ? \"logoPulse 1s ease-in-out infinite\" : \"logoPulse 3s ease-in-out infinite\",\n transform: isHovered ? \"scale(1.2)\" : \"scale(1)\",\n transition: \"transform 0.3s ease-out\",\n pointerEvents: \"none\",\n }}\n />\n <img\n src={logomarkAsset}\n alt=\"FrameWorks Logo\"\n onClick={handleLogoClick}\n style={{\n width: `${logoSize}px`,\n height: `${logoSize}px`,\n position: \"relative\",\n zIndex: 1,\n filter: isHovered\n ? \"drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1)\"\n : \"drop-shadow(0 4px 8px rgba(36, 40, 59, 0.3))\",\n transform: isHovered ? \"scale(1.1)\" : \"scale(1)\",\n transition: \"all 0.3s ease-out\",\n cursor: isHovered ? \"pointer\" : \"default\",\n userSelect: \"none\",\n WebkitUserDrag: \"none\",\n } as React.CSSProperties}\n />\n </div>\n );\n};\n\n// ============================================================================\n// Status Overlay Component (shows on top of the fancy background)\n// ============================================================================\n\ninterface StatusOverlayProps {\n status?: StreamStatus;\n message: string;\n percentage?: number;\n error?: string;\n onRetry?: () => void;\n}\n\nfunction StatusIcon({ status }: { status?: StreamStatus }) {\n const iconClass = \"w-5 h-5\";\n\n // Spinner for loading states\n if (status === 'INITIALIZING' || status === 'BOOTING' || status === 'WAITING_FOR_DATA' || !status) {\n return (\n <svg className={`${iconClass} animate-spin`} fill=\"none\" viewBox=\"0 0 24 24\" style={{ color: 'hsl(var(--tn-yellow, 40 95% 64%))' }}>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n );\n }\n\n // Offline icon\n if (status === 'OFFLINE') {\n return (\n <svg className={iconClass} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" style={{ color: 'hsl(var(--tn-red, 348 100% 72%))' }}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414\" />\n </svg>\n );\n }\n\n // Error icon\n if (status === 'ERROR' || status === 'INVALID') {\n return (\n <svg className={iconClass} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" style={{ color: 'hsl(var(--tn-red, 348 100% 72%))' }}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n );\n }\n\n // Default spinner\n return (\n <svg className={`${iconClass} animate-spin`} fill=\"none\" viewBox=\"0 0 24 24\" style={{ color: 'hsl(var(--tn-cyan, 193 100% 75%))' }}>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n );\n}\n\nconst StatusOverlay: React.FC<StatusOverlayProps> = ({ status, message, percentage, error, onRetry }) => {\n const showRetry = (status === 'ERROR' || status === 'INVALID') && onRetry;\n const showProgress = status === 'INITIALIZING' && percentage !== undefined;\n const displayMessage = error || message;\n\n return (\n <div\n style={{\n position: \"absolute\",\n bottom: \"16px\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 20,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"8px\",\n maxWidth: \"280px\",\n textAlign: \"center\",\n }}\n >\n {/* Subtle status indicator - just icon + message */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n color: \"#787c99\",\n fontSize: \"13px\",\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n }}\n >\n <StatusIcon status={status} />\n <span>{displayMessage}</span>\n </div>\n\n {/* Progress bar */}\n {showProgress && (\n <div\n style={{\n width: \"160px\",\n height: \"4px\",\n background: \"rgba(65, 72, 104, 0.4)\",\n borderRadius: \"2px\",\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n width: `${Math.min(100, percentage)}%`,\n height: \"100%\",\n background: \"hsl(var(--tn-cyan, 193 100% 75%))\",\n transition: \"width 0.3s ease-out\",\n }}\n />\n </div>\n )}\n\n {/* Retry button - only for errors */}\n {showRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n style={{\n padding: \"6px 16px\",\n background: \"transparent\",\n border: \"1px solid rgba(122, 162, 247, 0.4)\",\n borderRadius: \"4px\",\n color: \"#7aa2f7\",\n fontSize: \"11px\",\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(122, 162, 247, 0.1)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n }}\n >\n Retry\n </button>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// Hitmarker System\n// ============================================================================\n\ninterface Hitmarker {\n id: number;\n x: number;\n y: number;\n}\n\nconst playHitmarkerSound = () => {\n try {\n // Embedded hitmarker sound as base64 data URL\n const hitmarkerDataUrl = 'data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA' +\n 'AAD/+1QAAAAAAAAAAAAAAAAAAAAA' +\n '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' +\n 'qqqqqqqqqqqqqqqqqqqqqqqqqqo=';\n\n const audio = new Audio(hitmarkerDataUrl);\n audio.volume = 0.3;\n audio.play().catch(() => createSyntheticHitmarkerSound());\n } catch {\n createSyntheticHitmarkerSound();\n }\n};\n\nconst createSyntheticHitmarkerSound = () => {\n try {\n const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\n const oscillator1 = audioContext.createOscillator();\n const oscillator2 = audioContext.createOscillator();\n const gainNode1 = audioContext.createGain();\n const gainNode2 = audioContext.createGain();\n const masterGain = audioContext.createGain();\n\n oscillator1.connect(gainNode1);\n oscillator2.connect(gainNode2);\n gainNode1.connect(masterGain);\n gainNode2.connect(masterGain);\n masterGain.connect(audioContext.destination);\n\n oscillator1.frequency.setValueAtTime(1800, audioContext.currentTime);\n oscillator1.frequency.exponentialRampToValueAtTime(900, audioContext.currentTime + 0.08);\n oscillator2.frequency.setValueAtTime(3600, audioContext.currentTime);\n oscillator2.frequency.exponentialRampToValueAtTime(1800, audioContext.currentTime + 0.04);\n\n oscillator1.type = 'triangle';\n oscillator2.type = 'sine';\n\n gainNode1.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode1.gain.linearRampToValueAtTime(0.4, audioContext.currentTime + 0.002);\n gainNode1.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.12);\n\n gainNode2.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode2.gain.linearRampToValueAtTime(0.3, audioContext.currentTime + 0.001);\n gainNode2.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.06);\n\n masterGain.gain.setValueAtTime(0.5, audioContext.currentTime);\n\n const startTime = audioContext.currentTime;\n const stopTime = startTime + 0.15;\n\n oscillator1.start(startTime);\n oscillator2.start(startTime);\n oscillator1.stop(stopTime);\n oscillator2.stop(stopTime);\n } catch {\n // Audio context not available\n }\n};\n\n// ============================================================================\n// IdleScreen Component (Main Export)\n// ============================================================================\n\nexport interface IdleScreenProps {\n /** Stream status (OFFLINE, INITIALIZING, ERROR, etc.) */\n status?: StreamStatus;\n /** Human-readable message */\n message?: string;\n /** Processing percentage (for INITIALIZING) */\n percentage?: number;\n /** Error message */\n error?: string;\n /** Callback for retry button */\n onRetry?: () => void;\n}\n\nexport const IdleScreen: React.FC<IdleScreenProps> = ({\n status,\n message = \"Waiting for stream...\",\n percentage,\n error,\n onRetry,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [hitmarkers, setHitmarkers] = useState<Hitmarker[]>([]);\n\n const createHitmarker = (e: { clientX: number; clientY: number }) => {\n if (!containerRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n const newHitmarker: Hitmarker = {\n id: Date.now() + Math.random(),\n x,\n y,\n };\n\n setHitmarkers(prev => [...prev, newHitmarker]);\n playHitmarkerSound();\n\n setTimeout(() => {\n setHitmarkers(prev => prev.filter(h => h.id !== newHitmarker.id));\n }, 600);\n };\n\n // Inject CSS animations\n useEffect(() => {\n const styleId = 'idle-screen-animations';\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes fadeInOut {\n 0%, 100% { opacity: 0.6; }\n 50% { opacity: 0.9; }\n }\n @keyframes logoPulse {\n 0%, 100% { opacity: 0.15; transform: scale(1); }\n 50% { opacity: 0.25; transform: scale(1.05); }\n }\n @keyframes floatUp {\n 0% { transform: translateY(100vh) rotate(0deg); opacity: 0; }\n 10% { opacity: 0.6; }\n 90% { opacity: 0.6; }\n 100% { transform: translateY(-100px) rotate(360deg); opacity: 0; }\n }\n @keyframes gradientShift {\n 0%, 100% { background-position: 0% 50%; }\n 50% { background-position: 100% 50%; }\n }\n @keyframes hitmarkerFade45 {\n 0% { opacity: 1; transform: translate(-50%, -50%) rotate(45deg) scale(0.5); }\n 20% { opacity: 1; transform: translate(-50%, -50%) rotate(45deg) scale(1.2); }\n 100% { opacity: 0; transform: translate(-50%, -50%) rotate(45deg) scale(1); }\n }\n @keyframes hitmarkerFadeNeg45 {\n 0% { opacity: 1; transform: translate(-50%, -50%) rotate(-45deg) scale(0.5); }\n 20% { opacity: 1; transform: translate(-50%, -50%) rotate(-45deg) scale(1.2); }\n 100% { opacity: 0; transform: translate(-50%, -50%) rotate(-45deg) scale(1); }\n }\n `;\n document.head.appendChild(style);\n }\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"fw-player-root\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 5,\n background: `\n linear-gradient(135deg,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,\n hsl(var(--tn-bg, 233 23% 17%)) 25%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,\n hsl(var(--tn-bg, 233 23% 17%)) 75%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 100%\n )\n `,\n backgroundSize: \"400% 400%\",\n animation: \"gradientShift 16s ease-in-out infinite\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderRadius: \"0\",\n userSelect: \"none\",\n } as React.CSSProperties}\n >\n {/* Hitmarkers */}\n {hitmarkers.map(hitmarker => (\n <div\n key={hitmarker.id}\n style={{\n position: \"absolute\",\n left: `${hitmarker.x}px`,\n top: `${hitmarker.y}px`,\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\",\n zIndex: 100,\n width: \"40px\",\n height: \"40px\",\n }}\n >\n <div style={{ position: \"absolute\", top: \"25%\", left: \"25%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(45deg)\", animation: \"hitmarkerFade45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n <div style={{ position: \"absolute\", top: \"25%\", left: \"75%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(-45deg)\", animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n <div style={{ position: \"absolute\", top: \"75%\", left: \"25%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(-45deg)\", animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n <div style={{ position: \"absolute\", top: \"75%\", left: \"75%\", width: \"12px\", height: \"3px\", backgroundColor: \"#ffffff\", transform: \"translate(-50%, -50%) rotate(45deg)\", animation: \"hitmarkerFade45 0.6s ease-out forwards\", boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\", borderRadius: \"1px\" }} />\n </div>\n ))}\n\n {/* Floating particles */}\n {[...Array(12)].map((_, index) => (\n <div\n key={`particle-${index}`}\n style={{\n position: \"absolute\",\n left: `${Math.random() * 100}%`,\n width: `${Math.random() * 4 + 2}px`,\n height: `${Math.random() * 4 + 2}px`,\n borderRadius: \"50%\",\n background: [\"#7aa2f7\", \"#bb9af7\", \"#9ece6a\", \"#73daca\", \"#7dcfff\", \"#f7768e\", \"#e0af68\", \"#2ac3de\"][index % 8],\n opacity: 0,\n animation: `floatUp ${8 + Math.random() * 4}s linear infinite`,\n animationDelay: `${Math.random() * 8}s`,\n pointerEvents: \"none\",\n }}\n />\n ))}\n\n {/* Animated bubbles */}\n {[...Array(8)].map((_, index) => (\n <AnimatedBubble key={index} index={index} />\n ))}\n\n {/* Center logo */}\n <CenterLogo containerRef={containerRef as React.RefObject<HTMLDivElement>} onHitmarker={createHitmarker} />\n\n {/* DVD Logo */}\n <DvdLogo parentRef={containerRef as React.RefObject<HTMLDivElement>} scale={0.08} />\n\n {/* Status overlay */}\n <StatusOverlay\n status={status}\n message={message}\n percentage={percentage}\n error={error}\n onRetry={onRetry}\n />\n\n {/* Overlay texture */}\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: `\n radial-gradient(circle at 20% 80%, rgba(122, 162, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(187, 154, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(158, 206, 106, 0.02) 0%, transparent 50%)\n `,\n pointerEvents: \"none\",\n }}\n />\n </div>\n );\n};\n\nexport default IdleScreen;\n","import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface TitleOverlayProps {\n title?: string | null;\n description?: string | null;\n isVisible: boolean;\n className?: string;\n}\n\n/**\n * Title/description overlay that appears at the top of the player.\n * Visible on hover or when paused - controlled by parent via isVisible prop.\n */\nconst TitleOverlay: React.FC<TitleOverlayProps> = ({\n title,\n description,\n isVisible,\n className,\n}) => {\n // Don't render if no content\n if (!title && !description) return null;\n\n return (\n <div\n className={cn(\n \"fw-title-overlay absolute inset-x-0 top-0 z-20 pointer-events-none\",\n \"bg-gradient-to-b from-black/70 via-black/40 to-transparent\",\n \"px-4 py-3 transition-opacity duration-300\",\n isVisible ? \"opacity-100\" : \"opacity-0\",\n className\n )}\n >\n {title && (\n <h2 className=\"text-white text-sm font-medium truncate max-w-[80%]\">\n {title}\n </h2>\n )}\n {description && (\n <p className=\"text-white/70 text-xs mt-0.5 line-clamp-2 max-w-[70%]\">\n {description}\n </p>\n )}\n </div>\n );\n};\n\nexport default TitleOverlay;\n","import React from \"react\";\nimport {\n cn,\n type ContentMetadata,\n type PlaybackQuality,\n type StreamState,\n} from \"@livepeer-frameworks/player-core\";\n\ninterface StatsPanelProps {\n isOpen: boolean;\n onClose: () => void;\n metadata?: ContentMetadata | null;\n streamState?: StreamState | null;\n quality?: PlaybackQuality | null;\n videoElement?: HTMLVideoElement | null;\n protocol?: string;\n nodeId?: string;\n geoDistance?: number;\n}\n\n/**\n * \"Stats for nerds\" panel showing detailed playback information.\n * Toggleable overlay with technical details about the stream.\n */\nconst StatsPanel: React.FC<StatsPanelProps> = ({\n isOpen,\n onClose,\n metadata,\n streamState,\n quality,\n videoElement,\n protocol,\n nodeId,\n geoDistance,\n}) => {\n if (!isOpen) return null;\n\n // Video element stats\n const video = videoElement;\n const currentRes = video ? `${video.videoWidth}x${video.videoHeight}` : \"—\";\n const buffered = video && video.buffered.length > 0\n ? (video.buffered.end(video.buffered.length - 1) - video.currentTime).toFixed(1)\n : \"—\";\n const playbackRate = video?.playbackRate?.toFixed(2) ?? \"1.00\";\n\n // Quality monitor stats\n const qualityScore = quality?.score?.toFixed(0) ?? \"—\";\n const bitrateKbps = quality?.bitrate\n ? `${(quality.bitrate / 1000).toFixed(0)} kbps`\n : \"—\";\n const frameDropRate = quality?.frameDropRate?.toFixed(1) ?? \"—\";\n const stallCount = quality?.stallCount ?? 0;\n const latency = quality?.latency ? `${Math.round(quality.latency)} ms` : \"—\";\n\n // Stream state stats\n const viewers = metadata?.viewers ?? \"—\";\n const streamStatus = streamState?.status ?? metadata?.status ?? \"—\";\n\n const mistInfo = metadata?.mist ?? streamState?.streamInfo;\n\n const deriveTracksFromMist = () => {\n const mistTracks = mistInfo?.meta?.tracks;\n if (!mistTracks) return undefined;\n return Object.values(mistTracks).map(t => ({\n type: t.type,\n codec: t.codec,\n width: t.width,\n height: t.height,\n bitrate: typeof t.bps === \"number\" ? Math.round(t.bps) : undefined,\n fps: typeof t.fpks === \"number\" ? t.fpks / 1000 : undefined,\n channels: t.channels,\n sampleRate: t.rate,\n }));\n };\n\n // Format track info from metadata\n const formatTracks = () => {\n const tracks = metadata?.tracks ?? deriveTracksFromMist();\n if (!tracks?.length) return \"—\";\n return tracks.map(t => {\n if (t.type === \"video\") {\n const resolution = t.width && t.height ? `${t.width}x${t.height}` : \"?\";\n const bitrate = t.bitrate ? `${Math.round(t.bitrate / 1000)}kbps` : \"?\";\n return `${t.codec ?? \"?\"} ${resolution}@${bitrate}`;\n }\n const channels = t.channels ? `${t.channels}ch` : \"?\";\n return `${t.codec ?? \"?\"} ${channels}`;\n }).join(\", \");\n };\n\n const mistType = mistInfo?.type ?? \"—\";\n const mistBufferWindow = mistInfo?.meta?.buffer_window;\n const mistLastMs = mistInfo?.lastms;\n const mistUnixOffset = mistInfo?.unixoffset;\n\n const stats = [\n { label: \"Resolution\", value: currentRes },\n { label: \"Buffer\", value: `${buffered}s` },\n { label: \"Latency\", value: latency },\n { label: \"Bitrate\", value: bitrateKbps },\n { label: \"Quality Score\", value: `${qualityScore}/100` },\n { label: \"Frame Drop Rate\", value: `${frameDropRate}%` },\n { label: \"Stalls\", value: String(stallCount) },\n { label: \"Playback Rate\", value: `${playbackRate}x` },\n { label: \"Protocol\", value: protocol ?? \"—\" },\n { label: \"Node\", value: nodeId ?? \"—\" },\n { label: \"Geo Distance\", value: geoDistance ? `${geoDistance.toFixed(0)} km` : \"—\" },\n { label: \"Viewers\", value: String(viewers) },\n { label: \"Status\", value: streamStatus },\n { label: \"Tracks\", value: formatTracks() },\n { label: \"Mist Type\", value: mistType },\n { label: \"Mist Buffer Window\", value: mistBufferWindow != null ? String(mistBufferWindow) : \"—\" },\n { label: \"Mist Lastms\", value: mistLastMs != null ? String(mistLastMs) : \"—\" },\n { label: \"Mist Unixoffset\", value: mistUnixOffset != null ? String(mistUnixOffset) : \"—\" },\n ];\n\n // Add metadata fields if available\n if (metadata?.title) {\n stats.unshift({ label: \"Title\", value: metadata.title });\n }\n if (metadata?.durationSeconds) {\n const mins = Math.floor(metadata.durationSeconds / 60);\n const secs = metadata.durationSeconds % 60;\n stats.push({ label: \"Duration\", value: `${mins}:${String(secs).padStart(2, \"0\")}` });\n }\n if (metadata?.recordingSizeBytes) {\n const mb = (metadata.recordingSizeBytes / (1024 * 1024)).toFixed(1);\n stats.push({ label: \"Size\", value: `${mb} MB` });\n }\n\n return (\n <div\n className={cn(\n \"fw-stats-panel absolute top-2 right-2 z-30\",\n \"bg-black border border-white/10 rounded\",\n \"text-white text-xs font-mono\",\n \"max-w-[320px] max-h-[80%] overflow-auto\",\n \"shadow-lg\"\n )}\n style={{ backgroundColor: '#000000' }} // Inline fallback for opaque background\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-white/10\">\n <span className=\"text-white/70 text-[10px] uppercase tracking-wider\">\n Stats Overlay\n </span>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"text-white/50 hover:text-white transition-colors p-1 -mr-1\"\n aria-label=\"Close stats panel\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M2 2l8 8M10 2l-8 8\" />\n </svg>\n </button>\n </div>\n\n {/* Stats grid */}\n <div className=\"px-3 py-2 space-y-1\">\n {stats.map(({ label, value }) => (\n <div key={label} className=\"flex justify-between gap-4\">\n <span className=\"text-white/50 shrink-0\">{label}</span>\n <span className=\"text-white/90 truncate text-right\">{value}</span>\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default StatsPanel;\n","/**\n * usePlayerController.ts\n *\n * React hook that wraps PlayerController for declarative usage.\n * Manages the complete player lifecycle and provides reactive state.\n */\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport {\n PlayerController,\n type PlayerControllerConfig,\n type PlayerState,\n type StreamState,\n type StreamInfo,\n type PlaybackQuality,\n type ContentEndpoints,\n type ContentMetadata,\n} from '@livepeer-frameworks/player-core';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UsePlayerControllerConfig extends Omit<PlayerControllerConfig, 'playerManager'> {\n /** Enable/disable the hook */\n enabled?: boolean;\n /** Callback when state changes */\n onStateChange?: (state: PlayerState) => void;\n /** Callback when stream state changes */\n onStreamStateChange?: (state: StreamState) => void;\n /** Callback when error occurs */\n onError?: (error: string) => void;\n /** Callback when ready */\n onReady?: (videoElement: HTMLVideoElement) => void;\n}\n\nexport interface PlayerControllerState {\n /** Current player state */\n state: PlayerState;\n /** Stream state (for live streams) */\n streamState: StreamState | null;\n /** Resolved endpoints */\n endpoints: ContentEndpoints | null;\n /** Content metadata */\n metadata: ContentMetadata | null;\n /** Video element (null if not ready) */\n videoElement: HTMLVideoElement | null;\n /** Current time */\n currentTime: number;\n /** Duration */\n duration: number;\n /** Is playing */\n isPlaying: boolean;\n /** Is paused */\n isPaused: boolean;\n /** Is buffering */\n isBuffering: boolean;\n /** Is muted */\n isMuted: boolean;\n /** Volume (0-1) */\n volume: number;\n /** Error text */\n error: string | null;\n /** Is passive error */\n isPassiveError: boolean;\n /** Has playback ever started */\n hasPlaybackStarted: boolean;\n /** Is holding speed (2x gesture) */\n isHoldingSpeed: boolean;\n /** Current hold speed */\n holdSpeed: number;\n /** Is hovering (controls visible) */\n isHovering: boolean;\n /** Should show controls */\n shouldShowControls: boolean;\n /** Is loop enabled */\n isLoopEnabled: boolean;\n /** Is fullscreen */\n isFullscreen: boolean;\n /** Is PiP active */\n isPiPActive: boolean;\n /** Is effectively live (live or DVR recording) */\n isEffectivelyLive: boolean;\n /** Should show idle screen */\n shouldShowIdleScreen: boolean;\n /** Current player info */\n currentPlayerInfo: { name: string; shortname: string } | null;\n /** Current source info */\n currentSourceInfo: { url: string; type: string } | null;\n /** Playback quality metrics */\n playbackQuality: PlaybackQuality | null;\n /** Subtitles enabled */\n subtitlesEnabled: boolean;\n /** Available quality levels */\n qualities: Array<{ id: string; label: string; bitrate?: number; width?: number; height?: number; isAuto?: boolean; active?: boolean }>;\n /** Available text/caption tracks */\n textTracks: Array<{ id: string; label: string; language?: string; active: boolean }>;\n /** Stream info for player selection (sources + tracks) */\n streamInfo: StreamInfo | null;\n}\n\nexport interface UsePlayerControllerReturn {\n /** Container ref to attach to your player container div */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Current state (reactive) */\n state: PlayerControllerState;\n /** Controller instance (for direct method calls) */\n controller: PlayerController | null;\n /** Play */\n play: () => Promise<void>;\n /** Pause */\n pause: () => void;\n /** Toggle play/pause */\n togglePlay: () => void;\n /** Seek to time */\n seek: (time: number) => void;\n /** Seek by delta */\n seekBy: (delta: number) => void;\n /** Jump to live edge (for live streams) */\n jumpToLive: () => void;\n /** Set volume */\n setVolume: (volume: number) => void;\n /** Toggle mute */\n toggleMute: () => void;\n /** Toggle loop */\n toggleLoop: () => void;\n /** Toggle fullscreen */\n toggleFullscreen: () => Promise<void>;\n /** Toggle PiP */\n togglePiP: () => Promise<void>;\n /** Toggle subtitles */\n toggleSubtitles: () => void;\n /** Clear error */\n clearError: () => void;\n /** Retry playback */\n retry: () => Promise<void>;\n /** Reload player */\n reload: () => Promise<void>;\n /** Get qualities */\n getQualities: () => Array<{ id: string; label: string; bitrate?: number }>;\n /** Select quality */\n selectQuality: (id: string) => void;\n /** Handle mouse enter (for controls visibility) */\n handleMouseEnter: () => void;\n /** Handle mouse leave (for controls visibility) */\n handleMouseLeave: () => void;\n /** Handle mouse move (for controls visibility) */\n handleMouseMove: () => void;\n /** Handle touch start (for controls visibility) */\n handleTouchStart: () => void;\n /** Set dev mode options (force player, type, source) */\n setDevModeOptions: (options: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n playbackMode?: 'auto' | 'low-latency' | 'quality' | 'vod';\n }) => Promise<void>;\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialState: PlayerControllerState = {\n state: 'booting',\n streamState: null,\n endpoints: null,\n metadata: null,\n videoElement: null,\n currentTime: 0,\n duration: NaN,\n isPlaying: false,\n isPaused: true,\n isBuffering: false,\n isMuted: true,\n volume: 1,\n error: null,\n isPassiveError: false,\n hasPlaybackStarted: false,\n isHoldingSpeed: false,\n holdSpeed: 2,\n isHovering: false,\n shouldShowControls: false,\n isLoopEnabled: false,\n isFullscreen: false,\n isPiPActive: false,\n isEffectivelyLive: false,\n shouldShowIdleScreen: true,\n currentPlayerInfo: null,\n currentSourceInfo: null,\n playbackQuality: null,\n subtitlesEnabled: false,\n qualities: [],\n textTracks: [],\n streamInfo: null,\n};\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function usePlayerController(\n config: UsePlayerControllerConfig\n): UsePlayerControllerReturn {\n const { enabled = true, onStateChange, onStreamStateChange, onError, onReady, ...controllerConfig } = config;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const controllerRef = useRef<PlayerController | null>(null);\n const [state, setState] = useState<PlayerControllerState>(initialState);\n\n // Stable config ref for effect dependencies\n const configRef = useRef(controllerConfig);\n configRef.current = controllerConfig;\n\n // Create and attach controller\n useEffect(() => {\n if (!enabled) return;\n\n const container = containerRef.current;\n if (!container) return;\n\n // Create controller\n const controller = new PlayerController({\n contentId: configRef.current.contentId,\n contentType: configRef.current.contentType,\n endpoints: configRef.current.endpoints,\n gatewayUrl: configRef.current.gatewayUrl,\n mistUrl: configRef.current.mistUrl,\n authToken: configRef.current.authToken,\n autoplay: configRef.current.autoplay,\n muted: configRef.current.muted,\n controls: configRef.current.controls,\n poster: configRef.current.poster,\n debug: configRef.current.debug,\n });\n\n controllerRef.current = controller;\n\n // Subscribe to events\n const unsubs: Array<() => void> = [];\n\n // Sync state from controller - called on video events\n const syncState = () => {\n if (!controllerRef.current) return;\n const c = controllerRef.current;\n setState(prev => ({\n ...prev,\n isPlaying: c.isPlaying(),\n isPaused: c.isPaused(),\n isBuffering: c.isBuffering(),\n isMuted: c.isMuted(),\n volume: c.getVolume(),\n hasPlaybackStarted: c.hasPlaybackStarted(),\n shouldShowControls: c.shouldShowControls(),\n shouldShowIdleScreen: c.shouldShowIdleScreen(),\n playbackQuality: c.getPlaybackQuality(),\n isLoopEnabled: c.isLoopEnabled(),\n subtitlesEnabled: c.isSubtitlesEnabled(),\n qualities: c.getQualities(),\n streamInfo: c.getStreamInfo(),\n }));\n };\n\n unsubs.push(controller.on('stateChange', ({ state: newState }) => {\n setState(prev => ({ ...prev, state: newState }));\n onStateChange?.(newState);\n }));\n\n unsubs.push(controller.on('streamStateChange', ({ state: streamState }) => {\n setState(prev => ({\n ...prev,\n streamState,\n metadata: controller.getMetadata(),\n isEffectivelyLive: controller.isEffectivelyLive(),\n shouldShowIdleScreen: controller.shouldShowIdleScreen(),\n }));\n onStreamStateChange?.(streamState);\n }));\n\n unsubs.push(controller.on('timeUpdate', ({ currentTime, duration }) => {\n setState(prev => ({ ...prev, currentTime, duration }));\n }));\n\n unsubs.push(controller.on('error', ({ error }) => {\n setState(prev => ({\n ...prev,\n error,\n isPassiveError: controller.isPassiveError(),\n }));\n onError?.(error);\n }));\n\n unsubs.push(controller.on('errorCleared', () => {\n setState(prev => ({ ...prev, error: null, isPassiveError: false }));\n }));\n\n unsubs.push(controller.on('ready', ({ videoElement }) => {\n setState(prev => ({\n ...prev,\n videoElement,\n endpoints: controller.getEndpoints(),\n metadata: controller.getMetadata(),\n streamInfo: controller.getStreamInfo(),\n isEffectivelyLive: controller.isEffectivelyLive(),\n shouldShowIdleScreen: controller.shouldShowIdleScreen(),\n currentPlayerInfo: controller.getCurrentPlayerInfo(),\n currentSourceInfo: controller.getCurrentSourceInfo(),\n qualities: controller.getQualities(),\n }));\n onReady?.(videoElement);\n\n // Set up video event listeners AFTER video is ready\n // syncState is defined below - this closure captures it\n const handleVideoEvent = () => {\n if (controllerRef.current?.shouldSuppressVideoEvents?.()) return;\n syncState();\n };\n videoElement.addEventListener('play', handleVideoEvent);\n videoElement.addEventListener('pause', handleVideoEvent);\n videoElement.addEventListener('waiting', handleVideoEvent);\n videoElement.addEventListener('playing', handleVideoEvent);\n unsubs.push(() => {\n videoElement.removeEventListener('play', handleVideoEvent);\n videoElement.removeEventListener('pause', handleVideoEvent);\n videoElement.removeEventListener('waiting', handleVideoEvent);\n videoElement.removeEventListener('playing', handleVideoEvent);\n });\n }));\n\n unsubs.push(controller.on('playerSelected', ({ player: _player, source }) => {\n setState(prev => ({\n ...prev,\n currentPlayerInfo: controller.getCurrentPlayerInfo(),\n currentSourceInfo: { url: source.url, type: source.type },\n qualities: controller.getQualities(),\n }));\n }));\n\n unsubs.push(controller.on('volumeChange', ({ volume, muted }) => {\n setState(prev => ({ ...prev, volume, isMuted: muted }));\n }));\n\n unsubs.push(controller.on('loopChange', ({ isLoopEnabled }) => {\n setState(prev => ({ ...prev, isLoopEnabled }));\n }));\n\n unsubs.push(controller.on('fullscreenChange', ({ isFullscreen }) => {\n setState(prev => ({ ...prev, isFullscreen }));\n }));\n\n unsubs.push(controller.on('pipChange', ({ isPiP }) => {\n setState(prev => ({ ...prev, isPiPActive: isPiP }));\n }));\n\n unsubs.push(controller.on('holdSpeedStart', ({ speed }) => {\n setState(prev => ({ ...prev, isHoldingSpeed: true, holdSpeed: speed }));\n }));\n\n unsubs.push(controller.on('holdSpeedEnd', () => {\n setState(prev => ({ ...prev, isHoldingSpeed: false }));\n }));\n\n unsubs.push(controller.on('hoverStart', () => {\n setState(prev => ({ ...prev, isHovering: true, shouldShowControls: true }));\n }));\n\n unsubs.push(controller.on('hoverEnd', () => {\n setState(prev => ({\n ...prev,\n isHovering: false,\n shouldShowControls: controller.shouldShowControls(),\n }));\n }));\n\n unsubs.push(controller.on('captionsChange', ({ enabled }) => {\n setState(prev => ({ ...prev, subtitlesEnabled: enabled }));\n }));\n\n // Attach controller to container\n // Note: Video event listeners are set up in the 'ready' handler above\n controller.attach(container).catch(err => {\n console.warn('[usePlayerController] Attach failed:', err);\n });\n\n // Set initial state\n setState(prev => ({\n ...prev,\n isLoopEnabled: controller.isLoopEnabled(),\n }));\n\n return () => {\n unsubs.forEach(fn => fn());\n controller.destroy();\n controllerRef.current = null;\n setState(initialState);\n };\n }, [enabled, config.contentId, config.contentType]); // Re-create on content change\n\n // Stable action callbacks\n const play = useCallback(async () => {\n await controllerRef.current?.play();\n }, []);\n\n const pause = useCallback(() => {\n controllerRef.current?.pause();\n }, []);\n\n const togglePlay = useCallback(() => {\n controllerRef.current?.togglePlay();\n }, []);\n\n const seek = useCallback((time: number) => {\n controllerRef.current?.seek(time);\n }, []);\n\n const seekBy = useCallback((delta: number) => {\n controllerRef.current?.seekBy(delta);\n }, []);\n\n const setVolume = useCallback((volume: number) => {\n controllerRef.current?.setVolume(volume);\n }, []);\n\n const toggleMute = useCallback(() => {\n controllerRef.current?.toggleMute();\n }, []);\n\n const toggleLoop = useCallback(() => {\n controllerRef.current?.toggleLoop();\n }, []);\n\n const toggleFullscreen = useCallback(async () => {\n await controllerRef.current?.toggleFullscreen();\n }, []);\n\n const togglePiP = useCallback(async () => {\n await controllerRef.current?.togglePictureInPicture();\n }, []);\n\n const toggleSubtitles = useCallback(() => {\n controllerRef.current?.toggleSubtitles();\n }, []);\n\n const clearError = useCallback(() => {\n controllerRef.current?.clearError();\n setState(prev => ({ ...prev, error: null, isPassiveError: false }));\n }, []);\n\n const jumpToLive = useCallback(() => {\n controllerRef.current?.jumpToLive();\n }, []);\n\n const retry = useCallback(async () => {\n await controllerRef.current?.retry();\n }, []);\n\n const reload = useCallback(async () => {\n await controllerRef.current?.reload();\n }, []);\n\n const getQualities = useCallback(() => {\n return controllerRef.current?.getQualities() ?? [];\n }, []);\n\n const selectQuality = useCallback((id: string) => {\n controllerRef.current?.selectQuality(id);\n }, []);\n\n const handleMouseEnter = useCallback(() => {\n controllerRef.current?.handleMouseEnter();\n }, []);\n\n const handleMouseLeave = useCallback(() => {\n controllerRef.current?.handleMouseLeave();\n }, []);\n\n const handleMouseMove = useCallback(() => {\n controllerRef.current?.handleMouseMove();\n }, []);\n\n const handleTouchStart = useCallback(() => {\n controllerRef.current?.handleTouchStart();\n }, []);\n\n const setDevModeOptions = useCallback(async (options: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n playbackMode?: 'auto' | 'low-latency' | 'quality' | 'vod';\n }) => {\n await controllerRef.current?.setDevModeOptions(options);\n }, []);\n\n return {\n containerRef,\n state,\n controller: controllerRef.current,\n play,\n pause,\n togglePlay,\n seek,\n seekBy,\n jumpToLive,\n setVolume,\n toggleMute,\n toggleLoop,\n toggleFullscreen,\n togglePiP,\n toggleSubtitles,\n clearError,\n retry,\n reload,\n getQualities,\n selectQuality,\n handleMouseEnter,\n handleMouseLeave,\n handleMouseMove,\n handleTouchStart,\n setDevModeOptions,\n };\n}\n\nexport default usePlayerController;\n","/**\n * PlayerContext\n *\n * React context for sharing PlayerController state across components.\n * Follows the \"context wraps hook\" pattern (same as npm_studio).\n *\n * Usage:\n * ```tsx\n * <PlayerProvider config={{ contentId: 'stream-1', contentType: 'live' }}>\n * <PlayerControls />\n * </PlayerProvider>\n * ```\n */\n\nimport React, { createContext, useContext, type ReactNode } from 'react';\nimport {\n usePlayerController,\n type UsePlayerControllerConfig,\n type UsePlayerControllerReturn,\n} from '../hooks/usePlayerController';\n\n// Context holds the full hook return value\nconst PlayerContext = createContext<UsePlayerControllerReturn | null>(null);\n\nexport interface PlayerProviderProps {\n children: ReactNode;\n /** Configuration for the player controller */\n config: UsePlayerControllerConfig;\n}\n\n/**\n * Provider component that wraps Player and its controls.\n * Calls usePlayerController internally and shares state via context.\n */\nexport function PlayerProvider({ children, config }: PlayerProviderProps) {\n const playerController = usePlayerController(config);\n\n return (\n <PlayerContext.Provider value={playerController}>\n {children}\n </PlayerContext.Provider>\n );\n}\n\n/**\n * Hook to access player context.\n * Must be used within a PlayerProvider.\n */\nexport function usePlayerContext(): UsePlayerControllerReturn {\n const context = useContext(PlayerContext);\n if (!context) {\n throw new Error('usePlayerContext must be used within a PlayerProvider');\n }\n return context;\n}\n\n/**\n * Hook to optionally access player context.\n * Returns null if not within a PlayerProvider (no error thrown).\n * Use this when component may or may not be within a PlayerProvider.\n */\nexport function usePlayerContextOptional(): UsePlayerControllerReturn | null {\n return useContext(PlayerContext);\n}\n\n// Export context for advanced use cases\nexport { PlayerContext };\n\n// Type exports\nexport type { UsePlayerControllerReturn as PlayerContextValue };\nexport type { UsePlayerControllerConfig };\n","import * as React from \"react\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nexport interface SliderProps extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {\n showTrack?: boolean;\n trackClassName?: string;\n thumbClassName?: string;\n /** Show thumb only on hover (YouTube-style) - but always shows a smaller thumb when not hovered */\n hoverThumb?: boolean;\n /** Use cyan accent color (matches SeekBar styling) */\n accentColor?: boolean;\n}\n\nconst Slider = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, SliderProps>(\n ({ className, trackClassName, thumbClassName, showTrack = true, hoverThumb: _hoverThumb = false, accentColor = false, orientation = \"horizontal\", ...props }, ref) => {\n // Colors based on accentColor prop\n const rangeColorClass = accentColor ? \"bg-[hsl(var(--tn-cyan,195_100%_50%))]\" : \"bg-white/90\";\n const thumbColorClass = accentColor ? \"bg-[hsl(var(--tn-cyan,195_100%_50%))]\" : \"bg-white\";\n\n return (\n <SliderPrimitive.Root\n ref={ref}\n orientation={orientation}\n className={cn(\n \"group relative flex touch-none select-none items-center cursor-pointer\",\n orientation === \"horizontal\" ? \"w-full h-5\" : \"h-full flex-col w-5\",\n className\n )}\n {...props}\n >\n {showTrack && (\n <SliderPrimitive.Track\n className={cn(\n \"absolute rounded-full bg-white/30 transition-all duration-150\",\n orientation === \"horizontal\"\n ? \"inset-x-0 h-1 group-hover:h-1.5\"\n : \"inset-y-0 w-1 group-hover:w-1.5\",\n trackClassName\n )}\n >\n <SliderPrimitive.Range\n className={cn(\n \"absolute rounded-full transition-all duration-150\",\n orientation === \"horizontal\" ? \"h-full\" : \"w-full bottom-0\",\n rangeColorClass\n )}\n />\n </SliderPrimitive.Track>\n )}\n <SliderPrimitive.Thumb\n className={cn(\n \"block rounded-full border-0 cursor-pointer shadow-md transition-all duration-150\",\n \"w-2.5 h-2.5 group-hover:w-3.5 group-hover:h-3.5\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n thumbColorClass,\n thumbClassName\n )}\n />\n </SliderPrimitive.Root>\n );\n }\n);\nSlider.displayName = SliderPrimitive.Root.displayName;\n\nexport { Slider };\n","import React, { useRef, useState, useCallback, useMemo } from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface SeekBarProps {\n /** Current playback time in seconds */\n currentTime: number;\n /** Total duration in seconds */\n duration: number;\n /** Buffered time ranges from video element */\n buffered?: TimeRanges;\n /** Whether seeking is allowed */\n disabled?: boolean;\n /** Called when user seeks to a new time */\n onSeek?: (time: number) => void;\n /** Additional class names */\n className?: string;\n /** Whether this is a live stream */\n isLive?: boolean;\n /** For live: start of seekable DVR window (seconds) */\n seekableStart?: number;\n /** For live: current live edge position (seconds) */\n liveEdge?: number;\n /** Defer seeking until drag release */\n commitOnRelease?: boolean;\n}\n\n/**\n * Industry-standard video seek bar with:\n * - Track background\n * - Buffer progress indicator\n * - Playback progress indicator\n * - Thumb on hover\n * - Time tooltip on hover (relative for live: \"-5:30\")\n */\nconst SeekBar: React.FC<SeekBarProps> = ({\n currentTime,\n duration,\n buffered,\n disabled = false,\n onSeek,\n className,\n isLive = false,\n seekableStart = 0,\n liveEdge,\n commitOnRelease = false,\n}) => {\n const trackRef = useRef<HTMLDivElement>(null);\n const [isHovering, setIsHovering] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n const [dragTime, setDragTime] = useState<number | null>(null);\n const dragTimeRef = useRef<number | null>(null);\n const [hoverPosition, setHoverPosition] = useState(0);\n const [hoverTime, setHoverTime] = useState(0);\n\n // Effective live edge (use provided or fall back to duration)\n const effectiveLiveEdge = liveEdge ?? duration;\n\n // Seekable window size\n const seekableWindow = effectiveLiveEdge - seekableStart;\n\n // Calculate progress percentage\n // For live streams: position within the DVR window\n // For VOD: position within total duration\n const displayTime = dragTime ?? currentTime;\n const progressPercent = useMemo(() => {\n if (isLive && seekableWindow > 0) {\n const positionInWindow = displayTime - seekableStart;\n return Math.min(100, Math.max(0, (positionInWindow / seekableWindow) * 100));\n }\n if (!Number.isFinite(duration) || duration <= 0) return 0;\n return Math.min(100, Math.max(0, (displayTime / duration) * 100));\n }, [displayTime, duration, isLive, seekableStart, seekableWindow]);\n\n // Calculate buffered segments as array of {start%, end%} for accurate display\n const bufferedSegments = useMemo(() => {\n if (!buffered || buffered.length === 0) return [];\n\n const rangeEnd = isLive ? effectiveLiveEdge : duration;\n const rangeStart = isLive ? seekableStart : 0;\n const rangeSize = rangeEnd - rangeStart;\n\n if (!Number.isFinite(rangeSize) || rangeSize <= 0) return [];\n\n const segments: Array<{ startPercent: number; endPercent: number }> = [];\n for (let i = 0; i < buffered.length; i++) {\n const start = buffered.start(i);\n const end = buffered.end(i);\n\n // Calculate position relative to the seekable range\n const relativeStart = start - rangeStart;\n const relativeEnd = end - rangeStart;\n\n segments.push({\n startPercent: Math.min(100, Math.max(0, (relativeStart / rangeSize) * 100)),\n endPercent: Math.min(100, Math.max(0, (relativeEnd / rangeSize) * 100)),\n });\n }\n return segments;\n }, [buffered, duration, isLive, seekableStart, effectiveLiveEdge]);\n\n // Format time as MM:SS or HH:MM:SS (for VOD)\n const formatTime = useCallback((seconds: number): string => {\n if (!Number.isFinite(seconds) || seconds < 0) return \"0:00\";\n const total = Math.floor(seconds);\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const secs = total % 60;\n if (hours > 0) {\n return `${hours}:${String(minutes).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n }\n return `${minutes}:${String(secs).padStart(2, \"0\")}`;\n }, []);\n\n // Format relative time for live streams (e.g., \"-5:30\" = 5:30 behind live edge)\n const formatLiveTime = useCallback((seconds: number, edge: number): string => {\n const behindSeconds = edge - seconds;\n if (behindSeconds < 1) return \"LIVE\";\n const total = Math.floor(behindSeconds);\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const secs = total % 60;\n if (hours > 0) {\n return `-${hours}:${String(minutes).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n }\n return `-${minutes}:${String(secs).padStart(2, \"0\")}`;\n }, []);\n\n // Calculate time from mouse position\n // For live: maps position to time within DVR window\n const getTimeFromPosition = useCallback((clientX: number): number => {\n if (!trackRef.current) return 0;\n const rect = trackRef.current.getBoundingClientRect();\n const x = clientX - rect.left;\n const percent = Math.min(1, Math.max(0, x / rect.width));\n\n // Live with valid seekable window\n if (isLive && Number.isFinite(seekableWindow) && seekableWindow > 0) {\n return seekableStart + (percent * seekableWindow);\n }\n\n // VOD with finite duration\n if (Number.isFinite(duration) && duration > 0) {\n return percent * duration;\n }\n\n // Fallback: If we have liveEdge, use it even if not marked as live\n // This handles cases where duration is Infinity but we have valid seekable data\n if (liveEdge !== undefined && Number.isFinite(liveEdge) && liveEdge > 0) {\n const start = Number.isFinite(seekableStart) ? seekableStart : 0;\n const window = liveEdge - start;\n if (window > 0) {\n return start + (percent * window);\n }\n }\n\n // Last resort: use currentTime as a baseline\n return percent * (currentTime || 1);\n }, [duration, isLive, seekableStart, seekableWindow, liveEdge, currentTime]);\n\n // Handle mouse move for hover preview\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!trackRef.current || disabled) return;\n const rect = trackRef.current.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const percent = Math.min(1, Math.max(0, x / rect.width));\n setHoverPosition(percent * 100);\n setHoverTime(getTimeFromPosition(e.clientX));\n }, [disabled, getTimeFromPosition]);\n\n // Handle click to seek\n const handleClick = useCallback((e: React.MouseEvent) => {\n if (disabled) return;\n if (!isLive && !Number.isFinite(duration)) return;\n const time = getTimeFromPosition(e.clientX);\n onSeek?.(time);\n setDragTime(null);\n dragTimeRef.current = null;\n }, [disabled, duration, isLive, getTimeFromPosition, onSeek]);\n\n // Handle drag start\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (disabled) return;\n if (!isLive && !Number.isFinite(duration)) return;\n e.preventDefault();\n setIsDragging(true);\n\n const handleDragMove = (moveEvent: MouseEvent) => {\n const time = getTimeFromPosition(moveEvent.clientX);\n if (commitOnRelease) {\n setDragTime(time);\n dragTimeRef.current = time;\n } else {\n onSeek?.(time);\n }\n };\n\n const handleDragEnd = () => {\n setIsDragging(false);\n document.removeEventListener(\"mousemove\", handleDragMove);\n document.removeEventListener(\"mouseup\", handleDragEnd);\n const pending = dragTimeRef.current;\n if (commitOnRelease && pending !== null) {\n onSeek?.(pending);\n setDragTime(null);\n dragTimeRef.current = null;\n }\n };\n\n document.addEventListener(\"mousemove\", handleDragMove);\n document.addEventListener(\"mouseup\", handleDragEnd);\n\n // Initial seek\n const time = getTimeFromPosition(e.clientX);\n if (commitOnRelease) {\n setDragTime(time);\n dragTimeRef.current = time;\n } else {\n onSeek?.(time);\n }\n }, [disabled, duration, isLive, getTimeFromPosition, onSeek, commitOnRelease]);\n\n const showThumb = isHovering || isDragging;\n const canShowTooltip = isLive ? seekableWindow > 0 : Number.isFinite(duration);\n\n return (\n <div\n ref={trackRef}\n className={cn(\n \"group relative w-full h-6 flex items-center cursor-pointer\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className\n )}\n onMouseEnter={() => !disabled && setIsHovering(true)}\n onMouseLeave={() => { setIsHovering(false); setIsDragging(false); }}\n onMouseMove={handleMouseMove}\n onClick={handleClick}\n onMouseDown={handleMouseDown}\n role=\"slider\"\n aria-label=\"Seek\"\n aria-valuemin={isLive ? seekableStart : 0}\n aria-valuemax={isLive ? effectiveLiveEdge : (duration || 100)}\n aria-valuenow={displayTime}\n aria-valuetext={isLive ? formatLiveTime(displayTime, effectiveLiveEdge) : formatTime(displayTime)}\n tabIndex={disabled ? -1 : 0}\n >\n {/* Track background */}\n <div className={cn(\n \"fw-seek-track\",\n isDragging && \"fw-seek-track--active\"\n )}>\n {/* Buffered segments - show actual buffered ranges */}\n {bufferedSegments.map((segment, index) => (\n <div\n key={index}\n className=\"fw-seek-buffered\"\n style={{\n left: `${segment.startPercent}%`,\n width: `${segment.endPercent - segment.startPercent}%`,\n }}\n />\n ))}\n {/* Playback progress */}\n <div\n className=\"fw-seek-progress\"\n style={{ width: `${progressPercent}%` }}\n />\n </div>\n\n {/* Thumb */}\n <div\n className={cn(\n \"fw-seek-thumb\",\n showThumb ? \"fw-seek-thumb--active\" : \"fw-seek-thumb--hidden\"\n )}\n style={{ left: `${progressPercent}%` }}\n />\n\n {/* Hover time tooltip */}\n {isHovering && !isDragging && canShowTooltip && (\n <div\n className=\"fw-seek-tooltip\"\n style={{ left: `${hoverPosition}%` }}\n >\n {isLive ? formatLiveTime(hoverTime, effectiveLiveEdge) : formatTime(hoverTime)}\n </div>\n )}\n </div>\n );\n};\n\nexport default SeekBar;\n","import React from 'react';\n\ninterface IconProps {\n size?: number;\n color?: string;\n className?: string;\n}\n\nexport const PlayIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M8 5v14l11-7z\"\n fill={color}\n />\n </svg>\n);\n\nexport const PauseIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" fill={color} />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" fill={color} />\n </svg>\n);\n\nexport const SkipBackIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n {/* Circular rewind arrow */}\n <path\n d=\"M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"\n fill={color}\n />\n <text x=\"12\" y=\"15\" fontSize=\"7\" fontWeight=\"bold\" fill={color} textAnchor=\"middle\">10</text>\n </svg>\n);\n\nexport const SkipForwardIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n {/* Circular forward arrow */}\n <path\n d=\"M12 5V1l5 5-5 5V7c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6h2c0 4.42-3.58 8-8 8s-8-3.58-8-8 3.58-8 8-8z\"\n fill={color}\n />\n <text x=\"12\" y=\"15\" fontSize=\"7\" fontWeight=\"bold\" fill={color} textAnchor=\"middle\">10</text>\n </svg>\n);\n\nexport const VolumeUpIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <polygon points=\"11,5 6,9 2,9 2,15 6,15 11,19\" fill={color} />\n <path\n d=\"M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const VolumeOffIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <polygon points=\"11,5 6,9 2,9 2,15 6,15 11,19\" fill={color} />\n <line x1=\"23\" y1=\"9\" x2=\"17\" y2=\"15\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" />\n <line x1=\"17\" y1=\"9\" x2=\"23\" y2=\"15\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n);\n\nexport const FullscreenIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3m8 0h3a2 2 0 0 0 2-2v-3\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const FullscreenExitIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const PictureInPictureIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\" stroke={color} strokeWidth=\"2\" fill=\"none\" />\n <rect x=\"8\" y=\"10\" width=\"10\" height=\"6\" rx=\"1\" ry=\"1\" fill={color} />\n </svg>\n);\n\nexport const ClosedCaptionsIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" ry=\"2\" stroke={color} strokeWidth=\"2\" fill=\"none\" />\n <path\n d=\"M8 10c0-.6.4-1 1-1h1c.6 0 1 .4 1 1v4c0 .6-.4 1-1 1H9c-.6 0-1-.4-1-1v-4zM14 10c0-.6.4-1 1-1h1c.6 0 1 .4 1 1v4c0 .6-.4 1-1 1h-1c-.6 0-1-.4-1-1v-4z\"\n fill={color}\n />\n </svg>\n);\n\nexport const LiveIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"3\" fill={color} />\n <path\n d=\"M12 1v6M12 17v6M4.22 4.22l4.24 4.24M15.54 15.54l4.24 4.24M1 12h6M17 12h6M4.22 19.78l4.24-4.24M15.54 8.46l4.24-4.24\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nexport const SettingsIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\n// Compound PlayPause icon that switches based on state\ninterface PlayPauseIconProps extends IconProps {\n isPlaying?: boolean;\n}\n\nexport const PlayPauseIcon: React.FC<PlayPauseIconProps> = ({ isPlaying, ...props }) => {\n return isPlaying ? <PauseIcon {...props} /> : <PlayIcon {...props} />;\n};\n\n// Volume icon that switches based on mute state\ninterface VolumeIconProps extends IconProps {\n isMuted?: boolean;\n}\n\nexport const VolumeIcon: React.FC<VolumeIconProps> = ({ isMuted, ...props }) => {\n return isMuted ? <VolumeOffIcon {...props} /> : <VolumeUpIcon {...props} />;\n};\n\n// Fullscreen icon that switches based on fullscreen state\ninterface FullscreenToggleIconProps extends IconProps {\n isFullscreen?: boolean;\n}\n\nexport const FullscreenToggleIcon: React.FC<FullscreenToggleIconProps> = ({ isFullscreen, ...props }) => {\n return isFullscreen ? <FullscreenExitIcon {...props} /> : <FullscreenIcon {...props} />;\n};\n\n// Stats icon (bar chart style - recognizable for \"stats for nerds\")\nexport const StatsIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"4\" y=\"13\" width=\"4\" height=\"7\" fill={color} />\n <rect x=\"10\" y=\"9\" width=\"4\" height=\"11\" fill={color} />\n <rect x=\"16\" y=\"4\" width=\"4\" height=\"16\" fill={color} />\n </svg>\n);\n\n// Seek to live/end icon (skip-to-end style: play triangle + bar)\nexport const SeekToLiveIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor', className = '' }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={className}\n aria-hidden=\"true\"\n >\n {/* Play triangle */}\n <path d=\"M5 5v14l11-7z\" fill={color} />\n {/* End bar */}\n <rect x=\"17\" y=\"5\" width=\"3\" height=\"14\" fill={color} />\n </svg>\n);","import React, { useEffect, useMemo, useState, useRef, useCallback } from \"react\";\nimport { usePlayerContextOptional } from \"../context/PlayerContext\";\nimport {\n cn,\n // Seeking utilities from core\n SPEED_PRESETS,\n isMediaStreamSource,\n supportsPlaybackRate as coreSupportsPlaybackRate,\n calculateSeekableRange,\n canSeekStream,\n calculateLiveThresholds,\n calculateIsNearLive,\n isLiveContent,\n // Time formatting from core\n formatTimeDisplay,\n} from \"@livepeer-frameworks/player-core\";\nimport { Slider } from \"../ui/slider\";\nimport SeekBar from \"./SeekBar\";\nimport {\n FullscreenToggleIcon,\n PlayPauseIcon,\n SeekToLiveIcon,\n SkipBackIcon,\n SkipForwardIcon,\n VolumeIcon,\n SettingsIcon\n} from \"./Icons\";\nimport type { MistStreamInfo, PlaybackMode } from \"../types\";\n\ninterface PlayerControlsProps {\n currentTime: number;\n duration: number;\n isVisible?: boolean;\n className?: string;\n onSeek?: (time: number) => void;\n showStatsButton?: boolean;\n isStatsOpen?: boolean;\n onStatsToggle?: () => void;\n /** Live MistServer stream info - drives control visibility based on server metadata */\n mistStreamInfo?: MistStreamInfo;\n /** Disable all controls (e.g., while player is initializing) */\n disabled?: boolean;\n /** Current playback mode */\n playbackMode?: PlaybackMode;\n /** Callback when playback mode changes */\n onModeChange?: (mode: PlaybackMode) => void;\n /** Current source protocol type (e.g., 'whep', 'ws/video/mp4', 'html5/application/vnd.apple.mpegurl') */\n sourceType?: string;\n /** Content-type based live flag (for mode selector visibility, separate from seek bar isLive) */\n isContentLive?: boolean;\n /** Video element - passed from parent hook */\n videoElement?: HTMLVideoElement | null;\n /** Available quality levels - passed from parent hook */\n qualities?: Array<{ id: string; label: string; bitrate?: number; width?: number; height?: number; isAuto?: boolean; active?: boolean }>;\n /** Callback to select quality */\n onSelectQuality?: (id: string) => void;\n /** Is player muted */\n isMuted?: boolean;\n /** Current volume (0-1) */\n volume?: number;\n /** Callback for volume change */\n onVolumeChange?: (volume: number) => void;\n /** Toggle mute callback */\n onToggleMute?: () => void;\n /** Is playing */\n isPlaying?: boolean;\n /** Toggle play/pause callback */\n onTogglePlay?: () => void;\n /** Toggle fullscreen callback */\n onToggleFullscreen?: () => void;\n /** Is fullscreen */\n isFullscreen?: boolean;\n /** Is loop enabled */\n isLoopEnabled?: boolean;\n /** Toggle loop callback */\n onToggleLoop?: () => void;\n /** Jump to live edge callback */\n onJumpToLive?: () => void;\n}\n\n\nconst PlayerControls: React.FC<PlayerControlsProps> = ({\n currentTime,\n duration,\n isVisible = true,\n _className,\n onSeek,\n mistStreamInfo,\n disabled = false,\n playbackMode = 'auto',\n onModeChange,\n sourceType,\n isContentLive,\n videoElement: propVideoElement,\n qualities: propQualities = [],\n onSelectQuality,\n isMuted: propIsMuted,\n volume: propVolume,\n onVolumeChange,\n onToggleMute,\n isPlaying: propIsPlaying,\n onTogglePlay,\n onToggleFullscreen,\n isFullscreen: propIsFullscreen,\n isLoopEnabled: _propIsLoopEnabled,\n onToggleLoop: _onToggleLoop,\n onJumpToLive,\n}) => {\n // Context fallback - prefer props passed from parent over context\n // Context provides UsePlayerControllerReturn which has state.videoElement and controller\n const ctx = usePlayerContextOptional();\n const contextVideo = ctx?.state?.videoElement;\n const player = ctx?.controller;\n\n // Robust video element detection - prefer prop, then context, then DOM query\n const [video, setVideo] = useState<HTMLVideoElement | null>(null);\n const videoCheckIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const findVideoElement = useCallback((): HTMLVideoElement | null => {\n if (propVideoElement) return propVideoElement;\n if (contextVideo) return contextVideo;\n if (player?.getVideoElement?.()) return player.getVideoElement();\n const domVideo = document.querySelector('.fw-player-video') as HTMLVideoElement | null\n ?? document.querySelector('[data-player-container=\"true\"] video') as HTMLVideoElement | null\n ?? document.querySelector('.fw-player-container video') as HTMLVideoElement | null;\n return domVideo;\n }, [propVideoElement, contextVideo, player]);\n\n useEffect(() => {\n const updateVideo = () => {\n const v = findVideoElement();\n if (v && v !== video) {\n setVideo(v);\n }\n };\n updateVideo();\n if (!video) {\n videoCheckIntervalRef.current = setInterval(() => {\n const v = findVideoElement();\n if (v) {\n setVideo(v);\n if (videoCheckIntervalRef.current) {\n clearInterval(videoCheckIntervalRef.current);\n videoCheckIntervalRef.current = null;\n }\n }\n }, 100);\n setTimeout(() => {\n if (videoCheckIntervalRef.current) {\n clearInterval(videoCheckIntervalRef.current);\n videoCheckIntervalRef.current = null;\n }\n }, 5000);\n }\n return () => {\n if (videoCheckIntervalRef.current) {\n clearInterval(videoCheckIntervalRef.current);\n videoCheckIntervalRef.current = null;\n }\n };\n }, [contextVideo, player, findVideoElement, video]);\n\n const mistTracks = mistStreamInfo?.meta?.tracks;\n\n // Quality selection priority:\n // 1. Player-provided qualities (HLS.js/DASH.js levels with correct numeric indices)\n // 2. Mist track metadata (for players that don't provide quality API)\n // This fixes a critical bug where Mist track IDs (e.g., \"a1\", \"v0\") were passed to\n // HLS/DASH players which expect numeric indices (e.g., \"0\", \"1\", \"2\")\n // Quality levels - prefer props, then player API, then Mist tracks\n const qualities = useMemo(() => {\n // Priority 1: Props from parent (usePlayerController hook)\n if (propQualities && propQualities.length > 0) {\n return propQualities;\n }\n\n // Priority 2: Player's quality API\n const playerQualities = player?.getQualities?.();\n if (playerQualities && playerQualities.length > 0) {\n return playerQualities;\n }\n\n // Fallback to Mist track metadata for players without quality API\n if (mistTracks) {\n return Object.entries(mistTracks)\n .filter(([, t]) => t.type === 'video')\n .map(([id, t]) => ({\n id,\n label: t.height ? `${t.height}p` : t.codec,\n width: t.width,\n height: t.height,\n bitrate: t.bps,\n }))\n .sort((a, b) => (b.height || 0) - (a.height || 0));\n }\n return [];\n }, [propQualities, player, mistTracks]);\n\n const textTracks = player?.getTextTracks?.() ?? [];\n\n // Internal state - used as fallback when props not provided\n const [internalIsPlaying, setInternalIsPlaying] = useState(false);\n const [internalIsMuted, setInternalIsMuted] = useState(false);\n const [internalIsFullscreen, setInternalIsFullscreen] = useState(false);\n const [hasAudio, setHasAudio] = useState(true);\n const [buffered, setBuffered] = useState<TimeRanges | undefined>(undefined);\n const [internalVolume, setInternalVolume] = useState<number>(() => {\n if (!video) return 100;\n return Math.round(video.volume * 100);\n });\n const [playbackRate, setPlaybackRate] = useState<number>(() => video?.playbackRate ?? 1);\n\n // Derived state - prefer props over internal state\n const isPlaying = propIsPlaying ?? internalIsPlaying;\n const isMuted = propIsMuted ?? internalIsMuted;\n const isFullscreen = propIsFullscreen ?? internalIsFullscreen;\n const volumeValue = propVolume !== undefined ? Math.round(propVolume * 100) : internalVolume;\n const [qualityValue, setQualityValue] = useState<string>(\"auto\");\n const [captionValue, setCaptionValue] = useState<string>(\"none\");\n const [isSettingsOpen, setIsSettingsOpen] = useState(false);\n // Hysteresis state for Live badge - prevents flip-flopping\n const [isNearLiveState, setIsNearLiveState] = useState(true);\n\n // Close settings menu when clicking outside\n useEffect(() => {\n if (!isSettingsOpen) return;\n\n const handleWindowClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (target && !target.closest('.fw-settings-menu')) {\n setIsSettingsOpen(false);\n }\n };\n\n // Use setTimeout to avoid immediate close from the same click that opened it\n const timeoutId = setTimeout(() => {\n window.addEventListener('click', handleWindowClick);\n }, 0);\n\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener('click', handleWindowClick);\n };\n }, [isSettingsOpen]);\n\n // Core utility-based calculations\n const deriveBufferWindowMs = useCallback((tracks?: Record<string, { firstms?: number; lastms?: number }>) => {\n if (!tracks) return undefined;\n const list = Object.values(tracks);\n if (list.length === 0) return undefined;\n const firstmsValues = list.map(t => t.firstms).filter((v): v is number => v !== undefined);\n const lastmsValues = list.map(t => t.lastms).filter((v): v is number => v !== undefined);\n if (firstmsValues.length === 0 || lastmsValues.length === 0) return undefined;\n const firstms = Math.max(...firstmsValues);\n const lastms = Math.min(...lastmsValues);\n const window = lastms - firstms;\n if (!Number.isFinite(window) || window <= 0) return undefined;\n return window;\n }, []);\n\n const bufferWindowMs = mistStreamInfo?.meta?.buffer_window\n ?? deriveBufferWindowMs(mistStreamInfo?.meta?.tracks as Record<string, { firstms?: number; lastms?: number }> | undefined);\n\n const isLive = useMemo(() => isLiveContent(isContentLive, mistStreamInfo, duration),\n [isContentLive, mistStreamInfo, duration]);\n\n const isWebRTC = useMemo(() => isMediaStreamSource(video), [video]);\n\n const supportsPlaybackRate = useMemo(() => coreSupportsPlaybackRate(video), [video]);\n\n // Seekable range using core calculation (allow controller override)\n const allowMediaStreamDvr = isMediaStreamSource(video) &&\n (bufferWindowMs !== undefined && bufferWindowMs > 0) &&\n (sourceType !== 'whep' && sourceType !== 'webrtc');\n const { seekableStart: calcSeekableStart, liveEdge: calcLiveEdge } = useMemo(() => calculateSeekableRange({\n isLive,\n video,\n mistStreamInfo,\n currentTime,\n duration,\n allowMediaStreamDvr,\n }), [isLive, video, mistStreamInfo, currentTime, duration, allowMediaStreamDvr]);\n const controllerSeekableStart = player?.getSeekableStart?.();\n const controllerLiveEdge = player?.getLiveEdge?.();\n const useControllerRange = Number.isFinite(controllerSeekableStart) &&\n Number.isFinite(controllerLiveEdge) &&\n (controllerLiveEdge as number) >= (controllerSeekableStart as number) &&\n ((controllerLiveEdge as number) > 0 || (controllerSeekableStart as number) > 0);\n const seekableStart = useControllerRange ? (controllerSeekableStart as number) : calcSeekableStart;\n const liveEdge = useControllerRange ? (controllerLiveEdge as number) : calcLiveEdge;\n\n const hasDvrWindow = isLive && Number.isFinite(liveEdge) && Number.isFinite(seekableStart) && liveEdge > seekableStart;\n const commitOnRelease = isLive;\n\n // Live thresholds with buffer window scaling\n const liveThresholds = useMemo(() =>\n calculateLiveThresholds(sourceType, isWebRTC, bufferWindowMs),\n [sourceType, isWebRTC, bufferWindowMs]);\n\n // Can seek - prefer PlayerController's computed value (includes player-specific canSeek)\n // Fall back to utility function when controller not available\n const baseCanSeek = useMemo(() => {\n // PlayerController already computes canSeek with player-specific logic\n if (player && typeof (player as any).canSeekStream === 'function') {\n return (player as any).canSeekStream();\n }\n // Fallback when no controller\n return canSeekStream({\n video,\n isLive,\n duration,\n bufferWindowMs,\n });\n }, [video, isLive, duration, bufferWindowMs, player]);\n const canSeek = baseCanSeek && (!isLive || hasDvrWindow);\n\n // Hysteresis for live badge - using core calculation\n useEffect(() => {\n if (!isLive) {\n setIsNearLiveState(true);\n return;\n }\n const newState = calculateIsNearLive(currentTime, liveEdge, liveThresholds, isNearLiveState);\n if (newState !== isNearLiveState) {\n setIsNearLiveState(newState);\n }\n }, [isLive, liveEdge, currentTime, liveThresholds, isNearLiveState]);\n\n // Track if we've already seeked to live on initial playback\n const hasSeekToLiveRef = useRef(false);\n\n // Sync internal state from video element (only when props not provided)\n useEffect(() => {\n if (!video) return;\n const updatePlayingState = () => setInternalIsPlaying(!video.paused);\n const updateMutedState = () => {\n const muted = video.muted || video.volume === 0;\n setInternalIsMuted(muted);\n setInternalVolume(Math.round(video.volume * 100));\n };\n const updateFullscreenState = () => {\n if (typeof document !== \"undefined\") setInternalIsFullscreen(!!document.fullscreenElement);\n };\n const updatePlaybackRate = () => setPlaybackRate(video.playbackRate);\n\n updatePlayingState();\n updateMutedState();\n updateFullscreenState();\n updatePlaybackRate();\n\n video.addEventListener(\"play\", updatePlayingState);\n video.addEventListener(\"pause\", updatePlayingState);\n video.addEventListener(\"playing\", updatePlayingState);\n video.addEventListener(\"volumechange\", updateMutedState);\n video.addEventListener(\"ratechange\", updatePlaybackRate);\n if (typeof document !== \"undefined\") document.addEventListener(\"fullscreenchange\", updateFullscreenState);\n\n return () => {\n video.removeEventListener(\"play\", updatePlayingState);\n video.removeEventListener(\"pause\", updatePlayingState);\n video.removeEventListener(\"playing\", updatePlayingState);\n video.removeEventListener(\"volumechange\", updateMutedState);\n video.removeEventListener(\"ratechange\", updatePlaybackRate);\n if (typeof document !== \"undefined\") document.removeEventListener(\"fullscreenchange\", updateFullscreenState);\n };\n }, [video, isLive]);\n\n // Reset the seek-to-live flag when video element changes (new stream)\n useEffect(() => {\n hasSeekToLiveRef.current = false;\n }, [video]);\n\n useEffect(() => {\n const activeTrack = textTracks.find((track) => track.active);\n setCaptionValue(activeTrack ? activeTrack.id : \"none\");\n }, [textTracks]);\n\n // Track buffered ranges for SeekBar\n useEffect(() => {\n if (!video) return;\n const updateBuffered = () => {\n const next = player?.getBufferedRanges?.() ?? video.buffered;\n setBuffered(next);\n };\n updateBuffered();\n video.addEventListener(\"progress\", updateBuffered);\n video.addEventListener(\"loadeddata\", updateBuffered);\n return () => {\n video.removeEventListener(\"progress\", updateBuffered);\n video.removeEventListener(\"loadeddata\", updateBuffered);\n };\n }, [video]);\n\n useEffect(() => {\n if (!video) { setHasAudio(true); return; }\n const checkAudio = () => {\n if (video.srcObject instanceof MediaStream) {\n const audioTracks = video.srcObject.getAudioTracks();\n setHasAudio(audioTracks.length > 0);\n return;\n }\n const videoAny = video as any;\n if (videoAny.audioTracks && videoAny.audioTracks.length !== undefined) {\n setHasAudio(videoAny.audioTracks.length > 0);\n return;\n }\n setHasAudio(true);\n };\n checkAudio();\n video.addEventListener(\"loadedmetadata\", checkAudio);\n return () => video.removeEventListener(\"loadedmetadata\", checkAudio);\n }, [video]);\n\n const handlePlayPause = () => {\n if (disabled) return;\n // Prefer prop callback from usePlayerController\n if (onTogglePlay) {\n onTogglePlay();\n return;\n }\n // Fallback: direct video/player manipulation\n if (!video && !player) return;\n const isPaused = player?.isPaused?.() ?? video?.paused ?? true;\n if (isPaused) {\n if (player?.play) player.play().catch(() => {});\n else if (video) video.play().catch(() => {});\n } else {\n if (player?.pause) player.pause();\n else if (video) video.pause();\n }\n };\n\n const handleSkipBack = () => {\n const newTime = Math.max(0, currentTime - 10);\n if (onSeek) {\n onSeek(newTime);\n return;\n }\n const v = findVideoElement();\n if (v) v.currentTime = newTime;\n };\n\n const handleSkipForward = () => {\n const maxTime = Number.isFinite(duration) ? duration : currentTime + 10;\n const newTime = Math.min(maxTime, currentTime + 10);\n if (onSeek) {\n onSeek(newTime);\n return;\n }\n const v = findVideoElement();\n if (v) v.currentTime = newTime;\n };\n\n const handleMute = () => {\n if (disabled) return;\n // Prefer prop callback from usePlayerController\n if (onToggleMute) {\n onToggleMute();\n return;\n }\n // Fallback: direct video/player manipulation\n const v = video ?? document.querySelector('.fw-player-video') as HTMLVideoElement | null;\n if (!v) return;\n const nextMuted = !(player?.isMuted?.() ?? v.muted);\n player?.setMuted?.(nextMuted);\n v.muted = nextMuted;\n setInternalIsMuted(nextMuted);\n if (nextMuted) setInternalVolume(0);\n else setInternalVolume(Math.round(v.volume * 100));\n };\n\n const handleVolumeChange = (value: number[]) => {\n if (disabled) return;\n const next = Math.max(0, Math.min(100, value[0] ?? 0));\n // Prefer prop callback from usePlayerController\n if (onVolumeChange) {\n onVolumeChange(next / 100);\n return;\n }\n // Fallback: direct video manipulation\n const v = video ?? document.querySelector('.fw-player-video') as HTMLVideoElement | null;\n if (!v) return;\n v.volume = next / 100;\n v.muted = next === 0;\n setInternalVolume(next);\n setInternalIsMuted(next === 0);\n };\n\n const handleFullscreen = () => {\n if (disabled) return;\n // Prefer prop callback from usePlayerController\n if (onToggleFullscreen) {\n onToggleFullscreen();\n return;\n }\n // Fallback: direct DOM manipulation\n if (typeof document === \"undefined\") return;\n const container = document.querySelector('[data-player-container=\"true\"]') as HTMLElement | null;\n if (!container) return;\n if (document.fullscreenElement) document.exitFullscreen().catch(() => {});\n else container.requestFullscreen().catch(() => {});\n };\n\n const handleGoLive = () => {\n if (disabled) return;\n if (onJumpToLive) {\n onJumpToLive();\n return;\n }\n player?.jumpToLive?.();\n };\n\n const handleSpeedChange = (value: string) => {\n if (disabled) return;\n const rate = Number(value);\n setPlaybackRate(rate);\n // Use player API if available, fall back to direct video element\n if (player?.setPlaybackRate) {\n player.setPlaybackRate(rate);\n } else {\n const v = findVideoElement();\n if (v) v.playbackRate = rate;\n }\n };\n\n const handleQualityChange = (value: string) => {\n if (disabled) return;\n setQualityValue(value);\n // Prefer prop callback from usePlayerController\n if (onSelectQuality) {\n onSelectQuality(value);\n return;\n }\n // Fallback: direct player manipulation\n player?.selectQuality?.(value);\n };\n\n const handleCaptionChange = (value: string) => {\n if (disabled) return;\n setCaptionValue(value);\n if (value === \"none\") player?.selectTextTrack?.(null);\n else player?.selectTextTrack?.(value);\n };\n\n // Time display - using core formatTimeDisplay\n const timeDisplay = useMemo(() => formatTimeDisplay({\n isLive,\n currentTime,\n duration,\n liveEdge,\n seekableStart,\n unixoffset: mistStreamInfo?.unixoffset,\n }), [isLive, currentTime, duration, liveEdge, seekableStart, mistStreamInfo?.unixoffset]);\n\n const [isVolumeHovered, setIsVolumeHovered] = useState(false);\n const [isVolumeFocused, setIsVolumeFocused] = useState(false);\n const isVolumeExpanded = isVolumeHovered || isVolumeFocused;\n\n return (\n <div className={cn(\n \"fw-player-surface fw-controls-wrapper\",\n isVisible ? \"fw-controls-wrapper--visible\" : \"fw-controls-wrapper--hidden\"\n )}>\n {/* Bottom Row: Controls with SeekBar on top */}\n <div\n className=\"fw-control-bar pointer-events-auto\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* SeekBar - sits directly on top of control buttons */}\n {canSeek && (\n <div className=\"fw-seek-wrapper\">\n <SeekBar\n currentTime={currentTime}\n duration={duration}\n buffered={buffered}\n disabled={disabled}\n isLive={isLive}\n seekableStart={seekableStart}\n liveEdge={liveEdge}\n commitOnRelease={commitOnRelease}\n onSeek={(time) => {\n if (onSeek) {\n onSeek(time);\n } else if (video) {\n video.currentTime = time;\n }\n }}\n />\n </div>\n )}\n\n {/* Control buttons row */}\n <div className=\"fw-controls-row\">\n {/* Left: Controls & Time */}\n <div className=\"fw-controls-left\">\n <div className=\"fw-control-group\">\n <button type=\"button\" className=\"fw-btn-flush\" aria-label={isPlaying ? \"Pause\" : \"Play\"} onClick={handlePlayPause}>\n <PlayPauseIcon isPlaying={isPlaying} size={18} />\n </button>\n {canSeek && (\n <>\n <button type=\"button\" className=\"fw-btn-flush hidden sm:flex\" aria-label=\"Skip back 10 seconds\" onClick={handleSkipBack}>\n <SkipBackIcon size={16} />\n </button>\n <button type=\"button\" className=\"fw-btn-flush hidden sm:flex\" aria-label=\"Skip forward 10 seconds\" onClick={handleSkipForward}>\n <SkipForwardIcon size={16} />\n </button>\n </>\n )}\n </div>\n\n {/* Volume pill - cohesive hover element (slab style) */}\n <div\n className={cn(\n \"fw-volume-group\",\n isVolumeExpanded && \"fw-volume-group--expanded\",\n !hasAudio && \"fw-volume-group--disabled\"\n )}\n onMouseEnter={() => hasAudio && setIsVolumeHovered(true)}\n onMouseLeave={() => {\n setIsVolumeHovered(false);\n setIsVolumeFocused(false);\n }}\n onFocusCapture={() => hasAudio && setIsVolumeFocused(true)}\n onBlurCapture={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsVolumeFocused(false);\n }}\n onClick={(e) => {\n // Click on the pill (not slider) toggles mute\n if (hasAudio && e.target === e.currentTarget) {\n handleMute();\n }\n }}\n >\n {/* Volume icon - part of the pill */}\n <button\n type=\"button\"\n className=\"fw-volume-btn\"\n aria-label={!hasAudio ? \"No audio\" : (isMuted ? \"Unmute\" : \"Mute\")}\n onClick={hasAudio ? handleMute : undefined}\n disabled={!hasAudio}\n >\n <VolumeIcon isMuted={isMuted || !hasAudio} size={16} />\n </button>\n {/* Slider - expands within the pill */}\n <div className={cn(\n \"fw-volume-slider-wrapper\",\n isVolumeExpanded ? \"fw-volume-slider-wrapper--expanded\" : \"fw-volume-slider-wrapper--collapsed\"\n )}>\n <Slider\n orientation=\"horizontal\"\n aria-label=\"Volume\"\n max={100}\n step={1}\n value={[volumeValue]}\n onValueChange={handleVolumeChange}\n className=\"w-full\"\n disabled={!hasAudio}\n />\n </div>\n </div>\n\n <div className=\"fw-control-group\">\n <span className=\"fw-time-display\">\n {timeDisplay}\n </span>\n </div>\n\n {isLive && (\n <div className=\"fw-control-group\">\n <button\n type=\"button\"\n onClick={handleGoLive}\n disabled={!hasDvrWindow || isNearLiveState}\n className={cn(\n \"fw-live-badge\",\n (!hasDvrWindow || isNearLiveState) ? \"fw-live-badge--active\" : \"fw-live-badge--behind\"\n )}\n title={!hasDvrWindow ? \"Live only\" : (isNearLiveState ? \"At live edge\" : \"Jump to live\")}\n >\n LIVE\n {!isNearLiveState && hasDvrWindow && <SeekToLiveIcon size={10} />}\n </button>\n </div>\n )}\n </div>\n\n {/* Right Group: Settings, Fullscreen */}\n <div className=\"fw-controls-right\">\n <div className=\"fw-control-group relative\">\n <button\n type=\"button\"\n className={cn(\"fw-btn-flush group\", isSettingsOpen && \"fw-btn-flush--active\")}\n aria-label=\"Settings\"\n title=\"Settings\"\n onClick={() => setIsSettingsOpen(!isSettingsOpen)}\n >\n <SettingsIcon size={16} className=\"transition-transform group-hover:rotate-90\" />\n </button>\n\n {/* Settings Popup */}\n {isSettingsOpen && (\n <div className=\"fw-player-surface fw-settings-menu\">\n {/* Playback Mode - only show for live content (not VOD/clips) */}\n {onModeChange && isContentLive !== false && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Mode</div>\n <div className=\"fw-settings-options\">\n {(['auto', 'low-latency', 'quality'] as const).map((mode) => (\n <button\n key={mode}\n className={cn(\n \"fw-settings-btn\",\n playbackMode === mode && \"fw-settings-btn--active\"\n )}\n onClick={() => { onModeChange(mode); setIsSettingsOpen(false); }}\n >\n {mode === 'low-latency' ? 'Fast' : mode === 'quality' ? 'Stable' : 'Auto'}\n </button>\n ))}\n </div>\n </div>\n )}\n {supportsPlaybackRate && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Speed</div>\n <div className=\"fw-settings-options fw-settings-options--wrap\">\n {SPEED_PRESETS.map((rate) => (\n <button\n key={rate}\n className={cn(\n \"fw-settings-btn\",\n playbackRate === rate && \"fw-settings-btn--active\"\n )}\n onClick={() => { handleSpeedChange(String(rate)); setIsSettingsOpen(false); }}\n >\n {rate}x\n </button>\n ))}\n </div>\n </div>\n )}\n {qualities.length > 0 && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Quality</div>\n <div className=\"fw-settings-list\">\n <button\n className={cn(\n \"fw-settings-list-item\",\n qualityValue === 'auto' && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleQualityChange('auto'); setIsSettingsOpen(false); }}\n >\n Auto\n </button>\n {qualities.map((q) => (\n <button\n key={q.id}\n className={cn(\n \"fw-settings-list-item\",\n qualityValue === q.id && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleQualityChange(q.id); setIsSettingsOpen(false); }}\n >\n {q.label}\n </button>\n ))}\n </div>\n </div>\n )}\n {textTracks.length > 0 && (\n <div className=\"fw-settings-section\">\n <div className=\"fw-settings-label\">Captions</div>\n <div className=\"fw-settings-list\">\n <button\n className={cn(\n \"fw-settings-list-item\",\n captionValue === 'none' && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleCaptionChange('none'); setIsSettingsOpen(false); }}\n >\n Off\n </button>\n {textTracks.map((t) => (\n <button\n key={t.id}\n className={cn(\n \"fw-settings-list-item\",\n captionValue === t.id && \"fw-settings-list-item--active\"\n )}\n onClick={() => { handleCaptionChange(t.id); setIsSettingsOpen(false); }}\n >\n {t.label || t.id}\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"fw-control-group\">\n <button type=\"button\" className=\"fw-btn-flush\" aria-label=\"Toggle fullscreen\" onClick={handleFullscreen}>\n <FullscreenToggleIcon isFullscreen={isFullscreen} size={16} />\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default PlayerControls;\n","import React, { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport {\n cn,\n globalPlayerManager,\n QualityMonitor,\n type StreamInfo,\n type MistStreamInfo,\n type PlaybackMode,\n} from \"@livepeer-frameworks/player-core\";\n\n/** Short labels for source types */\nconst SOURCE_TYPE_LABELS: Record<string, string> = {\n \"html5/application/vnd.apple.mpegurl\": \"HLS\",\n \"dash/video/mp4\": \"DASH\",\n \"html5/video/mp4\": \"MP4\",\n \"html5/video/webm\": \"WebM\",\n \"whep\": \"WHEP\",\n \"mist/html\": \"Mist\",\n \"mist/legacy\": \"Auto\",\n \"ws/video/mp4\": \"MEWS\",\n};\n\nexport interface DevModePanelProps {\n /** Callback when user selects a combo (one-shot selection) */\n onSettingsChange: (settings: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n }) => void;\n /** Current playback mode */\n playbackMode?: PlaybackMode;\n /** Callback when playback mode changes */\n onModeChange?: (mode: PlaybackMode) => void;\n /** Callback to force player reload */\n onReload?: () => void;\n /** Stream info for getting all combinations (sources + tracks from MistServer) */\n streamInfo?: StreamInfo | null;\n /** MistServer stream metadata including tracks */\n mistStreamInfo?: MistStreamInfo | null;\n /** Current player info */\n currentPlayer?: {\n name: string;\n shortname: string;\n } | null;\n /** Current source info */\n currentSource?: {\n url: string;\n type: string;\n } | null;\n /** Video element for stats */\n videoElement?: HTMLVideoElement | null;\n /** Protocol/node info */\n protocol?: string;\n nodeId?: string;\n /** Whether the panel toggle is visible (hover state) */\n isVisible?: boolean;\n /** Controlled open state (if provided, component is controlled) */\n isOpen?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (isOpen: boolean) => void;\n}\n\n/**\n * DevModePanel - Advanced Settings overlay for testing player configurations\n * Similar to MistPlayer's skin: \"dev\" mode\n */\nconst DevModePanel: React.FC<DevModePanelProps> = ({\n onSettingsChange,\n playbackMode = 'auto',\n onModeChange,\n onReload,\n streamInfo,\n mistStreamInfo,\n currentPlayer,\n currentSource,\n videoElement,\n protocol,\n nodeId,\n isVisible: _isVisible = true,\n isOpen: controlledIsOpen,\n onOpenChange,\n}) => {\n // Support both controlled and uncontrolled modes\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = useCallback((value: boolean) => {\n if (onOpenChange) {\n onOpenChange(value);\n } else {\n setInternalIsOpen(value);\n }\n }, [onOpenChange]);\n const [activeTab, setActiveTab] = useState<\"config\" | \"stats\">(\"config\");\n const [, setCurrentComboIndex] = useState(0);\n const [hoveredComboIndex, setHoveredComboIndex] = useState<number | null>(null);\n const [tooltipAbove, setTooltipAbove] = useState(false);\n const [showDisabledPlayers, setShowDisabledPlayers] = useState(false);\n const comboListRef = useRef<HTMLDivElement>(null);\n\n // Quality monitoring for playback score\n const qualityMonitorRef = useRef<QualityMonitor | null>(null);\n const [playbackScore, setPlaybackScore] = useState<number>(1.0);\n const [qualityScore, setQualityScore] = useState<number>(100);\n const [stallCount, setStallCount] = useState<number>(0);\n const [frameDropRate, setFrameDropRate] = useState<number>(0);\n\n // Player-specific stats (from getStats())\n const [playerStats, setPlayerStats] = useState<any>(null);\n const statsIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // Start/stop quality monitoring based on video element\n useEffect(() => {\n if (videoElement && isOpen) {\n if (!qualityMonitorRef.current) {\n qualityMonitorRef.current = new QualityMonitor({\n sampleInterval: 500,\n onSample: (quality) => {\n setQualityScore(quality.score);\n setStallCount(quality.stallCount);\n setFrameDropRate(quality.frameDropRate);\n // Get playback score from monitor\n if (qualityMonitorRef.current) {\n setPlaybackScore(qualityMonitorRef.current.getPlaybackScore());\n }\n },\n });\n }\n qualityMonitorRef.current.start(videoElement);\n }\n\n return () => {\n if (qualityMonitorRef.current) {\n qualityMonitorRef.current.stop();\n }\n };\n }, [videoElement, isOpen]);\n\n // Poll player-specific stats when stats tab is open\n useEffect(() => {\n if (isOpen && activeTab === \"stats\") {\n const pollStats = async () => {\n try {\n const player = globalPlayerManager.getCurrentPlayer();\n if (player && player.getStats) {\n const stats = await player.getStats();\n if (stats) {\n setPlayerStats(stats);\n }\n }\n } catch {\n // Ignore errors\n }\n };\n\n // Poll immediately and then every 500ms\n pollStats();\n statsIntervalRef.current = setInterval(pollStats, 500);\n\n return () => {\n if (statsIntervalRef.current) {\n clearInterval(statsIntervalRef.current);\n statsIntervalRef.current = null;\n }\n };\n }\n }, [isOpen, activeTab]);\n\n // Get all player-source combinations with scores (including incompatible)\n // Uses cached results from PlayerManager - won't recompute if data unchanged\n const allCombinations = useMemo(() => {\n if (!streamInfo) return [];\n try {\n // getAllCombinations now includes all combos (compatible + incompatible)\n // and uses content-based caching - won't spam on every render\n return globalPlayerManager.getAllCombinations(streamInfo, playbackMode);\n } catch {\n return [];\n }\n }, [streamInfo, playbackMode]);\n\n // For backward compatibility (Next Option only cycles compatible)\n const combinations = useMemo(() => {\n return allCombinations.filter(c => c.compatible);\n }, [allCombinations]);\n\n // Find current active combo index based on current player/source (in allCombinations)\n const activeComboIndex = useMemo(() => {\n if (!currentPlayer || !currentSource || allCombinations.length === 0) return -1;\n return allCombinations.findIndex(\n (c) => c.player === currentPlayer.shortname && c.sourceType === currentSource.type\n );\n }, [currentPlayer, currentSource, allCombinations]);\n\n // Find index in compatible-only list for Next Option cycling\n const activeCompatibleIndex = useMemo(() => {\n if (!currentPlayer || !currentSource || combinations.length === 0) return -1;\n return combinations.findIndex(\n (c) => c.player === currentPlayer.shortname && c.sourceType === currentSource.type\n );\n }, [currentPlayer, currentSource, combinations]);\n\n const handleReload = useCallback(() => {\n // Just trigger reload - controller manages the state\n onReload?.();\n }, [onReload]);\n\n const handleNextCombo = useCallback(() => {\n if (combinations.length === 0) return;\n\n // Start from active combo or 0, then move to next (only cycles compatible)\n const startIdx = activeCompatibleIndex >= 0 ? activeCompatibleIndex : -1;\n const nextIdx = (startIdx + 1) % combinations.length;\n const combo = combinations[nextIdx];\n\n setCurrentComboIndex(nextIdx);\n onSettingsChange({\n forcePlayer: combo.player,\n forceType: combo.sourceType,\n forceSource: combo.sourceIndex,\n });\n }, [combinations, activeCompatibleIndex, onSettingsChange]);\n\n const handleSelectCombo = useCallback((index: number) => {\n const combo = allCombinations[index];\n if (!combo) return;\n\n // Allow selecting even incompatible combos in dev mode (for testing)\n setCurrentComboIndex(index);\n onSettingsChange({\n forcePlayer: combo.player,\n forceType: combo.sourceType,\n forceSource: combo.sourceIndex,\n });\n }, [allCombinations, onSettingsChange]);\n\n // Video stats - poll periodically when stats tab is open\n const [stats, setStats] = useState<{\n resolution: string;\n buffered: string;\n playbackRate: string;\n currentTime: string;\n duration: string;\n readyState: number;\n networkState: number;\n } | null>(null);\n\n useEffect(() => {\n if (!isOpen || activeTab !== \"stats\") return;\n\n const updateStats = () => {\n // Get fresh video element from player manager\n const player = globalPlayerManager.getCurrentPlayer();\n const v = player?.getVideoElement() || videoElement;\n if (!v) {\n setStats(null);\n return;\n }\n setStats({\n resolution: `${v.videoWidth}x${v.videoHeight}`,\n buffered:\n v.buffered.length > 0\n ? (v.buffered.end(v.buffered.length - 1) - v.currentTime).toFixed(1)\n : \"0\",\n playbackRate: v.playbackRate.toFixed(2),\n currentTime: v.currentTime.toFixed(1),\n duration: isFinite(v.duration) ? v.duration.toFixed(1) : \"live\",\n readyState: v.readyState,\n networkState: v.networkState,\n });\n };\n\n updateStats();\n const interval = setInterval(updateStats, 500);\n return () => clearInterval(interval);\n }, [isOpen, activeTab, videoElement]);\n\n // Panel is only rendered when open (no floating toggle button)\n if (!isOpen) {\n return null;\n }\n\n return (\n <div className=\"fw-dev-panel\">\n {/* Header with tabs */}\n <div className=\"fw-dev-header\">\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"config\")}\n className={cn(\"fw-dev-tab\", activeTab === \"config\" && \"fw-dev-tab--active\")}\n >\n Config\n </button>\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"stats\")}\n className={cn(\"fw-dev-tab\", activeTab === \"stats\" && \"fw-dev-tab--active\")}\n >\n Stats\n </button>\n <div className=\"fw-dev-spacer\" />\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n className=\"fw-dev-close\"\n aria-label=\"Close dev mode panel\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path d=\"M2 2l8 8M10 2l-8 8\" />\n </svg>\n </button>\n </div>\n\n {/* Config Tab */}\n {activeTab === \"config\" && (\n <div ref={comboListRef} className=\"fw-dev-body\">\n {/* Current State */}\n <div className=\"fw-dev-section\">\n <div className=\"fw-dev-label\">Active</div>\n <div className=\"fw-dev-value\">\n {currentPlayer?.name || \"None\"}{\" \"}\n <span className=\"fw-dev-value-arrow\">→</span>{\" \"}\n {SOURCE_TYPE_LABELS[currentSource?.type || \"\"] || currentSource?.type || \"—\"}\n </div>\n {nodeId && (\n <div className=\"fw-dev-value-muted\">Node: {nodeId}</div>\n )}\n </div>\n\n {/* Playback Mode Selector */}\n <div className=\"fw-dev-section\">\n <div className=\"fw-dev-label\">Playback Mode</div>\n <div className=\"fw-dev-mode-group\">\n {(['auto', 'low-latency', 'quality'] as const).map((mode) => (\n <button\n key={mode}\n type=\"button\"\n onClick={() => onModeChange?.(mode)}\n className={cn(\n \"fw-dev-mode-btn\",\n playbackMode === mode && \"fw-dev-mode-btn--active\"\n )}\n >\n {mode === 'low-latency' ? 'Low Lat' : mode.charAt(0).toUpperCase() + mode.slice(1)}\n </button>\n ))}\n </div>\n <div className=\"fw-dev-mode-desc\">\n {playbackMode === 'auto' && 'Balanced: MP4/WS → WHEP → HLS'}\n {playbackMode === 'low-latency' && 'WHEP/WebRTC first (<1s delay)'}\n {playbackMode === 'quality' && 'MP4/WS first, HLS fallback'}\n </div>\n </div>\n\n {/* Action buttons */}\n <div className=\"fw-dev-actions\">\n <button\n type=\"button\"\n onClick={handleReload}\n className=\"fw-dev-action-btn\"\n >\n Reload\n </button>\n <button\n type=\"button\"\n onClick={handleNextCombo}\n className=\"fw-dev-action-btn\"\n >\n Next Option\n </button>\n </div>\n\n {/* Combo list */}\n <div className=\"fw-dev-section\" style={{ padding: 0, borderBottom: 0 }}>\n <div className=\"fw-dev-list-header\">\n <span className=\"fw-dev-list-title\">\n Player Options ({combinations.length})\n </span>\n {allCombinations.length > combinations.length && (\n <button\n type=\"button\"\n onClick={() => setShowDisabledPlayers(!showDisabledPlayers)}\n className=\"fw-dev-list-toggle\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className={cn(\"fw-dev-chevron\", showDisabledPlayers && \"fw-dev-chevron--open\")}\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n {showDisabledPlayers ? \"Hide\" : \"Show\"} disabled ({allCombinations.length - combinations.length})\n </button>\n )}\n </div>\n {allCombinations.length === 0 ? (\n <div className=\"fw-dev-list-empty\">\n No stream info available\n </div>\n ) : (\n <div>\n {allCombinations.map((combo, index) => {\n // Codec-incompatible items always show (with warning), MIME-incompatible hide in \"disabled\"\n const isCodecIncompat = (combo as any).codecIncompatible === true;\n if (!combo.compatible && !isCodecIncompat && !showDisabledPlayers) return null;\n\n const isActive = activeComboIndex === index;\n const typeLabel = SOURCE_TYPE_LABELS[combo.sourceType] || combo.sourceType.split(\"/\").pop();\n\n // Determine score class\n const getScoreClass = () => {\n if (!combo.compatible && !isCodecIncompat) return \"fw-dev-combo-score--disabled\";\n if (isCodecIncompat) return \"fw-dev-combo-score--low\";\n if (combo.score >= 2) return \"fw-dev-combo-score--high\";\n if (combo.score >= 1.5) return \"fw-dev-combo-score--mid\";\n return \"fw-dev-combo-score--low\";\n };\n\n // Determine rank class\n const getRankClass = () => {\n if (isActive) return \"fw-dev-combo-rank--active\";\n if (!combo.compatible && !isCodecIncompat) return \"fw-dev-combo-rank--disabled\";\n if (isCodecIncompat) return \"fw-dev-combo-rank--warn\";\n return \"\";\n };\n\n // Determine type class\n const getTypeClass = () => {\n if (!combo.compatible && !isCodecIncompat) return \"fw-dev-combo-type--disabled\";\n if (isCodecIncompat) return \"fw-dev-combo-type--warn\";\n return \"\";\n };\n\n return (\n <div\n key={`${combo.player}-${combo.sourceType}`}\n onMouseEnter={(e) => {\n setHoveredComboIndex(index);\n if (comboListRef.current) {\n const container = comboListRef.current;\n const row = e.currentTarget;\n const containerRect = container.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const relativePosition = (rowRect.top - containerRect.top) / containerRect.height;\n setTooltipAbove(relativePosition > 0.6);\n }\n }}\n onMouseLeave={() => setHoveredComboIndex(null)}\n className=\"fw-dev-combo\"\n >\n <button\n type=\"button\"\n onClick={() => handleSelectCombo(index)}\n className={cn(\n \"fw-dev-combo-btn\",\n isActive && \"fw-dev-combo-btn--active\",\n !combo.compatible && !isCodecIncompat && \"fw-dev-combo-btn--disabled\",\n isCodecIncompat && \"fw-dev-combo-btn--codec-warn\"\n )}\n >\n {/* Rank */}\n <span className={cn(\"fw-dev-combo-rank\", getRankClass())}>\n {combo.compatible ? index + 1 : isCodecIncompat ? \"⚠\" : \"—\"}\n </span>\n {/* Player + Protocol */}\n <span className=\"fw-dev-combo-name\">\n {combo.playerName}{\" \"}\n <span className=\"fw-dev-combo-arrow\">→</span>{\" \"}\n <span className={cn(\"fw-dev-combo-type\", getTypeClass())}>{typeLabel}</span>\n </span>\n {/* Score */}\n <span className={cn(\"fw-dev-combo-score\", getScoreClass())}>\n {combo.score.toFixed(2)}\n </span>\n </button>\n\n {/* Score breakdown tooltip */}\n {hoveredComboIndex === index && (\n <div className={cn(\n \"fw-dev-tooltip\",\n tooltipAbove ? \"fw-dev-tooltip--above\" : \"fw-dev-tooltip--below\"\n )}>\n {/* Full player/source info */}\n <div className=\"fw-dev-tooltip-header\">\n <div className=\"fw-dev-tooltip-title\">{combo.playerName}</div>\n <div className=\"fw-dev-tooltip-subtitle\">{combo.sourceType}</div>\n {combo.scoreBreakdown?.trackTypes && combo.scoreBreakdown.trackTypes.length > 0 && (\n <div className=\"fw-dev-tooltip-tracks\">\n Tracks: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.trackTypes.join(', ')}</span>\n </div>\n )}\n </div>\n {combo.compatible && combo.scoreBreakdown ? (\n <>\n <div className=\"fw-dev-tooltip-score\">Score: {combo.score.toFixed(2)}</div>\n <div className=\"fw-dev-tooltip-row\">\n Tracks [{combo.scoreBreakdown.trackTypes.join(', ')}]: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.trackScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.tracks}</span>\n </div>\n <div className=\"fw-dev-tooltip-row\">\n Priority: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.priorityScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.priority}</span>\n </div>\n <div className=\"fw-dev-tooltip-row\">\n Source: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.sourceScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.source}</span>\n </div>\n {combo.scoreBreakdown.reliabilityScore !== undefined && (\n <div className=\"fw-dev-tooltip-row\">\n Reliability: <span className=\"fw-dev-tooltip-value\">{combo.scoreBreakdown.reliabilityScore.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.reliability ?? 0}</span>\n </div>\n )}\n {combo.scoreBreakdown.modeBonus !== undefined && combo.scoreBreakdown.modeBonus !== 0 && (\n <div className=\"fw-dev-tooltip-row\">\n Mode ({playbackMode}): <span className=\"fw-dev-tooltip-bonus\">+{combo.scoreBreakdown.modeBonus.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.mode ?? 0}</span>\n </div>\n )}\n {combo.scoreBreakdown.routingBonus !== undefined && combo.scoreBreakdown.routingBonus !== 0 && (\n <div className=\"fw-dev-tooltip-row\">\n Routing: <span className={combo.scoreBreakdown.routingBonus > 0 ? \"fw-dev-tooltip-bonus\" : \"fw-dev-tooltip-penalty\"}>{combo.scoreBreakdown.routingBonus > 0 ? '+' : ''}{combo.scoreBreakdown.routingBonus.toFixed(2)}</span> <span className=\"fw-dev-tooltip-weight\">x{combo.scoreBreakdown.weights.routing ?? 0}</span>\n </div>\n )}\n </>\n ) : (\n <div className=\"fw-dev-tooltip-error\">{combo.incompatibleReason || 'Incompatible'}</div>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Stats Tab */}\n {activeTab === \"stats\" && (\n <div className=\"fw-dev-body\">\n {/* Playback Rate */}\n <div className=\"fw-dev-section\">\n <div className=\"fw-dev-label\">Playback Rate</div>\n <div className=\"fw-dev-rate\">\n <div className={cn(\n \"fw-dev-rate-value\",\n playbackScore >= 0.95 && playbackScore <= 1.05 ? \"fw-dev-stat-value--good\" :\n playbackScore > 1.05 ? \"fw-dev-stat-value--accent\" :\n playbackScore >= 0.75 ? \"fw-dev-stat-value--warn\" :\n \"fw-dev-stat-value--bad\"\n )}>\n {playbackScore.toFixed(2)}×\n </div>\n <div className=\"fw-dev-rate-status\">\n {playbackScore >= 0.95 && playbackScore <= 1.05 ? \"realtime\" :\n playbackScore > 1.05 ? \"catching up\" :\n playbackScore >= 0.75 ? \"slightly slow\" :\n \"stalling\"}\n </div>\n </div>\n <div className=\"fw-dev-rate-stats\">\n <span className={qualityScore >= 75 ? \"fw-dev-stat-value--good\" : \"fw-dev-stat-value--bad\"}>\n Quality: {qualityScore}/100\n </span>\n <span className={stallCount === 0 ? \"fw-dev-stat-value--good\" : \"fw-dev-stat-value--warn\"}>\n Stalls: {stallCount}\n </span>\n <span className={frameDropRate < 1 ? \"fw-dev-stat-value--good\" : \"fw-dev-stat-value--bad\"}>\n Drops: {frameDropRate.toFixed(1)}%\n </span>\n </div>\n </div>\n\n {/* Video Stats */}\n {stats ? (\n <div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Resolution</span>\n <span className=\"fw-dev-stat-value\">{stats.resolution}</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Buffer</span>\n <span className=\"fw-dev-stat-value\">{stats.buffered}s</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Playback Rate</span>\n <span className=\"fw-dev-stat-value\">{stats.playbackRate}x</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Time</span>\n <span className=\"fw-dev-stat-value\">\n {stats.currentTime} / {stats.duration}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Ready State</span>\n <span className=\"fw-dev-stat-value\">{stats.readyState}</span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Network State</span>\n <span className=\"fw-dev-stat-value\">{stats.networkState}</span>\n </div>\n {protocol && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Protocol</span>\n <span className=\"fw-dev-stat-value\">{protocol}</span>\n </div>\n )}\n {nodeId && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Node ID</span>\n <span className=\"fw-dev-stat-value truncate\" style={{ maxWidth: '150px' }}>\n {nodeId}\n </span>\n </div>\n )}\n </div>\n ) : (\n <div className=\"fw-dev-list-empty\">\n No video element available\n </div>\n )}\n\n {/* Player-specific Stats (HLS.js / WebRTC) */}\n {playerStats && (\n <div>\n <div className=\"fw-dev-list-header fw-dev-section-header\">\n <span className=\"fw-dev-list-title\">\n {playerStats.type === 'hls' ? 'HLS.js Stats' :\n playerStats.type === 'webrtc' ? 'WebRTC Stats' : 'Player Stats'}\n </span>\n </div>\n\n {/* HLS-specific stats */}\n {playerStats.type === 'hls' && (\n <>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Bitrate</span>\n <span className=\"fw-dev-stat-value--accent\">\n {playerStats.currentBitrate > 0\n ? `${Math.round(playerStats.currentBitrate / 1000)} kbps`\n : 'N/A'}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Bandwidth Est.</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.bandwidthEstimate > 0\n ? `${Math.round(playerStats.bandwidthEstimate / 1000)} kbps`\n : 'N/A'}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Level</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.currentLevel >= 0 ? playerStats.currentLevel : 'Auto'} / {playerStats.levels?.length || 0}\n </span>\n </div>\n {playerStats.latency !== undefined && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Latency</span>\n <span className={playerStats.latency > 5000 ? \"fw-dev-stat-value--warn\" : \"fw-dev-stat-value\"}>\n {Math.round(playerStats.latency)} ms\n </span>\n </div>\n )}\n </>\n )}\n\n {/* WebRTC-specific stats */}\n {playerStats.type === 'webrtc' && (\n <>\n {playerStats.video && (\n <>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Video Bitrate</span>\n <span className=\"fw-dev-stat-value--accent\">\n {playerStats.video.bitrate > 0\n ? `${Math.round(playerStats.video.bitrate / 1000)} kbps`\n : 'N/A'}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">FPS</span>\n <span className=\"fw-dev-stat-value\">\n {Math.round(playerStats.video.framesPerSecond || 0)}\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Frames</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.video.framesDecoded} decoded,{' '}\n <span className={playerStats.video.frameDropRate > 1 ? \"fw-dev-stat-value--bad\" : \"fw-dev-stat-value--good\"}>\n {playerStats.video.framesDropped} dropped\n </span>\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Packet Loss</span>\n <span className={playerStats.video.packetLossRate > 1 ? \"fw-dev-stat-value--bad\" : \"fw-dev-stat-value--good\"}>\n {playerStats.video.packetLossRate.toFixed(2)}%\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Jitter</span>\n <span className={playerStats.video.jitter > 30 ? \"fw-dev-stat-value--warn\" : \"fw-dev-stat-value\"}>\n {playerStats.video.jitter.toFixed(1)} ms\n </span>\n </div>\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">Jitter Buffer</span>\n <span className=\"fw-dev-stat-value\">\n {playerStats.video.jitterBufferDelay.toFixed(1)} ms\n </span>\n </div>\n </>\n )}\n {playerStats.network && (\n <div className=\"fw-dev-stat\">\n <span className=\"fw-dev-stat-label\">RTT</span>\n <span className={playerStats.network.rtt > 200 ? \"fw-dev-stat-value--warn\" : \"fw-dev-stat-value\"}>\n {Math.round(playerStats.network.rtt)} ms\n </span>\n </div>\n )}\n </>\n )}\n </div>\n )}\n\n {/* MistServer Track Info */}\n {mistStreamInfo?.meta?.tracks && Object.keys(mistStreamInfo.meta.tracks).length > 0 && (\n <div>\n <div className=\"fw-dev-list-header fw-dev-section-header\">\n <span className=\"fw-dev-list-title\">\n Tracks ({Object.keys(mistStreamInfo.meta.tracks).length})\n </span>\n </div>\n {Object.entries(mistStreamInfo.meta.tracks).map(([id, track]) => (\n <div key={id} className=\"fw-dev-track\">\n <div className=\"fw-dev-track-header\">\n <span className={cn(\n \"fw-dev-track-badge\",\n track.type === 'video' ? \"fw-dev-track-badge--video\" :\n track.type === 'audio' ? \"fw-dev-track-badge--audio\" :\n \"fw-dev-track-badge--other\"\n )}>\n {track.type}\n </span>\n <span className=\"fw-dev-track-codec\">{track.codec}</span>\n <span className=\"fw-dev-track-id\">#{id}</span>\n </div>\n <div className=\"fw-dev-track-meta\">\n {track.type === 'video' && track.width && track.height && (\n <span>{track.width}×{track.height}</span>\n )}\n {track.bps && (\n <span>{Math.round(track.bps / 1000)} kbps</span>\n )}\n {track.fpks && (\n <span>{Math.round(track.fpks / 1000)} fps</span>\n )}\n {track.type === 'audio' && track.channels && (\n <span>{track.channels}ch</span>\n )}\n {track.type === 'audio' && track.rate && (\n <span>{track.rate} Hz</span>\n )}\n {track.lang && (\n <span>{track.lang}</span>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Debug: Show if mistStreamInfo is missing tracks */}\n {mistStreamInfo && (!mistStreamInfo.meta?.tracks || Object.keys(mistStreamInfo.meta.tracks).length === 0) && (\n <div className=\"fw-dev-no-tracks\">\n <span className=\"fw-dev-no-tracks-text\">\n No track data available\n {mistStreamInfo.type && <span className=\"fw-dev-no-tracks-type\">({mistStreamInfo.type})</span>}\n </span>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default DevModePanel;\n","import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface SpeedIndicatorProps {\n isVisible: boolean;\n speed: number;\n className?: string;\n}\n\n/**\n * Speed indicator overlay that appears when holding for fast-forward.\n * Shows the current playback speed (e.g., \"2x\") in a pill overlay.\n */\nconst SpeedIndicator: React.FC<SpeedIndicatorProps> = ({\n isVisible,\n speed,\n className,\n}) => {\n return (\n <div\n className={cn(\n \"fw-speed-indicator absolute top-3 right-3 z-30 pointer-events-none\",\n \"transition-opacity duration-150\",\n isVisible ? \"opacity-100\" : \"opacity-0\",\n className\n )}\n >\n <div\n className={cn(\n \"bg-black/60 text-white px-2.5 py-1 rounded-md\",\n \"text-xs font-semibold tabular-nums\",\n \"flex items-center gap-2\",\n \"border border-white/15\",\n \"transform transition-transform duration-150\",\n isVisible ? \"scale-100\" : \"scale-90\"\n )}\n >\n <FastForwardIcon className=\"w-4 h-4\" />\n <span>{speed}x</span>\n </div>\n </div>\n );\n};\n\n// Simple fast-forward icon\nconst FastForwardIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\" />\n </svg>\n);\n\nexport default SpeedIndicator;\n","import React, { useEffect, useState } from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nexport type SkipDirection = \"back\" | \"forward\" | null;\n\ninterface SkipIndicatorProps {\n direction: SkipDirection;\n seconds?: number;\n className?: string;\n onHide?: () => void;\n}\n\n/**\n * Skip indicator overlay that appears when double-tapping to skip.\n * Shows the skip direction and amount (e.g., \"-10s\" or \"+10s\") with a ripple effect.\n */\nconst SkipIndicator: React.FC<SkipIndicatorProps> = ({\n direction,\n seconds = 10,\n className,\n onHide,\n}) => {\n const [isAnimating, setIsAnimating] = useState(false);\n\n useEffect(() => {\n if (direction) {\n setIsAnimating(true);\n const timer = setTimeout(() => {\n setIsAnimating(false);\n onHide?.();\n }, 600);\n return () => clearTimeout(timer);\n }\n }, [direction, onHide]);\n\n if (!direction) return null;\n\n const isBack = direction === \"back\";\n\n return (\n <div\n className={cn(\n \"fw-skip-indicator absolute inset-0 z-30 pointer-events-none\",\n \"flex items-center\",\n isBack ? \"justify-start pl-8\" : \"justify-end pr-8\",\n className\n )}\n >\n {/* Ripple background */}\n <div\n className={cn(\n \"absolute top-0 bottom-0 w-1/3\",\n isBack ? \"left-0\" : \"right-0\",\n \"bg-white/10\",\n isAnimating && \"animate-pulse\"\n )}\n />\n\n {/* Skip content */}\n <div\n className={cn(\n \"relative flex flex-col items-center gap-1 text-white\",\n \"transition-all duration-200\",\n isAnimating ? \"opacity-100 scale-100\" : \"opacity-0 scale-75\"\n )}\n >\n {/* Icon */}\n <div className=\"flex\">\n {isBack ? (\n <>\n <RewindIcon className=\"w-8 h-8\" />\n <RewindIcon className=\"w-8 h-8 -ml-4\" />\n </>\n ) : (\n <>\n <FastForwardIcon className=\"w-8 h-8\" />\n <FastForwardIcon className=\"w-8 h-8 -ml-4\" />\n </>\n )}\n </div>\n\n {/* Text */}\n <span className=\"text-sm font-semibold tabular-nums\">\n {isBack ? `-${seconds}s` : `+${seconds}s`}\n </span>\n </div>\n </div>\n );\n};\n\nconst RewindIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\" />\n </svg>\n);\n\nconst FastForwardIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\" />\n </svg>\n);\n\nexport default SkipIndicator;\n","import * as React from \"react\"\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\"\nimport { Check, ChevronRight, Circle } from \"lucide-react\"\nimport { cn } from \"@livepeer-frameworks/player-core\"\n\nconst ContextMenu = ContextMenuPrimitive.Root\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup\n\nconst ContextMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <ContextMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"fw-context-menu-item\",\n inset && \"fw-context-menu-item--inset\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto h-4 w-4\" />\n </ContextMenuPrimitive.SubTrigger>\n))\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName\n\nconst ContextMenuSubContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.SubContent\n ref={ref}\n className={cn(\"fw-player-surface fw-context-menu\", className)}\n {...props}\n />\n))\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName\n\nconst ContextMenuContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\n>(({ className, style, ...props }, ref) => (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n ref={ref}\n className={cn(\"fw-player-surface fw-context-menu\", className)}\n style={{\n // Inline styles for portal elements (rendered outside .fw-player-root)\n // These ensure styles work even without CSS variable inheritance\n backgroundColor: 'hsl(235 19% 13%)',\n color: 'hsl(229 35% 75%)',\n border: '1px solid rgba(90, 96, 127, 0.3)',\n ...style\n }}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n))\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName\n\nconst ContextMenuItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"fw-context-menu-item\",\n inset && \"fw-context-menu-item--inset\",\n className\n )}\n {...props}\n />\n))\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <ContextMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\"fw-context-menu-checkbox\", className)}\n checked={checked}\n {...props}\n >\n <span className=\"fw-context-menu-indicator\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n))\nContextMenuCheckboxItem.displayName =\n ContextMenuPrimitive.CheckboxItem.displayName\n\nconst ContextMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <ContextMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\"fw-context-menu-checkbox\", className)}\n {...props}\n >\n <span className=\"fw-context-menu-indicator\">\n <ContextMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n))\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName\n\nconst ContextMenuLabel = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"fw-context-menu-label\",\n inset && \"fw-context-menu-item--inset\",\n className\n )}\n {...props}\n />\n))\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName\n\nconst ContextMenuSeparator = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Separator\n ref={ref}\n className={cn(\"fw-context-menu-separator\", className)}\n {...props}\n />\n))\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName\n\nconst ContextMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\nContextMenuShortcut.displayName = \"ContextMenuShortcut\"\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n}\n","import React, { useState, useCallback } from \"react\";\nimport IdleScreen from \"./IdleScreen\";\nimport TitleOverlay from \"./TitleOverlay\";\nimport StatsPanel from \"./StatsPanel\";\nimport PlayerControls from \"./PlayerControls\";\nimport DevModePanel from \"./DevModePanel\";\nimport SpeedIndicator from \"./SpeedIndicator\";\nimport SkipIndicator, { SkipDirection } from \"./SkipIndicator\";\nimport { StatsIcon, SettingsIcon, PictureInPictureIcon } from \"./Icons\";\nimport { PlayerProps } from \"../types\";\nimport { usePlayerController } from \"../hooks/usePlayerController\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\nimport type { PlaybackMode, EndpointInfo } from \"@livepeer-frameworks/player-core\";\nimport {\n ContextMenu,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuSeparator,\n ContextMenuTrigger,\n} from \"../ui/context-menu\";\n\n/**\n * Inner player component that uses PlayerController via hook\n */\nconst PlayerInner: React.FC<PlayerProps> = ({\n contentId,\n contentType,\n thumbnailUrl = null,\n options,\n endpoints: propsEndpoints,\n onStateChange\n}) => {\n // ============================================================================\n // UI-only State (stays in wrapper)\n // ============================================================================\n const [isStatsOpen, setIsStatsOpen] = useState(false);\n const [isDevPanelOpen, setIsDevPanelOpen] = useState(false);\n const [skipDirection, setSkipDirection] = useState<SkipDirection>(null);\n\n // Playback mode preference (persistent)\n const [devPlaybackMode, setDevPlaybackMode] = useState<PlaybackMode>(options?.playbackMode || 'auto');\n\n // ============================================================================\n // PlayerController Hook - ALL business logic\n // ============================================================================\n const {\n containerRef,\n state,\n controller,\n togglePlay,\n toggleMute,\n toggleLoop,\n toggleFullscreen,\n togglePiP,\n setVolume,\n selectQuality,\n clearError,\n retry,\n reload,\n jumpToLive,\n handleMouseEnter,\n handleMouseLeave,\n handleMouseMove,\n setDevModeOptions,\n } = usePlayerController({\n contentId,\n contentType,\n endpoints: propsEndpoints,\n gatewayUrl: options?.gatewayUrl,\n mistUrl: options?.mistUrl,\n authToken: options?.authToken,\n autoplay: options?.autoplay !== false,\n muted: options?.muted !== false,\n controls: options?.stockControls === true,\n poster: thumbnailUrl || undefined,\n debug: options?.debug,\n onStateChange: (playerState) => {\n onStateChange?.(playerState);\n },\n onError: (error) => {\n console.warn('[Player] Error:', error);\n },\n });\n\n // ============================================================================\n // Dev Mode Callbacks\n // ============================================================================\n const handleDevSettingsChange = useCallback((settings: {\n forcePlayer?: string;\n forceType?: string;\n forceSource?: number;\n }) => {\n // One-shot selection - controller handles the state\n setDevModeOptions({\n forcePlayer: settings.forcePlayer,\n forceType: settings.forceType,\n forceSource: settings.forceSource,\n });\n }, [setDevModeOptions]);\n\n const handleModeChange = useCallback((mode: PlaybackMode) => {\n setDevPlaybackMode(mode);\n // Mode is a persistent preference\n setDevModeOptions({ playbackMode: mode });\n }, [setDevModeOptions]);\n\n const handleReload = useCallback(() => {\n clearError();\n reload();\n }, [clearError, reload]);\n\n const handleStatsToggle = useCallback(() => {\n setIsStatsOpen(prev => !prev);\n }, []);\n\n // Clear skip indicator after animation\n const handleSkipIndicatorHide = useCallback(() => {\n setSkipDirection(null);\n }, []);\n\n // ============================================================================\n // Derived Values\n // ============================================================================\n const primaryEndpoint = state.endpoints?.primary as EndpointInfo | undefined;\n const isLegacyPlayer = state.currentPlayerInfo?.shortname === 'mist-legacy';\n const useStockControls = options?.stockControls === true || isLegacyPlayer;\n\n // Title overlay visibility: show on hover or when paused\n const showTitleOverlay = (state.isHovering || state.isPaused) &&\n !state.shouldShowIdleScreen && !state.isBuffering && !state.error;\n\n // Buffering spinner: only during active playback\n const showBufferingSpinner = !state.shouldShowIdleScreen &&\n state.isBuffering && !state.error && state.hasPlaybackStarted;\n\n // ============================================================================\n // Waiting for Endpoint (shown as overlay, not early return)\n // ============================================================================\n const showWaitingForEndpoint = !state.endpoints?.primary && state.state !== 'booting';\n const waitingMessage = options?.gatewayUrl\n ? (state.state === 'gateway_loading' ? 'Resolving viewing endpoint...' : 'Waiting for endpoint...')\n : 'Waiting for endpoint...';\n\n // ============================================================================\n // Render\n // ============================================================================\n return (\n <ContextMenu>\n <ContextMenuTrigger asChild>\n <div\n className={cn(\n \"fw-player-surface fw-player-root w-full h-full overflow-hidden\",\n options?.devMode && \"flex\"\n )}\n data-player-container=\"true\"\n tabIndex={0}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseMove={handleMouseMove}\n >\n {/* Player area */}\n <div className={cn(\n \"relative\",\n options?.devMode ? \"flex-1 min-w-0\" : \"w-full h-full\"\n )}>\n {/* Video container - PlayerController attaches here */}\n <div ref={containerRef} className=\"fw-player-container\" />\n\n {/* Title/Description overlay */}\n <TitleOverlay\n title={state.metadata?.title}\n description={state.metadata?.description}\n isVisible={showTitleOverlay}\n />\n\n {/* Stats panel */}\n <StatsPanel\n isOpen={isStatsOpen}\n onClose={handleStatsToggle}\n metadata={state.metadata}\n streamState={state.streamState}\n quality={state.playbackQuality}\n videoElement={state.videoElement}\n protocol={primaryEndpoint?.protocol}\n nodeId={primaryEndpoint?.nodeId}\n geoDistance={primaryEndpoint?.geoDistance}\n />\n\n {/* Dev Mode Panel toggle */}\n {options?.devMode && !isDevPanelOpen && (\n <DevModePanel\n onSettingsChange={handleDevSettingsChange}\n playbackMode={devPlaybackMode}\n onModeChange={handleModeChange}\n onReload={handleReload}\n streamInfo={state.streamInfo}\n mistStreamInfo={state.streamState?.streamInfo}\n currentPlayer={state.currentPlayerInfo}\n currentSource={state.currentSourceInfo}\n videoElement={state.videoElement}\n protocol={primaryEndpoint?.protocol}\n nodeId={primaryEndpoint?.nodeId}\n isVisible={false}\n isOpen={false}\n onOpenChange={setIsDevPanelOpen}\n />\n )}\n\n {/* Speed indicator */}\n {state.isHoldingSpeed && (\n <SpeedIndicator isVisible={true} speed={state.holdSpeed} />\n )}\n\n {/* Skip indicator */}\n <SkipIndicator\n direction={skipDirection}\n seconds={10}\n onHide={handleSkipIndicatorHide}\n />\n\n {/* Waiting for endpoint overlay */}\n {showWaitingForEndpoint && (\n <IdleScreen status=\"OFFLINE\" message={waitingMessage} />\n )}\n\n {/* Idle screen */}\n {!showWaitingForEndpoint && state.shouldShowIdleScreen && (\n <IdleScreen\n status={state.isEffectivelyLive ? state.streamState?.status : undefined}\n message={state.isEffectivelyLive ? state.streamState?.message : 'Loading video...'}\n percentage={state.isEffectivelyLive ? state.streamState?.percentage : undefined}\n />\n )}\n\n {/* Buffering spinner */}\n {showBufferingSpinner && (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"fw-player-surface absolute inset-0 flex items-center justify-center bg-black/40 backdrop-blur-sm z-20\"\n >\n <div className=\"flex items-center gap-3 rounded-lg border border-white/10 bg-black/70 px-4 py-3 text-sm text-white shadow-lg\">\n <div className=\"w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin\"></div>\n <span>Buffering...</span>\n </div>\n </div>\n )}\n\n {/* Error overlay */}\n {!state.shouldShowIdleScreen && state.error && (\n <div\n role=\"alert\"\n aria-live=\"assertive\"\n className={cn(\n \"fw-error-overlay\",\n state.isPassiveError ? \"fw-error-overlay--passive\" : \"fw-error-overlay--fullscreen\"\n )}\n >\n <div className={cn(\n \"fw-error-popup\",\n state.isPassiveError ? \"fw-error-popup--passive\" : \"fw-error-popup--fullscreen\"\n )}>\n <div className={cn(\n \"fw-error-header\",\n state.isPassiveError ? \"fw-error-header--warning\" : \"fw-error-header--error\"\n )}>\n <span className={cn(\n \"fw-error-title\",\n state.isPassiveError ? \"fw-error-title--warning\" : \"fw-error-title--error\"\n )}>\n {state.isPassiveError ? \"Warning\" : \"Error\"}\n </span>\n <button\n type=\"button\"\n className=\"fw-error-close\"\n onClick={clearError}\n aria-label=\"Dismiss\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M9 3L3 9M3 3L9 9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n </svg>\n </button>\n </div>\n <div className=\"fw-error-body\">\n <p className=\"fw-error-message\">Playback issue</p>\n </div>\n <div className=\"fw-error-actions\">\n <button\n type=\"button\"\n className=\"fw-error-btn\"\n aria-label=\"Retry playback\"\n onClick={() => { clearError(); retry(); }}\n >\n Retry\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Player controls */}\n {!useStockControls && (\n <PlayerControls\n currentTime={state.currentTime}\n duration={state.duration}\n isVisible={state.shouldShowControls}\n onSeek={(t) => controller?.seek(t)}\n showStatsButton={false}\n isStatsOpen={isStatsOpen}\n onStatsToggle={handleStatsToggle}\n mistStreamInfo={state.streamState?.streamInfo}\n disabled={!state.videoElement}\n playbackMode={devPlaybackMode}\n onModeChange={handleModeChange}\n sourceType={state.currentSourceInfo?.type}\n isContentLive={state.isEffectivelyLive}\n // Props from usePlayerController hook\n videoElement={state.videoElement}\n qualities={state.qualities}\n onSelectQuality={selectQuality}\n isMuted={state.isMuted}\n volume={state.volume}\n onVolumeChange={setVolume}\n onToggleMute={toggleMute}\n isPlaying={state.isPlaying}\n onTogglePlay={togglePlay}\n onToggleFullscreen={toggleFullscreen}\n isFullscreen={state.isFullscreen}\n isLoopEnabled={state.isLoopEnabled}\n onToggleLoop={toggleLoop}\n onJumpToLive={jumpToLive}\n />\n )}\n </div>\n\n {/* Dev Mode Panel - side panel */}\n {options?.devMode && isDevPanelOpen && (\n <DevModePanel\n onSettingsChange={handleDevSettingsChange}\n playbackMode={devPlaybackMode}\n onModeChange={handleModeChange}\n onReload={handleReload}\n streamInfo={state.streamInfo}\n mistStreamInfo={state.streamState?.streamInfo}\n currentPlayer={state.currentPlayerInfo}\n currentSource={state.currentSourceInfo}\n videoElement={state.videoElement}\n protocol={primaryEndpoint?.protocol}\n nodeId={primaryEndpoint?.nodeId}\n isVisible={true}\n isOpen={true}\n onOpenChange={setIsDevPanelOpen}\n />\n )}\n </div>\n </ContextMenuTrigger>\n\n {/* Context menu */}\n <ContextMenuContent>\n <ContextMenuItem onClick={handleStatsToggle} className=\"gap-2\">\n <StatsIcon size={14} className=\"opacity-70 flex-shrink-0\" />\n <span>{isStatsOpen ? \"Hide Stats\" : \"Stats\"}</span>\n </ContextMenuItem>\n {options?.devMode && (\n <>\n <ContextMenuSeparator />\n <ContextMenuItem onClick={() => setIsDevPanelOpen(!isDevPanelOpen)} className=\"gap-2\">\n <SettingsIcon size={14} className=\"opacity-70 flex-shrink-0\" />\n <span>{isDevPanelOpen ? \"Hide Settings\" : \"Settings\"}</span>\n </ContextMenuItem>\n </>\n )}\n <ContextMenuSeparator />\n <ContextMenuItem onClick={togglePiP} className=\"gap-2\">\n <PictureInPictureIcon size={14} className=\"opacity-70 flex-shrink-0\" />\n <span>Picture-in-Picture</span>\n </ContextMenuItem>\n <ContextMenuItem onClick={toggleLoop} className=\"gap-2\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"opacity-70 flex-shrink-0\">\n <polyline points=\"17 1 21 5 17 9\"></polyline>\n <path d=\"M3 11V9a4 4 0 0 1 4-4h14\"></path>\n <polyline points=\"7 23 3 19 7 15\"></polyline>\n <path d=\"M21 13v2a4 4 0 0 1-4 4H3\"></path>\n </svg>\n <span>{state.isLoopEnabled ? \"Disable Loop\" : \"Enable Loop\"}</span>\n </ContextMenuItem>\n </ContextMenuContent>\n </ContextMenu>\n );\n};\n\n/**\n * Main Player component.\n *\n * Note: PlayerProvider is available if you need to use context-based access\n * across multiple components. PlayerInner manages its own PlayerController\n * via usePlayerController hook.\n */\nconst Player: React.FC<PlayerProps> = (props) => {\n return <PlayerInner {...props} />;\n};\n\nexport default Player;\n","import React, { useRef, useEffect, useState } from \"react\";\nimport DvdLogo from \"./DvdLogo\";\nimport logomarkAsset from \"../assets/logomark.svg\";\n\ninterface AnimatedBubbleProps {\n index: number;\n}\n\nconst AnimatedBubble: React.FC<AnimatedBubbleProps> = ({ index }) => {\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const [size, setSize] = useState(40);\n const [opacity, setOpacity] = useState(0);\n\n const getRandomPosition = () => ({\n top: Math.random() * 80 + 10, // 10% to 90%\n left: Math.random() * 80 + 10, // 10% to 90%\n });\n\n const getRandomSize = () => Math.random() * 60 + 30; // 30px to 90px\n\n useEffect(() => {\n // Initial random position and size\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n\n const animationCycle = () => {\n // Fade in\n setOpacity(0.15);\n\n setTimeout(() => {\n // Fade out\n setOpacity(0);\n\n setTimeout(() => {\n // Move to new random position with new size while invisible\n setPosition(getRandomPosition());\n setSize(getRandomSize());\n // Start next cycle after a brief delay to ensure position change is complete\n setTimeout(() => {\n animationCycle();\n }, 200);\n }, 1500); // Wait for fade out to complete\n }, 4000 + Math.random() * 3000); // Stay visible for 4-7 seconds (was 2-4)\n };\n\n // Start the animation cycle with staggered timing\n const timeout = setTimeout(animationCycle, index * 500);\n\n return () => {\n clearTimeout(timeout);\n };\n }, [index]);\n\n // Tokyo Night inspired pastel colors\n const bubbleColors = [\n \"rgba(122, 162, 247, 0.2)\", // Terminal Blue\n \"rgba(187, 154, 247, 0.2)\", // Terminal Magenta\n \"rgba(158, 206, 106, 0.2)\", // Strings/CSS classes \n \"rgba(115, 218, 202, 0.2)\", // Terminal Green\n \"rgba(125, 207, 255, 0.2)\", // Terminal Cyan\n \"rgba(247, 118, 142, 0.2)\", // Keywords/Terminal Red\n \"rgba(224, 175, 104, 0.2)\", // Terminal Yellow\n \"rgba(42, 195, 222, 0.2)\", // Language functions\n ];\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: `${position.top}%`,\n left: `${position.left}%`,\n width: `${size}px`,\n height: `${size}px`,\n borderRadius: \"50%\",\n background: bubbleColors[index % bubbleColors.length],\n opacity: opacity,\n transition: \"opacity 1s ease-in-out\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n } as React.CSSProperties}\n />\n );\n};\n\ninterface CenterLogoProps {\n containerRef: React.RefObject<HTMLDivElement>;\n scale?: number;\n onHitmarker?: (e: { clientX: number; clientY: number }) => void;\n}\n\nconst CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHitmarker }) => {\n const [logoSize, setLogoSize] = useState(100);\n const [offset, setOffset] = useState({ x: 0, y: 0 });\n const [isHovered, setIsHovered] = useState(false);\n\n useEffect(() => {\n if (containerRef.current) {\n const containerWidth = containerRef.current.clientWidth;\n const containerHeight = containerRef.current.clientHeight;\n const minDimension = Math.min(containerWidth, containerHeight);\n setLogoSize(minDimension * scale);\n }\n }, [containerRef, scale]);\n\n const handleLogoClick = (e: React.MouseEvent) => {\n e.stopPropagation(); // Prevent event bubbling to container\n if (onHitmarker) {\n // Get the exact click position on the logo\n onHitmarker({ clientX: e.clientX, clientY: e.clientY });\n }\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n\n const mouseX = e.clientX;\n const mouseY = e.clientY;\n\n // Calculate distance from center\n const deltaX = mouseX - centerX;\n const deltaY = mouseY - centerY;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n // If mouse is close to logo, move it away\n const maxDistance = logoSize * 1.5; // Detection radius\n if (distance < maxDistance && distance > 0) {\n const pushStrength = (maxDistance - distance) / maxDistance;\n const pushDistance = 50 * pushStrength; // Max push distance\n\n // Normalize direction and apply push\n const pushX = -(deltaX / distance) * pushDistance;\n const pushY = -(deltaY / distance) * pushDistance;\n\n setOffset({ x: pushX, y: pushY });\n setIsHovered(true);\n } else {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n }\n };\n\n const handleMouseLeave = () => {\n setOffset({ x: 0, y: 0 });\n setIsHovered(false);\n };\n\n useEffect(() => {\n if (containerRef.current) {\n const container = containerRef.current;\n container.addEventListener('mousemove', handleMouseMove);\n container.addEventListener('mouseleave', handleMouseLeave);\n\n return () => {\n container.removeEventListener('mousemove', handleMouseMove);\n container.removeEventListener('mouseleave', handleMouseLeave);\n };\n }\n }, [logoSize, containerRef]);\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: `translate(-50%, -50%) translate(${offset.x}px, ${offset.y}px)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10,\n transition: \"transform 0.3s ease-out\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n }}\n >\n {/* Pulsing circle background */}\n <div\n style={{\n position: \"absolute\",\n width: `${logoSize * 1.4}px`,\n height: `${logoSize * 1.4}px`,\n borderRadius: \"50%\",\n background: \"rgba(122, 162, 247, 0.15)\",\n animation: isHovered ? \"logoPulse 1s ease-in-out infinite\" : \"logoPulse 3s ease-in-out infinite\",\n transform: isHovered ? \"scale(1.2)\" : \"scale(1)\",\n transition: \"transform 0.3s ease-out\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n pointerEvents: \"none\",\n }}\n />\n\n {/* Logo - only the SVG is clickable */}\n <img\n src={logomarkAsset}\n alt=\"FrameWorks Logo\"\n onClick={handleLogoClick}\n style={{\n width: `${logoSize}px`,\n height: `${logoSize}px`,\n position: \"relative\",\n zIndex: 1,\n filter: isHovered\n ? \"drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1)\"\n : \"drop-shadow(0 4px 8px rgba(36, 40, 59, 0.3))\",\n transform: isHovered ? \"scale(1.1)\" : \"scale(1)\",\n transition: \"all 0.3s ease-out\",\n cursor: isHovered ? \"pointer\" : \"default\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n WebkitUserDrag: \"none\",\n WebkitTouchCallout: \"none\",\n } as React.CSSProperties}\n />\n </div>\n );\n};\n\ninterface LoadingScreenProps {\n message?: string;\n}\n\ninterface Hitmarker {\n id: number;\n x: number;\n y: number;\n}\n\nconst LoadingScreen: React.FC<LoadingScreenProps> = ({ message = \"Waiting for source...\" }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [hitmarkers, setHitmarkers] = useState<Hitmarker[]>([]);\n\n const playHitmarkerSound = () => {\n try {\n // Embedded hitmarker sound as base64 data URL\n const hitmarkerDataUrl = 'data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA' +\n 'AAD/+1QAAAAAAAAAAAAAAAAAAAAA' +\n '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' +\n 'qqqqqqqqqqqqqqqqqqqqqqqqqqo=';\n \n const audio = new Audio(hitmarkerDataUrl);\n audio.volume = 0.3;\n audio.play().catch(() => {\n // Fallback to synthetic sound if data URL fails\n createSyntheticHitmarkerSound();\n });\n } catch {\n // Fallback to synthetic sound\n createSyntheticHitmarkerSound();\n }\n };\n\n const createSyntheticHitmarkerSound = () => {\n try {\n const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\n \n // Create a more realistic hitmarker sound with noise and metallic ring\n const oscillator1 = audioContext.createOscillator();\n const oscillator2 = audioContext.createOscillator();\n const noiseBuffer = audioContext.createBuffer(1, audioContext.sampleRate * 0.1, audioContext.sampleRate);\n const noiseSource = audioContext.createBufferSource();\n \n // Generate white noise for the initial \"crack\"\n const noiseData = noiseBuffer.getChannelData(0);\n for (let i = 0; i < noiseData.length; i++) {\n noiseData[i] = Math.random() * 2 - 1;\n }\n noiseSource.buffer = noiseBuffer;\n \n const gainNode1 = audioContext.createGain();\n const gainNode2 = audioContext.createGain();\n const noiseGain = audioContext.createGain();\n const masterGain = audioContext.createGain();\n \n // Connect everything\n oscillator1.connect(gainNode1);\n oscillator2.connect(gainNode2);\n noiseSource.connect(noiseGain);\n \n gainNode1.connect(masterGain);\n gainNode2.connect(masterGain);\n noiseGain.connect(masterGain);\n masterGain.connect(audioContext.destination);\n \n // Sharp metallic frequencies\n oscillator1.frequency.setValueAtTime(1800, audioContext.currentTime);\n oscillator1.frequency.exponentialRampToValueAtTime(900, audioContext.currentTime + 0.08);\n \n oscillator2.frequency.setValueAtTime(3600, audioContext.currentTime);\n oscillator2.frequency.exponentialRampToValueAtTime(1800, audioContext.currentTime + 0.04);\n \n oscillator1.type = 'triangle';\n oscillator2.type = 'sine';\n \n // Sharp attack, quick decay\n gainNode1.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode1.gain.linearRampToValueAtTime(0.4, audioContext.currentTime + 0.002);\n gainNode1.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.12);\n \n gainNode2.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode2.gain.linearRampToValueAtTime(0.3, audioContext.currentTime + 0.001);\n gainNode2.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.06);\n \n // Noise burst for the initial crack\n noiseGain.gain.setValueAtTime(0, audioContext.currentTime);\n noiseGain.gain.linearRampToValueAtTime(0.2, audioContext.currentTime + 0.001);\n noiseGain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.01);\n \n masterGain.gain.setValueAtTime(0.5, audioContext.currentTime);\n \n const startTime = audioContext.currentTime;\n const stopTime = startTime + 0.15;\n \n oscillator1.start(startTime);\n oscillator2.start(startTime);\n noiseSource.start(startTime);\n \n oscillator1.stop(stopTime);\n oscillator2.stop(stopTime);\n noiseSource.stop(startTime + 0.02);\n \n } catch {\n console.log('Audio context not available');\n }\n };\n\n const createHitmarker = (e: { clientX: number; clientY: number }) => {\n if (!containerRef.current) return;\n \n const rect = containerRef.current.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n const newHitmarker: Hitmarker = {\n id: Date.now() + Math.random(),\n x,\n y,\n };\n \n setHitmarkers(prev => [...prev, newHitmarker]);\n \n // Play sound\n playHitmarkerSound();\n \n // Remove hitmarker after animation\n setTimeout(() => {\n setHitmarkers(prev => prev.filter(h => h.id !== newHitmarker.id));\n }, 600);\n };\n\n // Inject CSS animations\n useEffect(() => {\n const styleId = 'loading-screen-animations';\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes fadeInOut {\n 0%, 100% {\n opacity: 0.6;\n }\n 50% {\n opacity: 0.9;\n }\n }\n\n @keyframes logoPulse {\n 0%, 100% {\n opacity: 0.15;\n transform: scale(1);\n }\n 50% {\n opacity: 0.25;\n transform: scale(1.05);\n }\n }\n\n @keyframes shimmer {\n 0% {\n background-position: -200px 0;\n }\n 100% {\n background-position: calc(200px + 100%) 0;\n }\n }\n\n @keyframes floatUp {\n 0% {\n transform: translateY(100vh) rotate(0deg);\n opacity: 0;\n }\n 10% {\n opacity: 0.6;\n }\n 90% {\n opacity: 0.6;\n }\n 100% {\n transform: translateY(-100px) rotate(360deg);\n opacity: 0;\n }\n }\n\n @keyframes gradientShift {\n 0%, 100% {\n background-position: 0% 50%;\n }\n 50% {\n background-position: 100% 50%;\n }\n }\n\n @keyframes hitmarkerFade {\n 0% {\n opacity: 1;\n transform: scale(0.5);\n }\n 20% {\n opacity: 1;\n transform: scale(1.2);\n }\n 100% {\n opacity: 0;\n transform: scale(1);\n }\n }\n\n @keyframes hitmarkerFade45 {\n 0% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(45deg) scale(0.5);\n }\n 20% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(45deg) scale(1.2);\n }\n 100% {\n opacity: 0;\n transform: translate(-50%, -50%) rotate(45deg) scale(1);\n }\n }\n\n @keyframes hitmarkerFadeNeg45 {\n 0% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(-45deg) scale(0.5);\n }\n 20% {\n opacity: 1;\n transform: translate(-50%, -50%) rotate(-45deg) scale(1.2);\n }\n 100% {\n opacity: 0;\n transform: translate(-50%, -50%) rotate(-45deg) scale(1);\n }\n }\n `;\n document.head.appendChild(style);\n }\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"fw-player-root\"\n style={{\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n minHeight: \"300px\",\n background: `\n linear-gradient(135deg,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,\n hsl(var(--tn-bg, 233 23% 17%)) 25%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,\n hsl(var(--tn-bg, 233 23% 17%)) 75%,\n hsl(var(--tn-bg-dark, 235 21% 11%)) 100%\n )\n `,\n backgroundSize: \"400% 400%\",\n animation: \"gradientShift 16s ease-in-out infinite\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderRadius: \"0\", /* Slab - no rounded corners */\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n } as React.CSSProperties}\n >\n {/* Hitmarkers */}\n {hitmarkers.map(hitmarker => (\n <div\n key={hitmarker.id}\n style={{\n position: \"absolute\",\n left: `${hitmarker.x}px`,\n top: `${hitmarker.y}px`,\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\",\n zIndex: 100,\n width: \"40px\",\n height: \"40px\",\n }}\n >\n {/* Top-left diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"25%\",\n left: \"25%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(45deg)\",\n animation: \"hitmarkerFade45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n {/* Top-right diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"25%\",\n left: \"75%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(-45deg)\",\n animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n {/* Bottom-left diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"75%\",\n left: \"25%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(-45deg)\",\n animation: \"hitmarkerFadeNeg45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n {/* Bottom-right diagonal line */}\n <div\n style={{\n position: \"absolute\",\n top: \"75%\",\n left: \"75%\",\n width: \"12px\",\n height: \"3px\",\n backgroundColor: \"#ffffff\",\n transform: \"translate(-50%, -50%) rotate(45deg)\",\n animation: \"hitmarkerFade45 0.6s ease-out forwards\",\n boxShadow: \"0 0 8px rgba(255, 255, 255, 0.8)\",\n borderRadius: \"1px\",\n }}\n />\n </div>\n ))}\n\n {/* Floating particles */}\n {[...Array(12)].map((_, index) => (\n <div\n key={`particle-${index}`}\n style={{\n position: \"absolute\",\n left: `${Math.random() * 100}%`,\n width: `${Math.random() * 4 + 2}px`,\n height: `${Math.random() * 4 + 2}px`,\n borderRadius: \"50%\",\n background: [\n \"#7aa2f7\", // Terminal Blue\n \"#bb9af7\", // Terminal Magenta \n \"#9ece6a\", // Strings/CSS classes\n \"#73daca\", // Terminal Green\n \"#7dcfff\", // Terminal Cyan\n \"#f7768e\", // Keywords/Terminal Red\n \"#e0af68\", // Terminal Yellow\n \"#2ac3de\", // Language functions\n ][index % 8],\n opacity: 0,\n animation: `floatUp ${8 + Math.random() * 4}s linear infinite`,\n animationDelay: `${Math.random() * 8}s`,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n ))}\n\n {/* Animated bubbles with Tokyo Night colors */}\n {[...Array(8)].map((_, index) => (\n <AnimatedBubble key={index} index={index} />\n ))}\n\n {/* Center logo */}\n <CenterLogo containerRef={containerRef as React.RefObject<HTMLDivElement>} onHitmarker={createHitmarker} />\n\n {/* Bouncing DVD Logo */}\n <DvdLogo parentRef={containerRef as React.RefObject<HTMLDivElement>} scale={0.08} />\n\n {/* Message */}\n <div\n style={{\n position: \"absolute\",\n bottom: \"20%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n color: \"#a9b1d6\",\n fontSize: \"16px\",\n fontWeight: \"500\",\n textAlign: \"center\",\n animation: \"fadeInOut 2s ease-in-out infinite\",\n textShadow: \"0 2px 4px rgba(36, 40, 59, 0.5)\",\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n msUserSelect: \"none\",\n pointerEvents: \"none\",\n }}\n >\n {message}\n </div>\n\n {/* Subtle overlay texture */}\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: `\n radial-gradient(circle at 20% 80%, rgba(122, 162, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(187, 154, 247, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(158, 206, 106, 0.02) 0%, transparent 50%)\n `,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n </div>\n );\n};\n\nexport default LoadingScreen; \n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n outline: \"border border-border bg-transparent hover:bg-accent hover:text-accent-foreground\",\n destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n subtle: \"bg-muted text-muted-foreground hover:bg-muted/80\",\n link: \"text-primary underline-offset-4 hover:underline\"\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-9 w-9\"\n }\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\"\n }\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;\n }\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import React from 'react';\nimport type { StreamStatus } from '../types';\n\nexport interface StreamStateOverlayProps {\n /** Current stream status */\n status: StreamStatus;\n /** Human-readable message */\n message: string;\n /** Processing percentage (for INITIALIZING state) */\n percentage?: number;\n /** Callback for retry button */\n onRetry?: () => void;\n /** Whether to show the overlay */\n visible?: boolean;\n /** Additional className */\n className?: string;\n}\n\n/**\n * Get status icon based on stream state\n */\nfunction StatusIcon({ status }: { status: StreamStatus }) {\n const iconClass = \"w-5 h-5\";\n\n switch (status) {\n case 'ONLINE':\n return (\n <svg className={`${iconClass} fw-status-online`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n );\n\n case 'OFFLINE':\n return (\n <svg className={`${iconClass} fw-status-offline`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414\" />\n </svg>\n );\n\n case 'INITIALIZING':\n case 'BOOTING':\n case 'WAITING_FOR_DATA':\n return (\n <svg className={`${iconClass} fw-status-warning animate-spin`} fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n );\n\n case 'SHUTTING_DOWN':\n return (\n <svg className={`${iconClass} fw-status-warning`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n );\n\n case 'ERROR':\n case 'INVALID':\n default:\n return (\n <svg className={`${iconClass} fw-status-offline`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n );\n }\n}\n\n/**\n * Get status label for header\n */\nfunction getStatusLabel(status: StreamStatus): string {\n switch (status) {\n case 'ONLINE': return 'ONLINE';\n case 'OFFLINE': return 'OFFLINE';\n case 'INITIALIZING': return 'INITIALIZING';\n case 'BOOTING': return 'STARTING';\n case 'WAITING_FOR_DATA': return 'WAITING';\n case 'SHUTTING_DOWN': return 'ENDING';\n case 'ERROR': return 'ERROR';\n case 'INVALID': return 'INVALID';\n default: return 'STATUS';\n }\n}\n\n/**\n * StreamStateOverlay - Shows stream status when not playable\n *\n * Slab-based design with header/body/actions zones.\n * Uses Tokyo Night color palette and seam-based layout.\n */\nexport const StreamStateOverlay: React.FC<StreamStateOverlayProps> = ({\n status,\n message,\n percentage,\n onRetry,\n visible = true,\n className = '',\n}) => {\n if (!visible || status === 'ONLINE') {\n return null;\n }\n\n const showRetry = status === 'ERROR' || status === 'INVALID' || status === 'OFFLINE';\n const showProgress = status === 'INITIALIZING' && percentage !== undefined;\n\n return (\n <div\n className={`absolute inset-0 z-20 flex items-center justify-center ${className}`}\n style={{ backgroundColor: 'hsl(var(--tn-bg-dark) / 0.8)', backdropFilter: 'blur(4px)' }}\n role=\"status\"\n aria-live=\"polite\"\n >\n {/* Slab container - no rounded corners, seam borders */}\n <div\n className=\"fw-slab w-[280px] max-w-[90%]\"\n style={{ backgroundColor: 'hsl(var(--tn-bg) / 0.95)' }}\n >\n {/* Slab header - status label with icon */}\n <div className=\"fw-slab-header flex items-center gap-2\">\n <StatusIcon status={status} />\n <span>{getStatusLabel(status)}</span>\n </div>\n\n {/* Slab body - message and progress */}\n <div className=\"fw-slab-body\">\n <p className=\"text-sm\" style={{ color: 'hsl(var(--tn-fg))' }}>\n {message}\n </p>\n\n {showProgress && (\n <div className=\"mt-3\">\n {/* Progress bar - no rounded corners */}\n <div\n className=\"h-1.5 w-full overflow-hidden\"\n style={{ backgroundColor: 'hsl(var(--tn-bg-visual))' }}\n >\n <div\n className=\"h-full transition-all duration-300\"\n style={{\n width: `${Math.min(100, percentage)}%`,\n backgroundColor: 'hsl(var(--tn-yellow))',\n }}\n />\n </div>\n <p\n className=\"mt-1.5 text-xs font-mono\"\n style={{ color: 'hsl(var(--tn-fg-dark))' }}\n >\n {Math.round(percentage)}%\n </p>\n </div>\n )}\n\n {status === 'OFFLINE' && (\n <p className=\"mt-2 text-xs\" style={{ color: 'hsl(var(--tn-fg-dark))' }}>\n The stream will start when the broadcaster goes live\n </p>\n )}\n\n {(status === 'BOOTING' || status === 'WAITING_FOR_DATA') && (\n <p className=\"mt-2 text-xs\" style={{ color: 'hsl(var(--tn-fg-dark))' }}>\n Please wait while the stream prepares...\n </p>\n )}\n\n {/* Polling indicator for non-error states */}\n {!showRetry && (\n <div\n className=\"mt-3 flex items-center gap-2 text-xs\"\n style={{ color: 'hsl(var(--tn-fg-dark))' }}\n >\n <span\n className=\"h-1.5 w-1.5 animate-pulse\"\n style={{ backgroundColor: 'hsl(var(--tn-cyan))' }}\n />\n <span>Checking stream status...</span>\n </div>\n )}\n </div>\n\n {/* Slab actions - flush retry button */}\n {showRetry && onRetry && (\n <div className=\"fw-slab-actions\">\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"fw-btn-flush py-2.5 text-xs font-medium uppercase tracking-wide\"\n style={{ color: 'hsl(var(--tn-blue))' }}\n aria-label=\"Retry connection\"\n >\n Retry Connection\n </button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default StreamStateOverlay;\n","import React, { Component, ErrorInfo, ReactNode } from 'react';\nimport { Button } from '../ui/button';\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n onRetry?: () => void;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary to catch and handle player errors gracefully.\n * Prevents player errors from crashing the parent application.\n */\nclass PlayerErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n console.error('[PlayerErrorBoundary] Caught error:', error, errorInfo);\n this.props.onError?.(error, errorInfo);\n }\n\n handleRetry = (): void => {\n this.setState({ hasError: false, error: null });\n this.props.onRetry?.();\n };\n\n render(): ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div className=\"fw-player-error flex min-h-[280px] flex-col items-center justify-center gap-4 rounded-xl bg-slate-950 p-6 text-center text-white\">\n <div className=\"text-lg font-semibold text-red-400\">\n Playback Error\n </div>\n <p className=\"max-w-sm text-sm text-slate-400\">\n {this.state.error?.message || 'An unexpected error occurred while loading the player.'}\n </p>\n <Button\n type=\"button\"\n variant=\"secondary\"\n onClick={this.handleRetry}\n className=\"mt-2\"\n >\n Try Again\n </Button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\nexport default PlayerErrorBoundary;\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-full border border-transparent px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ring-offset-background\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n outline: \"border-border text-foreground\"\n }\n },\n defaultVariants: {\n variant: \"default\"\n }\n }\n);\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return <div className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","import { useEffect, useState, useRef, useCallback } from 'react';\nimport type {\n UseStreamStateOptions,\n StreamState,\n StreamStatus,\n MistStreamInfo,\n} from '../types';\n\n/**\n * Parse MistServer error string into StreamStatus enum\n */\nfunction parseErrorToStatus(error: string): StreamStatus {\n const lowerError = error.toLowerCase();\n\n if (lowerError.includes('offline')) return 'OFFLINE';\n if (lowerError.includes('initializing')) return 'INITIALIZING';\n if (lowerError.includes('booting')) return 'BOOTING';\n if (lowerError.includes('waiting for data')) return 'WAITING_FOR_DATA';\n if (lowerError.includes('shutting down')) return 'SHUTTING_DOWN';\n if (lowerError.includes('invalid')) return 'INVALID';\n\n return 'ERROR';\n}\n\n/**\n * Get human-readable message for stream status\n */\nfunction getStatusMessage(status: StreamStatus, percentage?: number): string {\n switch (status) {\n case 'ONLINE':\n return 'Stream is online';\n case 'OFFLINE':\n return 'Stream is offline';\n case 'INITIALIZING':\n return percentage !== undefined\n ? `Initializing... ${Math.round(percentage * 10) / 10}%`\n : 'Stream is initializing';\n case 'BOOTING':\n return 'Stream is starting up';\n case 'WAITING_FOR_DATA':\n return 'Waiting for stream data';\n case 'SHUTTING_DOWN':\n return 'Stream is shutting down';\n case 'INVALID':\n return 'Stream status is invalid';\n case 'ERROR':\n default:\n return 'Stream error';\n }\n}\n\n/**\n * Initial stream state\n */\nconst initialState: StreamState = {\n status: 'OFFLINE',\n isOnline: false,\n message: 'Connecting...',\n lastUpdate: 0,\n};\n\n/**\n * Hook to poll MistServer for stream status via WebSocket or HTTP\n *\n * Uses native MistServer protocol:\n * - WebSocket: ws://{baseUrl}/json_{streamName}.js\n * - HTTP fallback: GET {baseUrl}/json_{streamName}.js\n *\n * @example\n * ```tsx\n * const { status, isOnline, message } = useStreamState({\n * mistBaseUrl: 'https://mist.example.com',\n * streamName: 'pk_...', // playbackId (view key)\n * pollInterval: 3000,\n * });\n * ```\n */\nexport interface UseStreamStateReturn extends StreamState {\n /** Manual refetch function */\n refetch: () => void;\n /** WebSocket reference for sharing with MistReporter */\n socketRef: React.RefObject<WebSocket | null>;\n /** True when WebSocket is connected and ready (triggers re-render) */\n socketReady: boolean;\n}\n\nexport function useStreamState(options: UseStreamStateOptions): UseStreamStateReturn {\n const {\n mistBaseUrl,\n streamName,\n pollInterval = 3000,\n enabled = true,\n useWebSocket = true,\n debug = false,\n } = options;\n\n const [state, setState] = useState<StreamState>(initialState);\n const [socketReady, setSocketReady] = useState(false);\n const wsRef = useRef<WebSocket | null>(null);\n const pollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wsTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const mountedRef = useRef(true);\n\n // MistPlayer-style WebSocket timeout (5 seconds)\n const WS_TIMEOUT_MS = 5000;\n\n /**\n * Process MistServer response data\n */\n const processStreamInfo = useCallback((data: MistStreamInfo) => {\n if (!mountedRef.current) return;\n\n if (data.error) {\n // Stream has an error state - preserve previous streamInfo (track data)\n const status = parseErrorToStatus(data.error);\n const message = data.on_error || getStatusMessage(status, data.perc);\n\n setState(prev => ({\n status,\n isOnline: false,\n message,\n percentage: data.perc,\n lastUpdate: Date.now(),\n error: data.error,\n streamInfo: prev.streamInfo, // Preserve track data through error states\n }));\n } else {\n // Stream is online with valid metadata\n // Merge new data with existing streamInfo to preserve source/tracks from initial fetch\n // WebSocket updates may not include source array - only status updates\n setState(prev => {\n const mergedStreamInfo: MistStreamInfo = {\n ...prev.streamInfo, // Keep existing source/meta if present\n ...data, // Override with new data\n // Explicitly preserve source if not in new data\n source: data.source || prev.streamInfo?.source,\n // Merge meta to preserve tracks\n meta: {\n ...prev.streamInfo?.meta,\n ...data.meta,\n // Preserve tracks if not in new data\n tracks: data.meta?.tracks || prev.streamInfo?.meta?.tracks,\n },\n };\n\n return {\n status: 'ONLINE',\n isOnline: true,\n message: 'Stream is online',\n lastUpdate: Date.now(),\n streamInfo: mergedStreamInfo,\n };\n });\n }\n }, []);\n\n /**\n * HTTP polling fallback\n * Adds metaeverywhere=1 and inclzero=1 like MistPlayer\n */\n const pollHttp = useCallback(async () => {\n if (!mountedRef.current || !enabled) return;\n\n try {\n // Build URL with MistPlayer-style params\n const baseUrl = `${mistBaseUrl.replace(/\\/$/, '')}/json_${encodeURIComponent(streamName)}.js`;\n const url = `${baseUrl}?metaeverywhere=1&inclzero=1`;\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n // MistServer returns JSON with potential JSONP wrapper\n let text = await response.text();\n // Strip JSONP callback if present (use [\\s\\S]* instead of /s flag for ES5 compat)\n const jsonpMatch = text.match(/^[^(]+\\(([\\s\\S]*)\\);?$/);\n if (jsonpMatch) {\n text = jsonpMatch[1];\n }\n\n const data = JSON.parse(text) as MistStreamInfo;\n processStreamInfo(data);\n } catch (error) {\n if (!mountedRef.current) return;\n\n setState(prev => ({\n ...prev,\n status: 'ERROR',\n isOnline: false,\n message: error instanceof Error ? error.message : 'Connection failed',\n lastUpdate: Date.now(),\n error: error instanceof Error ? error.message : 'Unknown error',\n }));\n }\n\n // Schedule next poll\n if (mountedRef.current && enabled && !useWebSocket) {\n pollTimeoutRef.current = setTimeout(pollHttp, pollInterval);\n }\n }, [mistBaseUrl, streamName, enabled, useWebSocket, pollInterval, processStreamInfo]);\n\n /**\n * WebSocket connection with MistPlayer-style 5-second timeout\n */\n const connectWebSocket = useCallback(() => {\n if (!mountedRef.current || !enabled || !useWebSocket) return;\n\n // Clean up existing connection and timeout\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n if (wsRef.current) {\n wsRef.current.close();\n wsRef.current = null;\n }\n\n try {\n // Convert http(s) to ws(s)\n const wsUrl = mistBaseUrl\n .replace(/^http:/, 'ws:')\n .replace(/^https:/, 'wss:')\n .replace(/\\/$/, '');\n\n // Build URL with MistPlayer-style params\n const url = `${wsUrl}/json_${encodeURIComponent(streamName)}.js?metaeverywhere=1&inclzero=1`;\n const ws = new WebSocket(url);\n wsRef.current = ws;\n\n // MistPlayer-style timeout: if no message within 5 seconds, fall back to HTTP\n wsTimeoutRef.current = setTimeout(() => {\n if (ws.readyState <= WebSocket.OPEN) {\n if (debug) {\n console.debug('[useStreamState] WebSocket timeout (5s), falling back to HTTP polling');\n }\n ws.close();\n pollHttp();\n }\n }, WS_TIMEOUT_MS);\n\n ws.onopen = () => {\n if (debug) {\n console.debug('[useStreamState] WebSocket connected');\n }\n setSocketReady(true);\n };\n\n ws.onmessage = (event) => {\n // Clear timeout on first message\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n\n try {\n const data = JSON.parse(event.data) as MistStreamInfo;\n processStreamInfo(data);\n } catch (e) {\n console.warn('[useStreamState] Failed to parse WebSocket message:', e);\n }\n };\n\n ws.onerror = (_event) => {\n console.warn('[useStreamState] WebSocket error, falling back to HTTP polling');\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n ws.close();\n };\n\n ws.onclose = () => {\n wsRef.current = null;\n setSocketReady(false);\n\n if (!mountedRef.current || !enabled) return;\n\n // Fallback to HTTP polling or reconnect\n if (debug) {\n console.debug('[useStreamState] WebSocket closed, starting HTTP polling');\n }\n pollHttp();\n };\n } catch (error) {\n console.warn('[useStreamState] WebSocket connection failed:', error);\n // Fallback to HTTP polling\n pollHttp();\n }\n }, [mistBaseUrl, streamName, enabled, useWebSocket, debug, processStreamInfo, pollHttp]);\n\n /**\n * Manual refetch function\n */\n const refetch = useCallback(() => {\n if (useWebSocket && wsRef.current?.readyState === WebSocket.OPEN) {\n // WebSocket will receive updates automatically\n return;\n }\n pollHttp();\n }, [useWebSocket, pollHttp]);\n\n /**\n * Setup connection on mount and when options change\n * Always do initial HTTP poll to get full stream info (including sources),\n * then connect WebSocket for real-time status updates.\n * MistServer WebSocket updates may not include source array.\n */\n useEffect(() => {\n mountedRef.current = true;\n\n if (!enabled || !mistBaseUrl || !streamName) {\n setState(initialState);\n return;\n }\n\n // Reset state when stream changes\n setState({\n ...initialState,\n message: 'Connecting...',\n lastUpdate: Date.now(),\n });\n\n // Always do initial HTTP poll to get full data (including sources)\n // Then connect WebSocket for real-time updates\n const initializeConnection = async () => {\n // First HTTP poll to get complete stream info\n await pollHttp();\n\n // Then connect WebSocket for status updates (if enabled)\n if (useWebSocket && mountedRef.current) {\n connectWebSocket();\n }\n };\n\n initializeConnection();\n\n return () => {\n // Set mounted=false FIRST before any other cleanup\n mountedRef.current = false;\n if (debug) {\n console.debug('[useStreamState] cleanup starting, mountedRef set to false');\n }\n\n // Cleanup WebSocket timeout\n if (wsTimeoutRef.current) {\n clearTimeout(wsTimeoutRef.current);\n wsTimeoutRef.current = null;\n }\n\n // Cleanup WebSocket - remove handlers BEFORE closing to prevent onclose callback\n if (wsRef.current) {\n // Detach handlers first to prevent onclose from triggering pollHttp\n wsRef.current.onclose = null;\n wsRef.current.onerror = null;\n wsRef.current.onmessage = null;\n wsRef.current.onopen = null;\n wsRef.current.close();\n wsRef.current = null;\n }\n\n // Cleanup polling timeout\n if (pollTimeoutRef.current) {\n clearTimeout(pollTimeoutRef.current);\n pollTimeoutRef.current = null;\n }\n };\n }, [enabled, mistBaseUrl, streamName, useWebSocket, debug, connectWebSocket, pollHttp]);\n\n return {\n ...state,\n refetch,\n socketRef: wsRef,\n socketReady,\n };\n}\n\nexport default useStreamState;\n","import { useEffect, useState, useRef } from 'react';\nimport type { ContentType } from '@livepeer-frameworks/player-core';\nimport type { ContentEndpoints } from '../types';\n\nconst MAX_RETRIES = 3;\nconst INITIAL_DELAY_MS = 500;\n\ninterface Params {\n gatewayUrl: string;\n contentId: string;\n contentType?: ContentType;\n authToken?: string;\n}\n\nasync function fetchWithRetry(\n url: string,\n options: RequestInit,\n maxRetries: number = MAX_RETRIES,\n initialDelay: number = INITIAL_DELAY_MS\n): Promise<Response> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n return response;\n } catch (e) {\n lastError = e instanceof Error ? e : new Error('Fetch failed');\n\n // Don't retry on abort\n if (options.signal?.aborted) {\n throw lastError;\n }\n\n // Wait before retrying (exponential backoff)\n if (attempt < maxRetries - 1) {\n const delay = initialDelay * Math.pow(2, attempt);\n console.warn(`[useViewerEndpoints] Retry ${attempt + 1}/${maxRetries - 1} after ${delay}ms`);\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n throw lastError ?? new Error('Gateway unreachable after retries');\n}\n\nexport function useViewerEndpoints({ gatewayUrl, contentType: _contentType, contentId, authToken }: Params) {\n const [endpoints, setEndpoints] = useState<ContentEndpoints | null>(null);\n const [status, setStatus] = useState<'idle' | 'loading' | 'ready' | 'error'>('idle');\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => {\n if (!gatewayUrl || !contentId) return;\n setStatus('loading');\n setError(null);\n abortRef.current?.abort();\n const ac = new AbortController();\n abortRef.current = ac;\n\n (async () => {\n try {\n const graphqlEndpoint = gatewayUrl.replace(/\\/$/, '');\n const query = `\n query ResolveViewer($contentId: String!) {\n resolveViewerEndpoint(contentId: $contentId) {\n primary { nodeId baseUrl protocol url geoDistance loadScore outputs }\n fallbacks { nodeId baseUrl protocol url geoDistance loadScore outputs }\n metadata { contentType contentId title description durationSeconds status isLive viewers recordingSizeBytes clipSource createdAt }\n }\n }\n `;\n const res = await fetchWithRetry(graphqlEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n },\n body: JSON.stringify({ query, variables: { contentId } }),\n signal: ac.signal,\n });\n if (!res.ok) throw new Error(`Gateway GQL error ${res.status}`);\n const payload = await res.json();\n if (payload.errors?.length) throw new Error(payload.errors[0]?.message || 'GraphQL error');\n const resp = payload.data?.resolveViewerEndpoint;\n const primary = resp?.primary;\n const fallbacks = Array.isArray(resp?.fallbacks) ? resp.fallbacks : [];\n if (!primary) throw new Error('No endpoints');\n\n // Parse outputs JSON string (GraphQL returns JSON scalar as string)\n if (primary.outputs && typeof primary.outputs === 'string') {\n try { primary.outputs = JSON.parse(primary.outputs); } catch {}\n }\n if (fallbacks) {\n fallbacks.forEach((fb: any) => {\n if (fb.outputs && typeof fb.outputs === 'string') {\n try { fb.outputs = JSON.parse(fb.outputs); } catch {}\n }\n });\n }\n\n setEndpoints({ primary, fallbacks, metadata: resp?.metadata });\n setStatus('ready');\n } catch (e) {\n if (ac.signal.aborted) return;\n const message = e instanceof Error ? e.message : 'Unknown gateway error';\n console.error('[useViewerEndpoints] Gateway resolution failed:', message);\n setError(message);\n setStatus('error');\n }\n })();\n\n return () => ac.abort();\n }, [gatewayUrl, contentId, authToken]);\n\n return { endpoints, status, error };\n}\n\nexport default useViewerEndpoints;\n","import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\nimport { Button } from \"../ui/button\";\nimport type { ThumbnailOverlayProps } from \"../types\";\n\nconst ThumbnailOverlay: React.FC<ThumbnailOverlayProps> = ({\n thumbnailUrl,\n onPlay,\n message,\n showUnmuteMessage = false,\n style,\n className\n}) => {\n const handleClick = (e: React.MouseEvent | React.KeyboardEvent) => {\n e.stopPropagation();\n onPlay?.();\n };\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick(event);\n }\n }}\n style={style}\n className={cn(\n \"fw-player-thumbnail relative flex h-full min-h-[280px] w-full cursor-pointer items-center justify-center overflow-hidden rounded-xl bg-slate-950 text-foreground outline-none transition focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n , className)}\n >\n {thumbnailUrl && (\n <div\n className=\"absolute inset-0 bg-cover bg-center\"\n style={{ backgroundImage: `url(${thumbnailUrl})` }}\n />\n )}\n\n <div\n className={cn(\n \"absolute inset-0 bg-slate-950/70\",\n !thumbnailUrl && \"bg-gradient-to-br from-slate-900 via-slate-950 to-slate-900\"\n )}\n />\n\n <div className=\"relative z-10 flex max-w-[320px] flex-col items-center gap-4 px-6 text-center text-sm sm:gap-6\">\n {showUnmuteMessage ? (\n <div className=\"w-full rounded-lg border border-white/15 bg-black/80 p-4 text-sm text-white shadow-lg backdrop-blur\">\n <div className=\"mb-1 flex items-center justify-center gap-2 text-base font-semibold text-primary\">\n <span aria-hidden=\"true\">🔇</span> Click to unmute\n </div>\n <p className=\"text-xs text-white/80\">Stream is playing muted — tap to enable sound.</p>\n </div>\n ) : (\n <>\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n className=\"h-20 w-20 rounded-full bg-primary/90 text-primary-foreground shadow-lg shadow-primary/40 transition hover:bg-primary focus-visible:bg-primary\"\n aria-label=\"Play stream\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"ml-0.5 h-8 w-8\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n </Button>\n <div className=\"w-full rounded-lg border border-white/10 bg-black/70 p-5 text-white shadow-inner backdrop-blur\">\n <p className=\"text-base font-semibold text-primary\">\n {message ?? \"Click to play\"}\n </p>\n <p className=\"mt-1 text-xs text-white/70\">\n {message ? \"Start streaming instantly\" : \"Jump into the live feed\"}\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n );\n};\n\nexport default ThumbnailOverlay;\n","import { useEffect, useState, useRef, useCallback } from 'react';\nimport { MetaTrackManager, type MetaTrackEvent } from '@livepeer-frameworks/player-core';\nimport type { UseMetaTrackOptions } from '../types';\n\nexport interface UseMetaTrackReturn {\n /** Whether connected to MistServer WebSocket */\n isConnected: boolean;\n /** Connection state */\n connectionState: 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n /** List of subscribed track IDs */\n subscribedTracks: string[];\n /** Subscribe to a meta track */\n subscribe: (trackId: string, callback: (event: MetaTrackEvent) => void) => () => void;\n /** Unsubscribe from a meta track */\n unsubscribe: (trackId: string, callback: (event: MetaTrackEvent) => void) => void;\n /** Manually connect */\n connect: () => void;\n /** Manually disconnect */\n disconnect: () => void;\n /** Update playback time for timed event dispatch (call on video timeupdate) */\n setPlaybackTime: (timeInSeconds: number) => void;\n /** Handle seek event (call on video seeking/seeked) */\n onSeek: (newTimeInSeconds: number) => void;\n}\n\n/**\n * Hook for subscribing to real-time metadata from MistServer\n *\n * Uses native MistServer WebSocket protocol for low-latency metadata delivery:\n * - Subtitles/captions\n * - Live scores\n * - Timed events\n * - Chapter markers\n *\n * @example\n * ```tsx\n * const { isConnected, subscribe } = useMetaTrack({\n * mistBaseUrl: 'https://mist.example.com',\n * streamName: 'pk_...', // playbackId (view key)\n * enabled: true,\n * });\n *\n * useEffect(() => {\n * if (!isConnected) return;\n *\n * const unsubscribe = subscribe('1', (event) => {\n * if (event.type === 'subtitle') {\n * setSubtitle(event.data as SubtitleCue);\n * }\n * });\n *\n * return unsubscribe;\n * }, [isConnected, subscribe]);\n * ```\n */\nexport function useMetaTrack(options: UseMetaTrackOptions): UseMetaTrackReturn {\n const {\n mistBaseUrl,\n streamName,\n subscriptions: initialSubscriptions,\n enabled = true,\n } = options;\n\n const [isConnected, setIsConnected] = useState(false);\n const [connectionState, setConnectionState] = useState<'disconnected' | 'connecting' | 'connected' | 'reconnecting'>('disconnected');\n const [subscribedTracks, setSubscribedTracks] = useState<string[]>([]);\n const managerRef = useRef<MetaTrackManager | null>(null);\n\n // Create manager instance\n useEffect(() => {\n if (!enabled || !mistBaseUrl || !streamName) {\n if (managerRef.current) {\n managerRef.current.disconnect();\n managerRef.current = null;\n }\n setIsConnected(false);\n setConnectionState('disconnected');\n return;\n }\n\n managerRef.current = new MetaTrackManager({\n mistBaseUrl,\n streamName,\n subscriptions: initialSubscriptions,\n debug: false,\n });\n\n // Start polling connection state\n const pollState = () => {\n if (managerRef.current) {\n const state = managerRef.current.getState();\n setConnectionState(state);\n setIsConnected(state === 'connected');\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n };\n\n const pollInterval = setInterval(pollState, 500);\n\n // Connect\n managerRef.current.connect();\n pollState();\n\n return () => {\n clearInterval(pollInterval);\n if (managerRef.current) {\n managerRef.current.disconnect();\n managerRef.current = null;\n }\n setIsConnected(false);\n setConnectionState('disconnected');\n };\n }, [enabled, mistBaseUrl, streamName, initialSubscriptions]);\n\n /**\n * Subscribe to a meta track\n */\n const subscribe = useCallback((trackId: string, callback: (event: MetaTrackEvent) => void): () => void => {\n if (!managerRef.current) {\n return () => {};\n }\n\n const unsubscribe = managerRef.current.subscribe(trackId, callback);\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n\n return () => {\n unsubscribe();\n if (managerRef.current) {\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n };\n }, []);\n\n /**\n * Unsubscribe from a meta track\n */\n const unsubscribe = useCallback((trackId: string, callback: (event: MetaTrackEvent) => void) => {\n if (managerRef.current) {\n managerRef.current.unsubscribe(trackId, callback);\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n }, []);\n\n /**\n * Manually connect\n */\n const connect = useCallback(() => {\n managerRef.current?.connect();\n }, []);\n\n /**\n * Manually disconnect\n */\n const disconnect = useCallback(() => {\n managerRef.current?.disconnect();\n }, []);\n\n /**\n * Update playback time for timed event dispatch\n * Call this on video timeupdate events to keep subtitle/chapter timing in sync\n */\n const setPlaybackTime = useCallback((timeInSeconds: number) => {\n managerRef.current?.setPlaybackTime(timeInSeconds);\n }, []);\n\n /**\n * Handle seek event - clears buffered events and resets state\n * Call this on video seeking/seeked events\n */\n const onSeek = useCallback((newTimeInSeconds: number) => {\n managerRef.current?.onSeek(newTimeInSeconds);\n }, []);\n\n return {\n isConnected,\n connectionState,\n subscribedTracks,\n subscribe,\n unsubscribe,\n connect,\n disconnect,\n setPlaybackTime,\n onSeek,\n };\n}\n\nexport default useMetaTrack;\n","import { useEffect, useState, useRef, useCallback } from 'react';\nimport { QualityMonitor, type PlaybackQuality } from '@livepeer-frameworks/player-core';\nimport type { UsePlaybackQualityOptions } from '../types';\n\n/**\n * Hook to monitor video playback quality\n *\n * Tracks:\n * - Buffer health (seconds ahead)\n * - Stall count\n * - Frame drop rate\n * - Estimated bitrate\n * - Latency (live streams)\n * - Composite quality score (0-100)\n *\n * @example\n * ```tsx\n * const { quality, isMonitoring } = usePlaybackQuality({\n * videoElement,\n * enabled: true,\n * thresholds: { minScore: 60 },\n * onQualityDegraded: (q) => console.log('Quality dropped:', q.score),\n * });\n *\n * return <div>Quality: {quality?.score ?? '--'}</div>;\n * ```\n */\nexport function usePlaybackQuality(options: UsePlaybackQualityOptions) {\n const {\n videoElement,\n enabled = true,\n sampleInterval = 500,\n thresholds,\n onQualityDegraded,\n } = options;\n\n const [quality, setQuality] = useState<PlaybackQuality | null>(null);\n const [isMonitoring, setIsMonitoring] = useState(false);\n const monitorRef = useRef<QualityMonitor | null>(null);\n\n // Create/update monitor instance\n useEffect(() => {\n monitorRef.current = new QualityMonitor({\n sampleInterval,\n thresholds,\n onQualityDegraded,\n onSample: setQuality,\n });\n\n return () => {\n monitorRef.current?.stop();\n monitorRef.current = null;\n };\n }, [sampleInterval, thresholds, onQualityDegraded]);\n\n // Start/stop monitoring based on videoElement and enabled state\n useEffect(() => {\n if (!enabled || !videoElement || !monitorRef.current) {\n monitorRef.current?.stop();\n setIsMonitoring(false);\n return;\n }\n\n monitorRef.current.start(videoElement);\n setIsMonitoring(true);\n\n return () => {\n monitorRef.current?.stop();\n setIsMonitoring(false);\n };\n }, [videoElement, enabled]);\n\n /**\n * Get current quality snapshot\n */\n const getCurrentQuality = useCallback((): PlaybackQuality | null => {\n return monitorRef.current?.getCurrentQuality() ?? null;\n }, []);\n\n /**\n * Get rolling average quality\n */\n const getAverageQuality = useCallback((): PlaybackQuality | null => {\n return monitorRef.current?.getAverageQuality() ?? null;\n }, []);\n\n /**\n * Get quality history\n */\n const getHistory = useCallback((): PlaybackQuality[] => {\n return monitorRef.current?.getHistory() ?? [];\n }, []);\n\n /**\n * Reset stall counters\n */\n const resetStallCounters = useCallback(() => {\n monitorRef.current?.resetStallCounters();\n }, []);\n\n /**\n * Get total stall time\n */\n const getTotalStallMs = useCallback((): number => {\n return monitorRef.current?.getTotalStallMs() ?? 0;\n }, []);\n\n return {\n /** Current quality metrics */\n quality,\n /** Whether monitoring is active */\n isMonitoring,\n /** Get current quality snapshot */\n getCurrentQuality,\n /** Get rolling average quality */\n getAverageQuality,\n /** Get quality history */\n getHistory,\n /** Reset stall counters */\n resetStallCounters,\n /** Get total stall time in ms */\n getTotalStallMs,\n };\n}\n\nexport default usePlaybackQuality;\n","/**\n * usePlayerSelection\n *\n * React hook for subscribing to PlayerManager selection events.\n * Uses event-driven updates instead of polling - no render spam.\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport type {\n PlayerManager,\n PlayerSelection,\n PlayerCombination,\n StreamInfo,\n PlaybackMode,\n} from '@livepeer-frameworks/player-core';\n\nexport interface UsePlayerSelectionOptions {\n /** Stream info to compute selections for */\n streamInfo: StreamInfo | null;\n /** Playback mode override */\n playbackMode?: PlaybackMode;\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport interface UsePlayerSelectionReturn {\n /** Current best selection (null if no compatible player) */\n selection: PlayerSelection | null;\n /** All player+source combinations with scores */\n combinations: PlayerCombination[];\n /** Whether initial computation has completed */\n ready: boolean;\n /** Force recomputation (invalidates cache) */\n refresh: () => void;\n}\n\n/**\n * Subscribe to player selection changes from a PlayerManager.\n *\n * This hook uses the event system in PlayerManager, which means:\n * - Initial computation happens once when streamInfo is provided\n * - Updates only fire when selection actually changes (different player+source)\n * - No render spam from React strict mode or frequent re-renders\n *\n * @example\n * ```tsx\n * const { selection, combinations, ready } = usePlayerSelection(globalPlayerManager, {\n * streamInfo,\n * playbackMode: 'auto',\n * });\n *\n * if (!ready) return <Loading />;\n * if (!selection) return <NoPlayerAvailable />;\n *\n * return <div>Selected: {selection.player} + {selection.source.type}</div>;\n * ```\n */\nexport function usePlayerSelection(\n manager: PlayerManager,\n options: UsePlayerSelectionOptions\n): UsePlayerSelectionReturn {\n const { streamInfo, playbackMode, debug } = options;\n\n const [selection, setSelection] = useState<PlayerSelection | null>(null);\n const [combinations, setCombinations] = useState<PlayerCombination[]>([]);\n const [ready, setReady] = useState(false);\n\n // Subscribe to events\n useEffect(() => {\n const unsubSelection = manager.on('selection-changed', (sel) => {\n if (debug) {\n console.log('[usePlayerSelection] Selection changed:', sel?.player, sel?.source?.type);\n }\n setSelection(sel);\n });\n\n const unsubCombos = manager.on('combinations-updated', (combos) => {\n if (debug) {\n console.log('[usePlayerSelection] Combinations updated:', combos.length);\n }\n setCombinations(combos);\n setReady(true);\n });\n\n return () => {\n unsubSelection();\n unsubCombos();\n };\n }, [manager, debug]);\n\n // Trigger initial computation when streamInfo changes\n useEffect(() => {\n if (!streamInfo) {\n setSelection(null);\n setCombinations([]);\n setReady(false);\n return;\n }\n\n // This will use cache if available, or compute + emit events if not\n manager.getAllCombinations(streamInfo, playbackMode);\n }, [manager, streamInfo, playbackMode]);\n\n // Manual refresh function\n const refresh = useCallback(() => {\n if (!streamInfo) return;\n manager.invalidateCache();\n manager.getAllCombinations(streamInfo, playbackMode);\n }, [manager, streamInfo, playbackMode]);\n\n return {\n selection,\n combinations,\n ready,\n refresh,\n };\n}\n","import { useEffect, useRef, useCallback } from 'react';\nimport { TelemetryReporter, type TelemetryOptions, type PlaybackQuality, type ContentType } from '@livepeer-frameworks/player-core';\n\nexport interface UseTelemetryOptions extends TelemetryOptions {\n /** Video element to monitor */\n videoElement: HTMLVideoElement | null;\n /** Content ID being played */\n contentId: string;\n /** Content type */\n contentType: ContentType;\n /** Player type name */\n playerType: string;\n /** Protocol being used */\n protocol: string;\n /** Optional quality getter function */\n getQuality?: () => PlaybackQuality | null;\n}\n\n/**\n * Hook to send telemetry data to a server\n *\n * Reports playback metrics at configurable intervals:\n * - Current time and duration\n * - Buffer health\n * - Stall count and duration\n * - Quality score and bitrate\n * - Frame decode/drop stats\n * - Errors encountered\n *\n * Uses navigator.sendBeacon() for reliable reporting on page unload.\n *\n * @example\n * ```tsx\n * const { sessionId, recordError } = useTelemetry({\n * enabled: true,\n * endpoint: '/api/telemetry',\n * interval: 5000,\n * videoElement,\n * contentId: 'pk_...', // playbackId (view key)\n * contentType: 'live',\n * playerType: 'hlsjs',\n * protocol: 'HLS',\n * getQuality: () => qualityMonitor.getCurrentQuality(),\n * });\n *\n * // Record custom error\n * recordError('NETWORK_ERROR', 'Connection lost');\n * ```\n */\nexport function useTelemetry(options: UseTelemetryOptions) {\n const {\n enabled,\n endpoint,\n interval,\n authToken,\n batchSize,\n videoElement,\n contentId,\n contentType,\n playerType,\n protocol,\n getQuality,\n } = options;\n\n const reporterRef = useRef<TelemetryReporter | null>(null);\n\n // Create reporter instance\n useEffect(() => {\n if (!enabled || !endpoint || !contentId) {\n reporterRef.current?.stop();\n reporterRef.current = null;\n return;\n }\n\n reporterRef.current = new TelemetryReporter({\n endpoint,\n authToken,\n interval,\n batchSize,\n contentId,\n contentType,\n playerType,\n protocol,\n });\n\n return () => {\n reporterRef.current?.stop();\n reporterRef.current = null;\n };\n }, [enabled, endpoint, authToken, interval, batchSize, contentId, contentType, playerType, protocol]);\n\n // Start/stop reporting when video element changes\n useEffect(() => {\n if (!enabled || !videoElement || !reporterRef.current) {\n return;\n }\n\n reporterRef.current.start(videoElement, getQuality);\n\n return () => {\n reporterRef.current?.stop();\n };\n }, [enabled, videoElement, getQuality]);\n\n /**\n * Record a custom error\n */\n const recordError = useCallback((code: string, message: string) => {\n reporterRef.current?.recordError(code, message);\n }, []);\n\n /**\n * Get current session ID\n */\n const getSessionId = useCallback((): string | null => {\n return reporterRef.current?.getSessionId() ?? null;\n }, []);\n\n /**\n * Check if telemetry is active\n */\n const isActive = useCallback((): boolean => {\n return reporterRef.current?.isActive() ?? false;\n }, []);\n\n return {\n /** Session ID for this playback session */\n sessionId: reporterRef.current?.getSessionId() ?? null,\n /** Record a custom error */\n recordError,\n /** Get current session ID */\n getSessionId,\n /** Check if telemetry is active */\n isActive,\n };\n}\n\nexport default useTelemetry;\n"],"names":["ASPECT_RATIO","COLORS","pickNextColor","current","length","next","Math","floor","random","DvdLogo","_ref","parentRef","_ref$scale","scale","_useState2","_slicedToArray","useState","top","left","position","setPosition","positionRef","useRef","useEffect","_useState4","width","height","dimensions","setDimensions","dimensionsRef","velocityRef","x","y","_useState6","color","setColor","recalculateDimensions","React","useCallback","parent","parentWidth","clientWidth","parentHeight","clientHeight","maxHeight","nextDimensions","max","maxTop","maxLeft","startPosition","baseSpeed","min","ResizeObserver","observer","observe","disconnect","onResize","window","addEventListener","removeEventListener","animationFrame","lastTimestamp","performance","now","animate","timestamp","dims","deltaMs","speedMultiplier","_positionRef$current","_velocityRef$current","bounced","nextPosition","requestAnimationFrame","cancelAnimationFrame","_jsx","className","style","concat","children","viewBox","fill","d","logomarkAsset","AnimatedBubble","index","size","setSize","opacity","setOpacity","getRandomPosition","getRandomSize","animationCycle","setTimeout","timeout","clearTimeout","bubbleColors","borderRadius","background","transition","pointerEvents","userSelect","CenterLogo","_ref2","containerRef","_ref2$scale","onHitmarker","_useState8","logoSize","setLogoSize","_useState0","offset","setOffset","_useState10","isHovered","setIsHovered","containerWidth","containerHeight","minDimension","handleMouseMove","e","rect","getBoundingClientRect","centerX","centerY","deltaX","clientX","deltaY","clientY","distance","sqrt","maxDistance","pushDistance","handleMouseLeave","container","_jsxs","transform","display","alignItems","justifyContent","zIndex","animation","src","alt","onClick","stopPropagation","filter","cursor","WebkitUserDrag","StatusIcon","_ref3","status","iconClass","stroke","strokeLinecap","strokeLinejoin","strokeWidth","cx","cy","r","StatusOverlay","_ref4","message","percentage","error","onRetry","showRetry","showProgress","undefined","displayMessage","bottom","flexDirection","gap","maxWidth","textAlign","fontSize","fontFamily","overflow","type","padding","border","fontWeight","onMouseEnter","currentTarget","onMouseLeave","createSyntheticHitmarkerSound","audioContext","AudioContext","webkitAudioContext","oscillator1","createOscillator","oscillator2","gainNode1","createGain","gainNode2","masterGain","connect","destination","frequency","setValueAtTime","currentTime","exponentialRampToValueAtTime","gain","linearRampToValueAtTime","startTime","stopTime","start","stop","_unused2","IdleScreen","_ref5","_ref5$message","_useState12","hitmarkers","setHitmarkers","styleId","document","getElementById","createElement","id","textContent","head","appendChild","ref","inset","backgroundSize","map","hitmarker","backgroundColor","boxShadow","_toConsumableArray","Array","_","animationDelay","newHitmarker","Date","prev","audio","Audio","volume","play","_unused","playHitmarkerSound","h","right","TitleOverlay","title","description","isVisible","cn","StatsPanel","_video$playbackRate$t","_video$playbackRate","_quality$score$toFixe","_quality$score","_quality$frameDropRat","_quality$frameDropRat2","_quality$stallCount","_metadata$viewers","_streamState$status","_metadata$mist","_mistInfo$type","_mistInfo$meta2","isOpen","onClose","metadata","streamState","quality","videoElement","protocol","nodeId","geoDistance","_metadata$tracks","tracks","video","currentRes","videoWidth","videoHeight","buffered","end","toFixed","playbackRate","qualityScore","score","bitrateKbps","bitrate","frameDropRate","stallCount","latency","round","viewers","streamStatus","mistInfo","mist","streamInfo","mistType","mistBufferWindow","meta","buffer_window","mistLastMs","lastms","mistUnixOffset","unixoffset","stats","label","value","String","_mistInfo$meta","mistTracks","Object","values","t","codec","bps","fps","fpks","channels","sampleRate","rate","deriveTracksFromMist","_t$codec2","_t$codec","resolution","join","unshift","durationSeconds","mins","secs","push","padStart","recordingSizeBytes","mb","initialState","state","endpoints","duration","NaN","isPlaying","isPaused","isBuffering","isMuted","isPassiveError","hasPlaybackStarted","isHoldingSpeed","holdSpeed","isHovering","shouldShowControls","isLoopEnabled","isFullscreen","isPiPActive","isEffectivelyLive","shouldShowIdleScreen","currentPlayerInfo","currentSourceInfo","playbackQuality","subtitlesEnabled","qualities","textTracks","usePlayerController","config","_config$enabled","enabled","onStateChange","onStreamStateChange","onError","onReady","controllerConfig","_objectWithoutProperties","_excluded","controllerRef","setState","configRef","controller","PlayerController","contentId","contentType","gatewayUrl","mistUrl","authToken","autoplay","muted","controls","poster","debug","unsubs","on","newState","_objectSpread","getMetadata","getEndpoints","getStreamInfo","getCurrentPlayerInfo","getCurrentSourceInfo","getQualities","handleVideoEvent","_controllerRef$curren","_controllerRef$curren2","shouldSuppressVideoEvents","call","c","getVolume","getPlaybackQuality","isSubtitlesEnabled","syncState","_ref6","player","source","url","_ref7","_ref8","_ref9","_ref0","isPiP","_ref1","speed","_ref10","attach","err","console","warn","forEach","fn","destroy","_asyncToGenerator","_regenerator","m","_callee","_controllerRef$curren3","w","_context","n","a","pause","_controllerRef$curren4","togglePlay","_controllerRef$curren5","seek","time","_controllerRef$curren6","seekBy","delta","_controllerRef$curren7","setVolume","_controllerRef$curren8","toggleMute","_controllerRef$curren9","toggleLoop","_controllerRef$curren0","toggleFullscreen","_callee2","_controllerRef$curren1","_context2","togglePiP","_callee3","_controllerRef$curren10","_context3","togglePictureInPicture","toggleSubtitles","_controllerRef$curren11","clearError","_controllerRef$curren12","jumpToLive","_controllerRef$curren13","retry","_callee4","_controllerRef$curren14","_context4","reload","_callee5","_controllerRef$curren15","_context5","_controllerRef$curren16","_controllerRef$curren17","selectQuality","_controllerRef$curren18","handleMouseEnter","_controllerRef$curren19","_controllerRef$curren20","_controllerRef$curren21","handleTouchStart","_controllerRef$curren22","setDevModeOptions","_ref16","_callee6","options","_controllerRef$curren23","_context6","_x","apply","this","arguments","PlayerContext","createContext","usePlayerContextOptional","useContext","Slider","forwardRef","trackClassName","thumbClassName","_ref$showTrack","showTrack","hoverThumb","_hoverThumb","_ref$accentColor","accentColor","_ref$orientation","orientation","props","rangeColorClass","thumbColorClass","SliderPrimitive","Root","Track","Range","Thumb","displayName","SeekBar","_ref$disabled","disabled","onSeek","_ref$isLive","isLive","_ref$seekableStart","seekableStart","liveEdge","_ref$commitOnRelease","commitOnRelease","trackRef","setIsHovering","isDragging","setIsDragging","dragTime","setDragTime","dragTimeRef","hoverPosition","setHoverPosition","hoverTime","setHoverTime","effectiveLiveEdge","seekableWindow","displayTime","progressPercent","useMemo","positionInWindow","Number","isFinite","bufferedSegments","rangeStart","rangeSize","segments","i","relativeStart","relativeEnd","startPercent","endPercent","formatTime","seconds","total","hours","minutes","formatLiveTime","edge","behindSeconds","getTimeFromPosition","percent","handleClick","handleMouseDown","preventDefault","handleDragMove","moveEvent","handleDragEnd","pending","showThumb","canShowTooltip","onMouseMove","onMouseDown","role","tabIndex","segment","PlayIcon","_ref$size","_ref$color","_ref$className","PauseIcon","_ref2$size","_ref2$color","_ref2$className","SkipBackIcon","_ref3$size","_ref3$color","_ref3$className","textAnchor","SkipForwardIcon","_ref4$size","_ref4$color","_ref4$className","VolumeUpIcon","_ref5$size","_ref5$color","_ref5$className","points","VolumeOffIcon","_ref6$size","_ref6$color","_ref6$className","x1","y1","x2","y2","FullscreenIcon","_ref7$size","_ref7$color","_ref7$className","FullscreenExitIcon","_ref8$size","_ref8$color","_ref8$className","PictureInPictureIcon","_ref9$size","_ref9$color","_ref9$className","rx","ry","SettingsIcon","_ref10$size","_ref10$color","_ref10$className","PlayPauseIcon","_ref11","VolumeIcon","_ref12","_excluded2","FullscreenToggleIcon","_ref13","_excluded3","StatsIcon","_ref14","_ref14$size","_ref14$color","_ref14$className","SeekToLiveIcon","_ref15","_ref15$size","_ref15$color","_ref15$className","PlayerControls","_ctx$state","_mistStreamInfo$meta","_player$getTextTracks","_player$getTextTracks2","_mistStreamInfo$meta$","_mistStreamInfo$meta2","_mistStreamInfo$meta3","_player$getSeekableSt","_player$getLiveEdge","_ref$isVisible","_className","mistStreamInfo","_ref$playbackMode","playbackMode","onModeChange","sourceType","isContentLive","propVideoElement","_ref$qualities","propQualities","onSelectQuality","propIsMuted","propVolume","onVolumeChange","onToggleMute","propIsPlaying","onTogglePlay","onToggleFullscreen","propIsFullscreen","onToggleLoop","onJumpToLive","ctx","contextVideo","setVideo","videoCheckIntervalRef","findVideoElement","_player$getVideoEleme","_document$querySelect","getVideoElement","querySelector","v","setInterval","clearInterval","_player$getQualities","playerQualities","entries","sort","b","getTextTracks","internalIsPlaying","setInternalIsPlaying","internalIsMuted","setInternalIsMuted","internalIsFullscreen","setInternalIsFullscreen","hasAudio","setHasAudio","setBuffered","internalVolume","setInternalVolume","_useState14","setPlaybackRate","volumeValue","_useState16","qualityValue","setQualityValue","_useState18","captionValue","setCaptionValue","_useState20","isSettingsOpen","setIsSettingsOpen","_useState22","isNearLiveState","setIsNearLiveState","handleWindowClick","event","target","closest","timeoutId","deriveBufferWindowMs","list","firstmsValues","firstms","lastmsValues","bufferWindowMs","isLiveContent","isWebRTC","isMediaStreamSource","supportsPlaybackRate","coreSupportsPlaybackRate","allowMediaStreamDvr","_useMemo","calculateSeekableRange","calcSeekableStart","calcLiveEdge","controllerSeekableStart","getSeekableStart","controllerLiveEdge","getLiveEdge","useControllerRange","hasDvrWindow","liveThresholds","calculateLiveThresholds","canSeek","canSeekStream","calculateIsNearLive","hasSeekToLiveRef","updatePlayingState","paused","updateMutedState","updateFullscreenState","fullscreenElement","updatePlaybackRate","activeTrack","find","track","active","updateBuffered","_player$getBufferedRa","_player$getBufferedRa2","getBufferedRanges","checkAudio","srcObject","MediaStream","audioTracks","getAudioTracks","videoAny","handleMute","_player$isMuted","_player$isMuted2","_player$setMuted","nextMuted","setMuted","handleQualityChange","_player$selectQuality","handleCaptionChange","_player$selectTextTra","_player$selectTextTra2","selectTextTrack","timeDisplay","formatTimeDisplay","_useState24","isVolumeHovered","setIsVolumeHovered","_useState26","isVolumeFocused","setIsVolumeFocused","isVolumeExpanded","_player$isPaused","_player$isPaused2","newTime","maxTime","onFocusCapture","onBlurCapture","contains","relatedTarget","step","onValueChange","_value$","_player$jumpToLive","mode","SPEED_PRESETS","handleSpeedChange","q","exitFullscreen","requestFullscreen","SOURCE_TYPE_LABELS","whep","DevModePanel","_playerStats$levels","onSettingsChange","onReload","currentPlayer","currentSource","_isVisible","controlledIsOpen","onOpenChange","internalIsOpen","setInternalIsOpen","setIsOpen","activeTab","setActiveTab","setCurrentComboIndex","hoveredComboIndex","setHoveredComboIndex","tooltipAbove","setTooltipAbove","showDisabledPlayers","setShowDisabledPlayers","comboListRef","qualityMonitorRef","playbackScore","setPlaybackScore","setQualityScore","setStallCount","setFrameDropRate","playerStats","setPlayerStats","statsIntervalRef","QualityMonitor","sampleInterval","onSample","getPlaybackScore","pollStats","_stats","p","globalPlayerManager","getCurrentPlayer","getStats","allCombinations","getAllCombinations","combinations","compatible","activeComboIndex","findIndex","shortname","activeCompatibleIndex","handleReload","handleNextCombo","nextIdx","combo","forcePlayer","forceType","forceSource","sourceIndex","handleSelectCombo","setStats","updateStats","readyState","networkState","interval","name","charAt","toUpperCase","slice","borderBottom","_combo$scoreBreakdown","_combo$scoreBreakdown2","_combo$scoreBreakdown3","_combo$scoreBreakdown4","isCodecIncompat","codecIncompatible","isActive","typeLabel","split","pop","row","containerRect","relativePosition","playerName","scoreBreakdown","trackTypes","_Fragment","trackScore","weights","priorityScore","priority","sourceScore","reliabilityScore","reliability","modeBonus","routingBonus","routing","incompatibleReason","currentBitrate","bandwidthEstimate","currentLevel","levels","framesPerSecond","framesDecoded","framesDropped","packetLossRate","jitter","jitterBufferDelay","network","rtt","keys","lang","SpeedIndicator","FastForwardIcon","SkipIndicator","direction","_ref$seconds","onHide","isAnimating","setIsAnimating","timer","isBack","RewindIcon","ContextMenu","ContextMenuPrimitive","ContextMenuTrigger","Trigger","SubTrigger","ChevronRight","SubContent","ContextMenuContent","Portal","Content","ContextMenuItem","_excluded4","Item","checked","_excluded5","CheckboxItem","ItemIndicator","Check","_excluded6","RadioItem","Circle","_excluded7","Label","ContextMenuSeparator","_excluded8","Separator","PlayerInner","_state$endpoints","_state$currentPlayerI","_state$endpoints2","_state$metadata","_state$metadata2","_state$streamState","_state$streamState2","_state$streamState3","_state$streamState4","_state$streamState5","_state$currentSourceI","_state$streamState6","_ref$thumbnailUrl","thumbnailUrl","propsEndpoints","isStatsOpen","setIsStatsOpen","isDevPanelOpen","setIsDevPanelOpen","skipDirection","setSkipDirection","devPlaybackMode","setDevPlaybackMode","_usePlayerController","stockControls","playerState","handleDevSettingsChange","settings","handleModeChange","handleStatsToggle","handleSkipIndicatorHide","primaryEndpoint","primary","isLegacyPlayer","useStockControls","showTitleOverlay","showBufferingSpinner","showWaitingForEndpoint","waitingMessage","asChild","devMode","showStatsButton","onStatsToggle","WebkitUserSelect","MozUserSelect","msUserSelect","WebkitTouchCallout","buttonVariants","cva","variants","variant","default","secondary","ghost","outline","destructive","subtle","link","sm","lg","icon","defaultVariants","Button","_ref$asChild","Comp","Slot","getStatusLabel","PlayerErrorBoundary","_this","_classCallCheck","_callSuper","handleRetry","_this$props$onRetry","_this$props","hasError","_inherits","Component","key","errorInfo","_this$props$onError","_this$props2","_this$state$error","fallback","badgeVariants","isOnline","lastUpdate","fetchWithRetry","_x2","_fetchWithRetry","maxRetries","initialDelay","lastError","_loop","_ret","attempt","_args3","response","_options$signal","delay","_t2","fetch","Error","signal","aborted","pow","Promise","resolve","_regeneratorValues","_ref0$size","_ref0$color","_ref0$className","_ref1$size","_ref1$color","_ref1$className","_ref3$message","noiseBuffer","createBuffer","noiseSource","createBufferSource","noiseData","getChannelData","buffer","noiseGain","log","minHeight","textShadow","playerController","Provider","_ref2$visible","visible","backdropFilter","onPlay","_ref$showUnmuteMessag","showUnmuteMessage","onKeyDown","backgroundImage","mistBaseUrl","streamName","initialSubscriptions","subscriptions","_options$enabled","isConnected","setIsConnected","connectionState","setConnectionState","subscribedTracks","setSubscribedTracks","managerRef","MetaTrackManager","pollState","getState","getSubscribedTracks","pollInterval","subscribe","trackId","callback","unsubscribe","_managerRef$current","_managerRef$current2","setPlaybackTime","timeInSeconds","_managerRef$current3","newTimeInSeconds","_managerRef$current4","_options$sampleInterv","thresholds","onQualityDegraded","setQuality","isMonitoring","setIsMonitoring","monitorRef","_monitorRef$current","_monitorRef$current2","_monitorRef$current3","getCurrentQuality","_monitorRef$current$g","_monitorRef$current4","getAverageQuality","_monitorRef$current$g2","_monitorRef$current5","getHistory","_monitorRef$current$g3","_monitorRef$current6","resetStallCounters","_monitorRef$current7","getTotalStallMs","_monitorRef$current$g4","_monitorRef$current8","context","manager","selection","setSelection","setCombinations","ready","setReady","unsubSelection","sel","_sel$source","unsubCombos","combos","refresh","invalidateCache","_options$pollInterval","_options$useWebSocket","useWebSocket","_options$debug","socketReady","setSocketReady","wsRef","pollTimeoutRef","wsTimeoutRef","mountedRef","processStreamInfo","data","lowerError","toLowerCase","includes","on_error","getStatusMessage","perc","_prev$streamInfo","_prev$streamInfo2","_data$meta","_prev$streamInfo3","mergedStreamInfo","pollHttp","baseUrl","text","jsonpMatch","_t","replace","encodeURIComponent","method","headers","Accept","ok","match","JSON","parse","connectWebSocket","close","wsUrl","ws","WebSocket","OPEN","onopen","onmessage","onerror","_event","onclose","refetch","_wsRef$current","initializeConnection","socketRef","_reporterRef$current$3","_reporterRef$current7","endpoint","batchSize","playerType","getQuality","reporterRef","_reporterRef$current","TelemetryReporter","_reporterRef$current2","_reporterRef$current3","recordError","code","_reporterRef$current4","getSessionId","_reporterRef$current$","_reporterRef$current5","_reporterRef$current$2","_reporterRef$current6","sessionId","setEndpoints","setStatus","setError","abortRef","_abortRef$current","abort","ac","AbortController","_payload$errors","_payload$errors$","_payload$data","graphqlEndpoint","res","payload","resp","fallbacks","Authorization","body","stringify","query","variables","json","errors","resolveViewerEndpoint","isArray","outputs","fb"],"mappings":"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"}