stormcloud-video-player 0.7.49 → 0.7.50

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,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/OverlayRenderer.cjs","../../src/ui/OverlayRenderer.tsx","../../src/utils/overlays.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","OverlayRenderer_exports","OverlayRenderer","module","exports","import_react","require","OVERLAY_API_BASE","timeStringToSeconds","timeStr","parts","split","length","hours","parseInt","minutes","secStr","dotIdx","indexOf","seconds","substring","msFrag","ms","padEnd","num","parseFloat","isFinite","Math","max","isOverlayActive","overlay","currentTime","visible","startSec","start_time","durationSec","duration","resolveImageUrl","imageUrl","apiBaseUrl","startsWith","url","URL","origin","import_jsx_runtime","computeVideoDimensions","video","nativeWidth","videoWidth","nativeHeight","videoHeight","displayWidth","offsetWidth","displayHeight","offsetHeight","videoAspect","displayAspect","renderWidth","renderHeight","offsetX","offsetY","image_url","jsx","src","pointerEvents","content","alignItems","justifyContent","fontSize","fontFamily","fontWeight","textAlign","boxSizing","wordBreak","textShadow","userSelect","lineHeight","text","parseRSSXml","xmlText","stripped","maxItems","replace","DOMParser","parseFromString","doc","querySelectorAll","map","item","querySelector","textContent","trim","description","pubDate","i","items","Map","cachedFetchRSSItems","rssUrl","rssCache","cached","expiresAt","now","promise","fetchRSSItems","catch","err","RSS_CACHE_TTL_MS","encoded","resp","data","window","location","fetch","ok","includes","json","contents","Error","scroller_config","useId","useState","rssItems","setRssItems","rssLoading","setRssLoading","rssError","setRssError","cfg","rss_url","max_items","auto_refresh","updateInterval","update_interval","useEffect","use_custom_text","custom_text","cancelled","finally","autoRefresh","interval","setInterval","delete","then","clearInterval","sep","separator_char","segments","show_title","title","push","show_description","show_timestamp","Date","toLocaleDateString","show_author","author","show_category","join","category","scrollSpeed","scroll_speed","font_size","font_family","font_weight","textColor","text_color","background_color","background_opacity","borderRadius","border_radius","itemSpacing","item_spacing","padding","label","labelLine2","label_line2","labelColor","label_color","accentColor","accent_color","showAccentLine","show_accent_line","isHorizontal","direction","isReverse","fullText","animId","uid","id","keyframes","jsxs","Fragment","children","style","width","height","display","flexDirection","overflow","backgroundColor","bgOpacity","hexToRgb","bgColor","color","isEquitiesStrip","background","flexShrink","flex","minHeight","pad","gap","round","labelTextColor","boxShadow","alignSelf","maxWidth","letterSpacing","textTransform","whiteSpace","opacity","position","minWidth","animation","willChange","copy","paddingRight","seg","React","margin","paddingBottom","parseConfig","JSON","parse","parseClockMMSS","clock","m","exec","formatClockMMSS","totalSec","s","floor","mm","ss","toString","padStart","useScoreBugClock","overlayId","sourceClock","initialSec","setNow","startRef","useRef","current","source","at","tick","elapsed","remaining","ScoreBugOverlay","size","liveClock","f","w","displayClock","displayPeriod","period","showMiddleCol","Boolean","textOverflow","homeTeam","marginTop","homeScore","awayTeam","awayScore","sponsorText","sponsorImageUrl","borderTop","alt","objectFit","LowerThirdOverlay","accentH","h","headline","subtitle","QrCodeOverlay","qrSide","min","qrUrl","encodeURIComponent"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/ui/OverlayRenderer.tsx\nvar OverlayRenderer_exports = {};\n__export(OverlayRenderer_exports, {\n OverlayRenderer: () => OverlayRenderer\n});\nmodule.exports = __toCommonJS(OverlayRenderer_exports);\nvar import_react = __toESM(require(\"react\"), 1);\n\n// src/utils/overlays.ts\nvar OVERLAY_API_BASE = \"https://adstorm.co/api-adstorm-dev\";\nfunction timeStringToSeconds(timeStr) {\n if (!timeStr) return 0;\n const parts = timeStr.split(\":\");\n if (parts.length >= 3) {\n const hours = parseInt(parts[0] ?? \"0\", 10) || 0;\n const minutes = parseInt(parts[1] ?? \"0\", 10) || 0;\n const secStr = parts[2] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds = parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return hours * 3600 + minutes * 60 + seconds + ms / 1e3;\n }\n if (parts.length === 2) {\n const minutes = parseInt(parts[0] ?? \"0\", 10) || 0;\n const secStr = parts[1] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds = parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return minutes * 60 + seconds + ms / 1e3;\n }\n const num = parseFloat(timeStr);\n return isFinite(num) ? Math.max(0, num) : 0;\n}\nfunction isOverlayActive(overlay, currentTime) {\n if (!overlay.visible) return false;\n const startSec = timeStringToSeconds(overlay.start_time);\n const durationSec = timeStringToSeconds(overlay.duration);\n if (durationSec <= 0) return false;\n return currentTime >= startSec && currentTime < startSec + durationSec;\n}\nfunction resolveImageUrl(imageUrl, apiBaseUrl = OVERLAY_API_BASE) {\n if (!imageUrl) return \"\";\n if (imageUrl.startsWith(\"http://\") || imageUrl.startsWith(\"https://\")) {\n return imageUrl;\n }\n if (imageUrl.startsWith(\"/\")) {\n try {\n const url = new URL(apiBaseUrl);\n return `${url.origin}${imageUrl}`;\n } catch {\n return imageUrl;\n }\n }\n return `${apiBaseUrl}/${imageUrl}`;\n}\n\n// src/ui/OverlayRenderer.tsx\nvar import_jsx_runtime = require(\"react/jsx-runtime\");\nfunction computeVideoDimensions(video) {\n const nativeWidth = video.videoWidth;\n const nativeHeight = video.videoHeight;\n if (!nativeWidth || !nativeHeight) return null;\n const displayWidth = video.offsetWidth;\n const displayHeight = video.offsetHeight;\n if (!displayWidth || !displayHeight) return null;\n const videoAspect = nativeWidth / nativeHeight;\n const displayAspect = displayWidth / displayHeight;\n let renderWidth;\n let renderHeight;\n let offsetX;\n let offsetY;\n if (videoAspect > displayAspect) {\n renderWidth = displayWidth;\n renderHeight = displayWidth / videoAspect;\n offsetX = 0;\n offsetY = (displayHeight - renderHeight) / 2;\n } else {\n renderHeight = displayHeight;\n renderWidth = displayHeight * videoAspect;\n offsetX = (displayWidth - renderWidth) / 2;\n offsetY = 0;\n }\n return {\n nativeWidth,\n nativeHeight,\n displayWidth: renderWidth,\n displayHeight: renderHeight,\n offsetX,\n offsetY,\n scaleX: renderWidth / nativeWidth,\n scaleY: renderHeight / nativeHeight\n };\n}\nfunction ImageOverlay({ overlay }) {\n const src = resolveImageUrl(overlay.image_url || \"\");\n if (!src) return null;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"img\",\n {\n src,\n alt: overlay.name,\n draggable: false,\n style: {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"contain\",\n display: \"block\",\n pointerEvents: \"none\",\n userSelect: \"none\"\n }\n }\n );\n}\nfunction TextOverlay({ overlay }) {\n const text = overlay.content || \"\";\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n fontSize: \"clamp(10px, 1.4vw, 20px)\",\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n fontWeight: 600,\n textAlign: \"center\",\n padding: \"4px 8px\",\n boxSizing: \"border-box\",\n wordBreak: \"break-word\",\n textShadow: \"0 1px 4px rgba(0,0,0,0.7)\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n lineHeight: 1.3\n },\n children: text\n }\n );\n}\nfunction parseRSSXml(xmlText, maxItems) {\n const stripped = xmlText.replace(/^<\\?xml[^?]*\\?>\\s*/, \"\");\n const parser = new DOMParser();\n const doc = parser.parseFromString(stripped, \"text/xml\");\n const items = Array.from(doc.querySelectorAll(\"item\")).map((item) => ({\n title: (item.querySelector(\"title\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n description: (item.querySelector(\"description\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n pubDate: item.querySelector(\"pubDate\")?.textContent || \"\",\n author: item.querySelector(\"author, dc\\\\:creator\")?.textContent || \"\",\n category: item.querySelector(\"category\")?.textContent || \"\"\n })).filter((i) => i.title).slice(0, maxItems);\n if (items.length === 0 && doc.querySelector(\"parsererror\")) {\n throw new Error(\"Invalid RSS XML\");\n }\n return items;\n}\nvar RSS_CACHE_TTL_MS = 6e4;\nvar rssCache = /* @__PURE__ */ new Map();\nfunction cachedFetchRSSItems(rssUrl, maxItems) {\n const now = Date.now();\n const cached = rssCache.get(rssUrl);\n if (cached && cached.expiresAt > now) return cached.promise;\n const promise = fetchRSSItems(rssUrl, maxItems).catch((err) => {\n rssCache.delete(rssUrl);\n throw err;\n });\n rssCache.set(rssUrl, { promise, expiresAt: now + RSS_CACHE_TTL_MS });\n return promise;\n}\nasync function fetchRSSItems(rssUrl, maxItems) {\n const encoded = encodeURIComponent(rssUrl);\n try {\n const origin = typeof window !== \"undefined\" ? window.location.origin : \"\";\n const resp = await fetch(`${origin}/api/rss-proxy?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text.includes(\"<item\")) return parseRSSXml(text, maxItems);\n }\n } catch {\n }\n try {\n const resp = await fetch(`https://api.allorigins.win/get?url=${encoded}`);\n if (resp.ok) {\n const data = await resp.json();\n if (data.contents) return parseRSSXml(data.contents, maxItems);\n }\n } catch {\n }\n try {\n const resp = await fetch(`https://corsproxy.io/?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text) return parseRSSXml(text, maxItems);\n }\n } catch {\n }\n throw new Error(\"All RSS proxies failed\");\n}\nfunction ScrollerOverlay({ overlay }) {\n const cfg = overlay.scroller_config;\n const uid = (0, import_react.useId)().replace(/:/g, \"\");\n const [rssItems, setRssItems] = (0, import_react.useState)([]);\n const [rssLoading, setRssLoading] = (0, import_react.useState)(true);\n const [rssError, setRssError] = (0, import_react.useState)(false);\n const rssUrl = cfg?.rss_url || \"\";\n const maxItems = cfg?.max_items ?? 10;\n const autoRefresh = cfg?.auto_refresh !== false;\n const updateInterval = cfg?.update_interval ?? 5;\n (0, import_react.useEffect)(() => {\n if (!rssUrl || cfg?.use_custom_text && cfg?.custom_text) {\n setRssLoading(false);\n return;\n }\n let cancelled = false;\n setRssLoading(true);\n setRssError(false);\n cachedFetchRSSItems(rssUrl, maxItems).then((items) => {\n if (!cancelled) {\n setRssItems(items);\n setRssError(false);\n }\n }).catch(() => {\n if (!cancelled) setRssError(true);\n }).finally(() => {\n if (!cancelled) setRssLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [rssUrl, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n (0, import_react.useEffect)(() => {\n if (!rssUrl || !autoRefresh || cfg?.use_custom_text && cfg?.custom_text) return;\n const interval = setInterval(() => {\n rssCache.delete(rssUrl);\n cachedFetchRSSItems(rssUrl, maxItems).then((items) => {\n setRssItems(items);\n setRssError(false);\n }).catch(() => {\n });\n }, updateInterval * 60 * 1e3);\n return () => clearInterval(interval);\n }, [rssUrl, autoRefresh, updateInterval, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n const sep = cfg?.separator_char ?? \"\\u25C6\";\n let segments;\n if (cfg?.use_custom_text && cfg?.custom_text) {\n segments = [cfg.custom_text];\n } else if (rssItems.length > 0) {\n segments = rssItems.map((item) => {\n const parts = [];\n if (cfg?.show_title !== false && item.title) parts.push(item.title);\n if (cfg?.show_description && item.description) parts.push(item.description);\n if (cfg?.show_timestamp && item.pubDate) {\n try {\n parts.push(new Date(item.pubDate).toLocaleDateString());\n } catch {\n }\n }\n if (cfg?.show_author && item.author) parts.push(`\\u2014 ${item.author}`);\n if (cfg?.show_category && item.category) parts.push(`[${item.category}]`);\n return parts.join(\" \");\n });\n } else if (rssLoading) {\n segments = [\"Loading feed\\u2026\"];\n } else if (rssError) {\n segments = overlay.content ? [overlay.content] : [\"RSS feed unavailable\"];\n } else if (overlay.content) {\n segments = [overlay.content];\n } else {\n segments = rssUrl ? [\"Loading feed\\u2026\"] : [\"RSS Ticker\"];\n }\n const scrollSpeed = cfg?.scroll_speed ?? 40;\n const direction = cfg?.direction ?? \"left\";\n const fontSize = cfg?.font_size ?? 15;\n const fontFamily = cfg?.font_family || \"Roboto, 'Segoe UI', Arial, sans-serif\";\n const fontWeight = cfg?.font_weight || \"700\";\n const textColor = cfg?.text_color || \"#ffffff\";\n const bgColor = cfg?.background_color || \"#0d0d1a\";\n const bgOpacity = cfg?.background_opacity !== void 0 ? cfg.background_opacity / 100 : 0.95;\n const borderRadius = cfg?.border_radius ?? 0;\n const itemSpacing = cfg?.item_spacing ?? 60;\n const pad = cfg?.padding !== void 0 && cfg.padding >= 0 ? cfg.padding : 8;\n const label = cfg?.label ?? \"NEWS\";\n const labelLine2 = cfg?.label_line2 ?? \"\";\n const labelColor = cfg?.label_color ?? \"#f97316\";\n const labelTextColor = cfg?.label_text_color ?? \"#ffffff\";\n const accentColor = cfg?.accent_color ?? labelColor;\n const showAccentLine = cfg?.show_accent_line !== false;\n const isEquitiesStrip = cfg?.preset === \"equities_strip\";\n const isHorizontal = direction === \"left\" || direction === \"right\";\n const isReverse = direction === \"right\" || direction === \"down\";\n const fullText = segments.join(` ${sep} `);\n const durationSec = Math.max(6, fullText.length * 9 / scrollSpeed);\n const animId = `sc-ticker-${overlay.id}-${uid}`;\n const keyframes = isHorizontal ? `@keyframes ${animId} {\n ${isReverse ? \"0% { transform: translateX(-50%); } 100% { transform: translateX(0%); }\" : \"0% { transform: translateX(0); } 100% { transform: translateX(-50%); }\"}\n }` : `@keyframes ${animId} {\n ${isReverse ? \"0% { transform: translateY(-50%); } 100% { transform: translateY(0%); }\" : \"0% { transform: translateY(0); } 100% { transform: translateY(-50%); }\"}\n }`;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: keyframes }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n borderRadius: borderRadius > 0 ? `${borderRadius}px` : void 0,\n backgroundColor: `rgba(${hexToRgb(bgColor)}, ${bgOpacity})`,\n fontFamily,\n fontSize: `${fontSize}px`,\n fontWeight,\n color: textColor,\n pointerEvents: \"none\",\n userSelect: \"none\"\n },\n children: [\n showAccentLine && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n height: isEquitiesStrip ? 2 : 3,\n background: accentColor,\n flexShrink: 0,\n width: \"100%\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n flex: 1,\n overflow: \"hidden\",\n minHeight: 0,\n alignItems: \"center\",\n padding: isEquitiesStrip ? `${Math.max(2, pad * 0.5)}px ${pad}px` : `${Math.max(4, pad * 0.75)}px ${pad}px`,\n gap: isEquitiesStrip ? Math.max(4, Math.round(pad * 0.75)) : Math.max(6, pad),\n boxSizing: \"border-box\"\n },\n children: [\n label && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n background: labelColor,\n color: labelTextColor,\n padding: isEquitiesStrip ? \"6px 12px\" : \"10px 14px\",\n display: \"flex\",\n flexDirection: isEquitiesStrip ? \"row\" : \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n textAlign: \"center\",\n gap: isEquitiesStrip ? 0 : 2,\n borderRadius: Math.max(2, borderRadius > 0 ? borderRadius : 6),\n boxShadow: isEquitiesStrip ? \"inset 0 1px 0 rgba(255,255,255,0.08)\" : \"0 2px 8px rgba(0,0,0,0.35)\",\n alignSelf: \"stretch\",\n maxWidth: isEquitiesStrip ? \"min(200px, 28%)\" : void 0\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"span\",\n {\n style: {\n fontWeight: isEquitiesStrip ? 700 : 800,\n fontSize: isEquitiesStrip ? \"0.82em\" : \"0.78em\",\n letterSpacing: isEquitiesStrip ? \"0.04em\" : \"0.08em\",\n lineHeight: 1.2,\n textTransform: isEquitiesStrip ? \"none\" : \"uppercase\",\n whiteSpace: isEquitiesStrip ? \"normal\" : \"nowrap\",\n textAlign: isEquitiesStrip ? \"left\" : \"center\"\n },\n children: label\n }\n ),\n labelLine2 && !isEquitiesStrip && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"span\",\n {\n style: {\n fontWeight: 600,\n fontSize: \"0.58em\",\n letterSpacing: \"0.06em\",\n lineHeight: 1.15,\n opacity: 0.92,\n whiteSpace: \"nowrap\"\n },\n children: labelLine2\n }\n )\n ]\n }\n ),\n label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: isEquitiesStrip ? 1 : 2,\n alignSelf: \"stretch\",\n minHeight: isEquitiesStrip ? 20 : 24,\n background: accentColor,\n flexShrink: 0,\n borderRadius: 1,\n opacity: 0.85\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n flex: 1,\n overflow: \"hidden\",\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n minWidth: 0\n },\n children: isHorizontal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n display: \"inline-flex\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\"\n },\n children: [0, 1].map((copy) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { paddingRight: `${itemSpacing}px` }, children: segments.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [\n i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { opacity: 0.5, margin: \"0 8px\" }, children: sep }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { textShadow: \"0 1px 3px rgba(0,0,0,0.6)\" }, children: seg })\n ] }, i)) }, copy))\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\"\n },\n children: [0, 1].map(\n (copy) => segments.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { paddingBottom: `${itemSpacing / 4}px` }, children: seg }, `${copy}-${i}`))\n )\n }\n )\n }\n )\n ]\n }\n )\n ]\n }\n )\n ] });\n}\nfunction parseConfig(content) {\n if (!content) return null;\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\nfunction parseClockMMSS(clock) {\n if (!clock) return null;\n const m = /^\\s*(\\d{1,3}):([0-5]?\\d)\\s*$/.exec(clock);\n if (!m) return null;\n return parseInt(m[1], 10) * 60 + parseInt(m[2], 10);\n}\nfunction formatClockMMSS(totalSec) {\n const s = Math.max(0, Math.floor(totalSec));\n const mm = Math.floor(s / 60);\n const ss = s % 60;\n return `${mm}:${ss.toString().padStart(2, \"0\")}`;\n}\nfunction useScoreBugClock(overlayId, sourceClock) {\n const initialSec = parseClockMMSS(sourceClock);\n const [now, setNow] = (0, import_react.useState)(() => Date.now());\n const startRef = (0, import_react.useRef)(null);\n (0, import_react.useEffect)(() => {\n if (initialSec === null) {\n startRef.current = null;\n return;\n }\n startRef.current = {\n id: overlayId,\n source: sourceClock || \"\",\n at: Date.now(),\n seconds: initialSec\n };\n setNow(Date.now());\n const tick = window.setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(tick);\n }, [overlayId, sourceClock, initialSec]);\n if (initialSec === null || !startRef.current) return null;\n const elapsed = Math.floor((now - startRef.current.at) / 1e3);\n const remaining = Math.max(0, startRef.current.seconds - elapsed);\n return formatClockMMSS(remaining);\n}\nfunction ScoreBugOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n const liveClock = useScoreBugClock(overlay.id, cfg?.clock);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n const displayClock = liveClock ?? cfg.clock ?? \"\";\n const displayPeriod = cfg.period ?? \"\";\n const showMiddleCol = Boolean(displayPeriod || displayClock);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.028),\n display: \"flex\",\n flexDirection: \"column\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 8px 28px rgba(0,0,0,0.45)\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n padding: `${f * 0.42}px ${f * 0.85}px`,\n gap: f * 0.45,\n minHeight: 0\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n },\n children: cfg.homeTeam\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }, children: cfg.homeScore })\n ] }),\n showMiddleCol && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"0.88em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.92,\n color: cfg.textColor,\n padding: `0 ${f * 0.5}px`,\n flexShrink: 0,\n lineHeight: 1.25,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\"\n },\n children: [\n displayPeriod && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { children: displayPeriod }),\n displayClock && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontWeight: 700, opacity: 1 }, children: displayClock })\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n },\n children: cfg.awayTeam\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }, children: cfg.awayScore })\n ] })\n ]\n }\n ),\n (cfg.sponsorText || cfg.sponsorImageUrl) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"0.72em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.88,\n padding: `${f * 0.34}px ${f * 0.55}px`,\n borderTop: `1px solid ${cfg.accentColor}55`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: f * 0.45,\n overflow: \"hidden\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n background: `linear-gradient(180deg, rgba(0,0,0,0.12) 0%, rgba(0,0,0,0.22) 100%)`\n },\n children: [\n cfg.sponsorImageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"img\", { src: cfg.sponsorImageUrl, alt: \"sponsor\", style: { height: `${f * 1.35}px`, objectFit: \"contain\", flexShrink: 0 } }),\n cfg.sponsorText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.sponsorText })\n ]\n }\n )\n ]\n }\n );\n}\nfunction LowerThirdOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.05);\n const accentH = Math.max(3, size.h * 0.038);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.018),\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"flex-end\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 10px 32px rgba(0,0,0,0.4)\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { width: \"100%\", height: accentH, backgroundColor: cfg.accentColor, flexShrink: 0 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: `${f * 0.62}px ${f * 1.05}px`,\n minHeight: 0,\n gap: f * 0.18\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"1.28em\",\n fontWeight: 800,\n lineHeight: 1.22,\n letterSpacing: \"0.01em\",\n textShadow: \"0 2px 6px rgba(0,0,0,0.55)\"\n },\n children: cfg.headline\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"0.94em\",\n fontWeight: 500,\n opacity: 0.92,\n lineHeight: 1.35,\n color: cfg.textColor\n },\n children: cfg.subtitle\n }\n )\n ]\n }\n ),\n (cfg.sponsorText || cfg.sponsorImageUrl) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"0.68em\",\n fontWeight: 600,\n opacity: 0.72,\n padding: `${f * 0.28}px ${f * 1.05}px ${f * 0.48}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: f * 0.4,\n overflow: \"hidden\",\n letterSpacing: \"0.06em\",\n textTransform: \"uppercase\",\n borderTop: `1px solid rgba(255,255,255,0.08)`\n },\n children: [\n cfg.sponsorImageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"img\", { src: cfg.sponsorImageUrl, alt: \"sponsor\", style: { height: `${f * 1.25}px`, objectFit: \"contain\", flexShrink: 0 } }),\n cfg.sponsorText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.sponsorText })\n ]\n }\n )\n ]\n }\n );\n}\nfunction QrCodeOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const qrSide = Math.max(32, Math.min(size.w, size.h) * 0.55);\n const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=${Math.round(qrSide * 2)}x${Math.round(qrSide * 2)}&data=${encodeURIComponent(cfg.url || \"https://example.com\")}`;\n const f = Math.max(6, size.w * 0.06);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", gap: f * 0.4, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", padding: f * 0.6, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", overflow: \"hidden\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { flexShrink: 0, background: \"#fff\", borderRadius: Math.max(2, qrSide * 0.06), padding: Math.max(2, qrSide * 0.06), lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"img\", { src: qrUrl, alt: \"QR Code\", style: { width: `${qrSide}px`, height: `${qrSide}px`, display: \"block\" } }) }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: `${f * 1.1}px`, fontWeight: 700, textAlign: \"center\", color: cfg.accentColor, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }, children: cfg.ctaText }),\n cfg.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: `${f * 0.75}px`, opacity: 0.6, textAlign: \"center\", overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }, children: cfg.description })\n ] });\n}\nfunction ComingUpNextOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const f = Math.max(8, Math.min(size.h * 0.13, size.w * 0.048));\n const showSubtitle = size.h >= 60;\n const showThumbnail = false;\n const thumbW = 0;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: {\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.025),\n display: \"flex\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Arial', 'Helvetica Neue', Helvetica, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n WebkitFontSmoothing: \"antialiased\"\n }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { width: Math.max(3, size.w * 0.018), flexShrink: 0, backgroundColor: cfg.accentColor } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: {\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: `${f * 0.35}px ${f * 0.75}px`,\n minWidth: 0,\n gap: `${f * 0.08}px`\n }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"0.7em\",\n fontWeight: 700,\n textTransform: \"uppercase\",\n letterSpacing: \"0.09em\",\n color: cfg.accentColor,\n lineHeight: 1\n }, children: \"Coming Up Next\" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"1.2em\",\n fontWeight: 700,\n lineHeight: 1.2,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n }, children: cfg.title }),\n showSubtitle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"0.82em\",\n opacity: 0.65,\n lineHeight: 1.1,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n }, children: cfg.subtitle }),\n cfg.scheduledTime && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"0.9em\",\n fontWeight: 700,\n color: cfg.accentColor,\n lineHeight: 1\n }, children: cfg.scheduledTime })\n ] }),\n showThumbnail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { flexShrink: 0, width: `${thumbW}px`, overflow: \"hidden\" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"img\",\n {\n src: cfg.thumbnailUrl,\n alt: \"\",\n style: { width: \"100%\", height: \"100%\", objectFit: \"cover\", display: \"block\" }\n }\n ) })\n ] });\n}\nfunction ContextualTriggerOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const icons = { alert: \"\\u26A0\\uFE0F\", celebration: \"\\u{1F389}\", info: \"\\u2139\\uFE0F\", warning: \"\\u{1F514}\" };\n const f = Math.max(6, size.w * 0.05);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", alignItems: \"center\", gap: f * 0.8, padding: `0 ${f * 1.2}px`, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", borderLeft: `${Math.max(2, size.w * 0.02)}px solid ${cfg.accentColor}`, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { fontSize: \"2em\", flexShrink: 0 }, children: icons[cfg.iconType] || \"\\u26A1\" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, minWidth: 0 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.headline }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.message })\n ] })\n ] });\n}\nfunction OddsBettingOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.9em\", fontWeight: 700, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }, children: cfg.eventTitle }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { flex: 1, display: \"flex\", flexDirection: \"column\", gap: f * 0.2, justifyContent: \"center\" }, children: (cfg.options || []).slice(0, 5).map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", padding: `${f * 0.2}px ${f * 0.6}px`, borderRadius: Math.max(2, f * 0.3), background: `${cfg.accentColor}15`, fontSize: \"1em\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", flex: 1 }, children: opt.label }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { fontWeight: 700, marginLeft: f * 0.8, flexShrink: 0, color: cfg.accentColor }, children: opt.odds })\n ] }, i)) }),\n cfg.sponsorText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.7em\", opacity: 0.4, textAlign: \"center\", marginTop: f * 0.4 }, children: cfg.sponsorText })\n ] });\n}\nfunction BreakingNewsOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const urgencyColors = { breaking: \"#dc2626\", urgent: \"#ea580c\", normal: \"#2563eb\" };\n const labelBg = urgencyColors[cfg.urgency] || urgencyColors.normal;\n const label = cfg.urgency === \"breaking\" ? \"BREAKING\" : cfg.urgency === \"urgent\" ? \"URGENT\" : \"NEWS\";\n const f = Math.max(6, size.w * 0.05);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.02), display: \"flex\", alignItems: \"center\", background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", overflow: \"hidden\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { padding: `0 ${f * 0.8}px`, height: \"100%\", display: \"flex\", alignItems: \"center\", background: labelBg, color: \"#fff\", fontSize: \"1em\", fontWeight: 900, textTransform: \"uppercase\", letterSpacing: \"0.05em\", flexShrink: 0 }, children: label }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, padding: `0 ${f * 1}px`, minWidth: 0 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.headline }),\n cfg.body && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.body })\n ] })\n ] });\n}\nfunction calcCountdownRemaining(targetTime) {\n const diff = Math.max(0, new Date(targetTime).getTime() - Date.now());\n return {\n d: Math.floor(diff / 864e5),\n h: Math.floor(diff % 864e5 / 36e5),\n m: Math.floor(diff % 36e5 / 6e4),\n s: Math.floor(diff % 6e4 / 1e3),\n expired: diff === 0\n };\n}\nfunction CountdownOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n const targetTime = cfg?.targetTime ?? \"\";\n const [remaining, setRemaining] = (0, import_react.useState)(\n () => targetTime ? calcCountdownRemaining(targetTime) : { d: 0, h: 0, m: 0, s: 0, expired: false }\n );\n (0, import_react.useEffect)(() => {\n if (!targetTime) return;\n setRemaining(calcCountdownRemaining(targetTime));\n const id = setInterval(() => setRemaining(calcCountdownRemaining(targetTime)), 1e3);\n return () => clearInterval(id);\n }, [targetTime]);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.055);\n const pad = (n) => String(n).padStart(2, \"0\");\n const units = [\n { show: cfg.showDays, value: pad(remaining.d), label: \"DAYS\" },\n { show: cfg.showHours, value: pad(remaining.h), label: \"HRS\" },\n { show: cfg.showMinutes, value: pad(remaining.m), label: \"MIN\" },\n { show: cfg.showSeconds, value: pad(remaining.s), label: \"SEC\" }\n ];\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.8em\", fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }, children: cfg.eventName }),\n remaining.expired ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1em\", fontWeight: 700, opacity: 0.6 }, children: cfg.message || \"Event ended\" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { display: \"flex\", gap: f * 0.6, alignItems: \"center\" }, children: units.filter((u) => u.show).map((u, i, arr) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { textAlign: \"center\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"2em\", fontWeight: 900, lineHeight: 1, borderRadius: Math.max(2, f * 0.4), padding: `${f * 0.2}px ${f * 0.4}px`, background: `${cfg.accentColor}20` }, children: u.value }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.5em\", opacity: 0.5, marginTop: f * 0.2 }, children: u.label })\n ] }),\n i < arr.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.8em\", fontWeight: 700, opacity: 0.3 }, children: \":\" })\n ] }, u.label)) }),\n !remaining.expired && cfg.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.8em\", opacity: 0.6, marginTop: f * 0.4, textAlign: \"center\" }, children: cfg.message })\n ] });\n}\nfunction ShapeOverlay({ overlay, size }) {\n const f = Math.max(6, size.w * 0.05);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.03), background: \"rgba(99, 102, 241, 0.2)\", border: \"2px solid rgba(99, 102, 241, 0.4)\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\", pointerEvents: \"none\", userSelect: \"none\" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: `${f}px`, fontWeight: 500, color: \"rgba(163, 163, 163, 0.8)\", textTransform: \"uppercase\" }, children: overlay.name }) });\n}\nfunction hexToRgb(hex) {\n if (!hex || !hex.startsWith(\"#\")) return \"0,0,0\";\n const clean = hex.slice(1);\n const num = parseInt(clean.length === 3 ? clean.replace(/./g, \"$&$&\") : clean, 16);\n return `${num >> 16 & 255},${num >> 8 & 255},${num & 255}`;\n}\nvar FADE_DURATION_MS = 1e3;\nvar VALID_ENTER_ANIMATIONS = /* @__PURE__ */ new Set([\n \"fade\",\n \"slide_left\",\n \"slide_right\",\n \"slide_up\",\n \"slide_down\"\n]);\nfunction getEnterAnimation(overlay) {\n const flat = overlay.enter_animation;\n if (typeof flat === \"string\" && VALID_ENTER_ANIMATIONS.has(flat)) {\n return flat;\n }\n if (overlay.content) {\n try {\n const parsed = JSON.parse(overlay.content);\n const v = parsed?.enterAnimation;\n if (typeof v === \"string\" && VALID_ENTER_ANIMATIONS.has(v)) {\n return v;\n }\n } catch {\n }\n }\n return \"fade\";\n}\nfunction enterHiddenTransform(anim) {\n switch (anim) {\n case \"slide_left\":\n return \"translateX(-120%)\";\n case \"slide_right\":\n return \"translateX(120%)\";\n case \"slide_up\":\n return \"translateY(-120%)\";\n case \"slide_down\":\n return \"translateY(120%)\";\n default:\n return \"\";\n }\n}\nvar SHOWCASE_CYCLE_MS_DEFAULT = 36e3;\nvar SHOWCASE_MIN_BEAT_MS = 6e3;\nvar BEAT_POP_IN_MS = 520;\nvar BEAT_POP_OUT_MS = 520;\nvar SHOWCASE_PERSISTENT_TYPES = /* @__PURE__ */ new Set([\n \"scroller\",\n \"breaking_news\",\n \"image\",\n \"text\",\n \"shape\",\n \"countdown\",\n \"qr_code\",\n \"coming_up_next\",\n \"score_bug\"\n]);\nfunction easeOutCubic(t) {\n const u = 1 - t;\n return 1 - u * u * u;\n}\nfunction easeInCubic(t) {\n return t * t * t;\n}\nfunction easeOutBack(t) {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n return 1 + c3 * (t - 1) ** 3 + c1 * (t - 1) ** 2;\n}\nfunction beatOpacity(phase, beatMs) {\n if (phase < BEAT_POP_IN_MS) return easeOutCubic(phase / BEAT_POP_IN_MS);\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return Math.max(\n 0,\n 1 - easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS)\n );\n }\n return 1;\n}\nfunction beatScale(phase, beatMs) {\n if (phase < BEAT_POP_IN_MS) {\n return Math.min(1, 0.92 + 0.08 * easeOutBack(phase / BEAT_POP_IN_MS));\n }\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return 1 - 0.06 * easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS);\n }\n return 1;\n}\nfunction partitionShowcase(overlays) {\n const visible = overlays.filter((o) => o.visible);\n const persistent = [];\n const spotlight = [];\n for (const o of visible) {\n if (SHOWCASE_PERSISTENT_TYPES.has(o.type)) persistent.push(o);\n else spotlight.push(o);\n }\n spotlight.sort(\n (a, b) => a.z_index - b.z_index || a.id - b.id\n );\n const beats = [];\n for (const o of spotlight) beats.push([o]);\n return { persistent, beats };\n}\nfunction useShowcaseBeat(enabled, cycleMs, beats) {\n const safeBeats = Math.max(1, beats);\n const beatMs = Math.max(\n SHOWCASE_MIN_BEAT_MS,\n Math.floor(cycleMs / safeBeats)\n );\n const totalMs = beatMs * safeBeats;\n const [now, setNow] = (0, import_react.useState)(() => Date.now());\n (0, import_react.useEffect)(() => {\n if (!enabled) return;\n const id = window.setInterval(() => setNow(Date.now()), 64);\n return () => clearInterval(id);\n }, [enabled]);\n const phase = now % totalMs;\n const beatIndex = Math.min(safeBeats - 1, Math.floor(phase / beatMs));\n const beatPhase = phase - beatIndex * beatMs;\n return { beatIndex, beatPhase, beatMs };\n}\nvar OverlayRenderer = ({\n overlays,\n currentTime,\n videoRef,\n coordinateSpace,\n showcaseMode = false,\n showcaseCycleMs = SHOWCASE_CYCLE_MS_DEFAULT\n}) => {\n const [dims, setDims] = (0, import_react.useState)(null);\n const rafRef = (0, import_react.useRef)(null);\n const [fadeMap, setFadeMap] = (0, import_react.useState)(/* @__PURE__ */ new Map());\n const removeTimers = (0, import_react.useRef)(/* @__PURE__ */ new Map());\n const mountTimeRef = (0, import_react.useRef)(Date.now());\n const [wallclockSec, setWallclockSec] = (0, import_react.useState)(0);\n (0, import_react.useEffect)(() => {\n if (!showcaseMode) return;\n const tick = () => setWallclockSec((Date.now() - mountTimeRef.current) / 1e3);\n tick();\n const id = window.setInterval(tick, 200);\n return () => clearInterval(id);\n }, [showcaseMode]);\n const { persistent: showcasePersistent, beats: showcaseBeats } = (0, import_react.useMemo)(\n () => partitionShowcase(overlays),\n [overlays]\n );\n const {\n beatIndex: showcaseBeatIndex,\n beatPhase: showcaseBeatPhase,\n beatMs: showcaseBeatMs\n } = useShowcaseBeat(showcaseMode, showcaseCycleMs, showcaseBeats.length);\n const showcasePersistentIds = (0, import_react.useMemo)(\n () => new Set(showcasePersistent.map((o) => o.id)),\n [showcasePersistent]\n );\n const showcaseSpotlightIds = (0, import_react.useMemo)(() => {\n const beat = showcaseBeats[showcaseBeatIndex];\n return new Set((beat ?? []).map((o) => o.id));\n }, [showcaseBeats, showcaseBeatIndex]);\n const updateDims = (0, import_react.useCallback)(() => {\n const video = videoRef.current;\n if (video) {\n const computed = computeVideoDimensions(video);\n setDims((prev) => {\n if (!computed || prev && prev.nativeWidth === computed.nativeWidth && prev.nativeHeight === computed.nativeHeight && prev.displayWidth === computed.displayWidth && prev.displayHeight === computed.displayHeight && prev.offsetX === computed.offsetX && prev.offsetY === computed.offsetY) {\n return prev;\n }\n return computed;\n });\n }\n }, [videoRef]);\n (0, import_react.useEffect)(() => {\n updateDims();\n const interval = setInterval(updateDims, 500);\n const handleResize = () => {\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(updateDims);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => {\n clearInterval(interval);\n window.removeEventListener(\"resize\", handleResize);\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n };\n }, [updateDims]);\n const activeOverlays = (0, import_react.useMemo)(() => {\n if (showcaseMode) {\n const beat = showcaseBeats[showcaseBeatIndex] ?? [];\n const scheduledPersistent = showcasePersistent.filter(\n (o) => isOverlayActive(o, wallclockSec)\n );\n return [...scheduledPersistent, ...beat];\n }\n return overlays.filter((o) => isOverlayActive(o, currentTime));\n }, [\n overlays,\n currentTime,\n wallclockSec,\n showcaseMode,\n showcasePersistent,\n showcaseBeats,\n showcaseBeatIndex\n ]);\n (0, import_react.useLayoutEffect)(() => {\n const activeIds = new Set(activeOverlays.map((o) => o.id));\n setFadeMap((prev) => {\n const next = new Map(prev);\n for (const overlay of activeOverlays) {\n if (!next.has(overlay.id)) {\n next.set(overlay.id, { overlay, visible: false });\n } else {\n const existing = next.get(overlay.id);\n next.set(overlay.id, { ...existing, overlay });\n }\n }\n for (const [id, state] of next) {\n if (!activeIds.has(id) && state.visible) {\n next.set(id, { ...state, visible: false });\n if (!removeTimers.current.has(id)) {\n const timer = setTimeout(() => {\n setFadeMap((m) => {\n const updated = new Map(m);\n updated.delete(id);\n return updated;\n });\n removeTimers.current.delete(id);\n }, FADE_DURATION_MS);\n removeTimers.current.set(id, timer);\n }\n } else if (!activeIds.has(id) && !state.visible) {\n }\n }\n return next;\n });\n }, [activeOverlays]);\n (0, import_react.useEffect)(() => {\n const toFadeIn = [];\n for (const [id, state] of fadeMap) {\n if (!state.visible) {\n const isActive = activeOverlays.some((o) => o.id === id);\n if (isActive) toFadeIn.push(id);\n }\n }\n if (toFadeIn.length === 0) return;\n const raf = requestAnimationFrame(() => {\n setFadeMap((prev) => {\n const next = new Map(prev);\n for (const id of toFadeIn) {\n const state = next.get(id);\n if (state) next.set(id, { ...state, visible: true });\n }\n return next;\n });\n });\n return () => cancelAnimationFrame(raf);\n }, [fadeMap, activeOverlays]);\n (0, import_react.useEffect)(() => {\n return () => {\n for (const timer of removeTimers.current.values()) clearTimeout(timer);\n };\n }, []);\n if (!dims || fadeMap.size === 0) return null;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n \"aria-hidden\": \"true\",\n style: {\n position: \"absolute\",\n left: `${dims.offsetX}px`,\n top: `${dims.offsetY}px`,\n width: `${dims.displayWidth}px`,\n height: `${dims.displayHeight}px`,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n zIndex: 8\n },\n children: [...fadeMap.values()].map(({ overlay, visible }) => {\n const scaleX = coordinateSpace?.width ? dims.displayWidth / coordinateSpace.width : dims.scaleX;\n const scaleY = coordinateSpace?.height ? dims.displayHeight / coordinateSpace.height : dims.scaleY;\n const left = overlay.x * scaleX;\n const top = overlay.y * scaleY;\n const width = overlay.width * scaleX;\n const height = overlay.height * scaleY;\n const baseOpacity = Math.max(0, Math.min(100, overlay.opacity)) / 100;\n const isShowcasePersistent = showcaseMode && showcasePersistentIds.has(overlay.id);\n const isShowcaseSpotlight = showcaseMode && showcaseSpotlightIds.has(overlay.id);\n const isShowcaseDormant = showcaseMode && !isShowcasePersistent && !isShowcaseSpotlight;\n const useShowcasePop = isShowcaseSpotlight;\n const opacity = useShowcasePop ? baseOpacity * beatOpacity(showcaseBeatPhase, showcaseBeatMs) : isShowcaseDormant ? 0 : visible ? baseOpacity : 0;\n const popScale = useShowcasePop ? beatScale(showcaseBeatPhase, showcaseBeatMs) : 1;\n const sz = { w: width, h: height };\n const enterAnim = getEnterAnimation(overlay);\n const hasSlide = enterAnim !== \"fade\" && !useShowcasePop;\n const slideTransform = hasSlide && !visible ? enterHiddenTransform(enterAnim) : \"\";\n const popTransform = showcaseMode && useShowcasePop ? `scale(${popScale})` : \"\";\n const combinedTransform = [slideTransform, popTransform].filter(Boolean).join(\" \");\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n opacity,\n transition: useShowcasePop ? \"none\" : hasSlide ? `opacity ${FADE_DURATION_MS}ms ease, transform ${FADE_DURATION_MS}ms cubic-bezier(0.22, 1, 0.36, 1)` : `opacity ${FADE_DURATION_MS}ms ease`,\n transform: combinedTransform || void 0,\n transformOrigin: showcaseMode && useShowcasePop ? \"center center\" : void 0,\n zIndex: overlay.z_index,\n overflow: \"hidden\"\n },\n children: [\n overlay.type === \"image\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageOverlay, { overlay }),\n overlay.type === \"text\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextOverlay, { overlay }),\n overlay.type === \"scroller\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollerOverlay, { overlay }),\n overlay.type === \"shape\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShapeOverlay, { overlay, size: sz }),\n overlay.type === \"score_bug\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScoreBugOverlay, { overlay, size: sz }),\n overlay.type === \"lower_third\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LowerThirdOverlay, { overlay, size: sz }),\n overlay.type === \"qr_code\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(QrCodeOverlay, { overlay, size: sz }),\n overlay.type === \"coming_up_next\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComingUpNextOverlay, { overlay, size: sz }),\n overlay.type === \"contextual_trigger\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextualTriggerOverlay, { overlay, size: sz }),\n overlay.type === \"odds_betting\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OddsBettingOverlay, { overlay, size: sz }),\n overlay.type === \"breaking_news\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BreakingNewsOverlay, { overlay, size: sz }),\n overlay.type === \"countdown\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CountdownOverlay, { overlay, size: sz })\n ]\n },\n overlay.id\n );\n })\n }\n );\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n OverlayRenderer\n});\n","import React, {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useCallback,\n useMemo,\n useId,\n} from \"react\";\nimport {\n type SwirlOverlay,\n isOverlayActive,\n resolveImageUrl,\n} from \"../utils/overlays\";\n\ninterface VideoDimensions {\n nativeWidth: number;\n nativeHeight: number;\n displayWidth: number;\n displayHeight: number;\n offsetX: number;\n offsetY: number;\n scaleX: number;\n scaleY: number;\n}\n\ninterface OverlayRendererProps {\n overlays: SwirlOverlay[];\n currentTime: number;\n videoRef: React.RefObject<HTMLVideoElement | null>;\n coordinateSpace?: { width: number; height: number } | null;\n showcaseMode?: boolean;\n showcaseCycleMs?: number;\n}\n\nfunction computeVideoDimensions(\n video: HTMLVideoElement\n): VideoDimensions | null {\n const nativeWidth = video.videoWidth;\n const nativeHeight = video.videoHeight;\n if (!nativeWidth || !nativeHeight) return null;\n\n const displayWidth = video.offsetWidth;\n const displayHeight = video.offsetHeight;\n if (!displayWidth || !displayHeight) return null;\n\n const videoAspect = nativeWidth / nativeHeight;\n const displayAspect = displayWidth / displayHeight;\n\n let renderWidth: number;\n let renderHeight: number;\n let offsetX: number;\n let offsetY: number;\n\n if (videoAspect > displayAspect) {\n renderWidth = displayWidth;\n renderHeight = displayWidth / videoAspect;\n offsetX = 0;\n offsetY = (displayHeight - renderHeight) / 2;\n } else {\n renderHeight = displayHeight;\n renderWidth = displayHeight * videoAspect;\n offsetX = (displayWidth - renderWidth) / 2;\n offsetY = 0;\n }\n\n return {\n nativeWidth,\n nativeHeight,\n displayWidth: renderWidth,\n displayHeight: renderHeight,\n offsetX,\n offsetY,\n scaleX: renderWidth / nativeWidth,\n scaleY: renderHeight / nativeHeight,\n };\n}\n\nfunction ImageOverlay({ overlay }: { overlay: SwirlOverlay }) {\n const src = resolveImageUrl(overlay.image_url || \"\");\n if (!src) return null;\n return (\n <img\n src={src}\n alt={overlay.name}\n draggable={false}\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: \"contain\",\n display: \"block\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n );\n}\n\nfunction TextOverlay({ overlay }: { overlay: SwirlOverlay }) {\n const text = overlay.content || \"\";\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n fontSize: \"clamp(10px, 1.4vw, 20px)\",\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n fontWeight: 600,\n textAlign: \"center\",\n padding: \"4px 8px\",\n boxSizing: \"border-box\",\n wordBreak: \"break-word\",\n textShadow: \"0 1px 4px rgba(0,0,0,0.7)\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n lineHeight: 1.3,\n }}\n >\n {text}\n </div>\n );\n}\n\ninterface RSSItem {\n title: string;\n description: string;\n pubDate: string;\n author: string;\n category: string;\n}\n\nfunction parseRSSXml(xmlText: string, maxItems: number): RSSItem[] {\n const stripped = xmlText.replace(/^<\\?xml[^?]*\\?>\\s*/, \"\");\n const parser = new DOMParser();\n const doc = parser.parseFromString(stripped, \"text/xml\");\n const items = Array.from(doc.querySelectorAll(\"item\"))\n .map((item) => ({\n title: (item.querySelector(\"title\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n description: (item.querySelector(\"description\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n pubDate: item.querySelector(\"pubDate\")?.textContent || \"\",\n author: item.querySelector(\"author, dc\\\\:creator\")?.textContent || \"\",\n category: item.querySelector(\"category\")?.textContent || \"\",\n }))\n .filter((i) => i.title)\n .slice(0, maxItems);\n if (items.length === 0 && doc.querySelector(\"parsererror\")) {\n throw new Error(\"Invalid RSS XML\");\n }\n return items;\n}\n\nconst RSS_CACHE_TTL_MS = 60_000;\nconst rssCache = new Map<string, { promise: Promise<RSSItem[]>; expiresAt: number }>();\n\nfunction cachedFetchRSSItems(rssUrl: string, maxItems: number): Promise<RSSItem[]> {\n const now = Date.now();\n const cached = rssCache.get(rssUrl);\n if (cached && cached.expiresAt > now) return cached.promise;\n const promise = fetchRSSItems(rssUrl, maxItems).catch((err) => {\n rssCache.delete(rssUrl);\n throw err;\n });\n rssCache.set(rssUrl, { promise, expiresAt: now + RSS_CACHE_TTL_MS });\n return promise;\n}\n\nasync function fetchRSSItems(rssUrl: string, maxItems: number): Promise<RSSItem[]> {\n const encoded = encodeURIComponent(rssUrl);\n\n try {\n const origin = typeof window !== \"undefined\" ? window.location.origin : \"\";\n const resp = await fetch(`${origin}/api/rss-proxy?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text.includes(\"<item\")) return parseRSSXml(text, maxItems);\n }\n } catch { /* fall through */ }\n\n try {\n const resp = await fetch(`https://api.allorigins.win/get?url=${encoded}`);\n if (resp.ok) {\n const data = await resp.json();\n if (data.contents) return parseRSSXml(data.contents, maxItems);\n }\n } catch { /* fall through */ }\n\n try {\n const resp = await fetch(`https://corsproxy.io/?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text) return parseRSSXml(text, maxItems);\n }\n } catch { /* fall through */ }\n\n throw new Error(\"All RSS proxies failed\");\n}\n\nfunction ScrollerOverlay({ overlay }: { overlay: SwirlOverlay }) {\n const cfg = overlay.scroller_config;\n const uid = useId().replace(/:/g, \"\");\n\n const [rssItems, setRssItems] = useState<RSSItem[]>([]);\n const [rssLoading, setRssLoading] = useState(true);\n const [rssError, setRssError] = useState(false);\n\n const rssUrl = cfg?.rss_url || \"\";\n const maxItems = cfg?.max_items ?? 10;\n const autoRefresh = cfg?.auto_refresh !== false;\n const updateInterval = cfg?.update_interval ?? 5;\n\n useEffect(() => {\n if (!rssUrl || (cfg?.use_custom_text && cfg?.custom_text)) {\n setRssLoading(false);\n return;\n }\n let cancelled = false;\n setRssLoading(true);\n setRssError(false);\n cachedFetchRSSItems(rssUrl, maxItems)\n .then((items) => { if (!cancelled) { setRssItems(items); setRssError(false); } })\n .catch(() => { if (!cancelled) setRssError(true); })\n .finally(() => { if (!cancelled) setRssLoading(false); });\n return () => { cancelled = true; };\n }, [rssUrl, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n\n useEffect(() => {\n if (!rssUrl || !autoRefresh || (cfg?.use_custom_text && cfg?.custom_text)) return;\n const interval = setInterval(() => {\n rssCache.delete(rssUrl);\n cachedFetchRSSItems(rssUrl, maxItems)\n .then((items) => { setRssItems(items); setRssError(false); })\n .catch(() => { /* keep showing last good items */ });\n }, updateInterval * 60 * 1000);\n return () => clearInterval(interval);\n }, [rssUrl, autoRefresh, updateInterval, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n\n const sep = cfg?.separator_char ?? \"◆\";\n\n let segments: string[];\n if (cfg?.use_custom_text && cfg?.custom_text) {\n segments = [cfg.custom_text];\n } else if (rssItems.length > 0) {\n segments = rssItems.map((item) => {\n const parts: string[] = [];\n if (cfg?.show_title !== false && item.title) parts.push(item.title);\n if (cfg?.show_description && item.description) parts.push(item.description);\n if (cfg?.show_timestamp && item.pubDate) {\n try { parts.push(new Date(item.pubDate).toLocaleDateString()); } catch { /* ignore */ }\n }\n if (cfg?.show_author && item.author) parts.push(`— ${item.author}`);\n if (cfg?.show_category && item.category) parts.push(`[${item.category}]`);\n return parts.join(\" \");\n });\n } else if (rssLoading) {\n segments = [\"Loading feed…\"];\n } else if (rssError) {\n segments = overlay.content ? [overlay.content] : [\"RSS feed unavailable\"];\n } else if (overlay.content) {\n segments = [overlay.content];\n } else {\n segments = rssUrl ? [\"Loading feed…\"] : [\"RSS Ticker\"];\n }\n\n const scrollSpeed = cfg?.scroll_speed ?? 40;\n const direction = cfg?.direction ?? \"left\";\n const fontSize = cfg?.font_size ?? 15;\n const fontFamily = cfg?.font_family || \"Roboto, 'Segoe UI', Arial, sans-serif\";\n const fontWeight = cfg?.font_weight || \"700\";\n const textColor = cfg?.text_color || \"#ffffff\";\n const bgColor = cfg?.background_color || \"#0d0d1a\";\n const bgOpacity = cfg?.background_opacity !== undefined ? cfg.background_opacity / 100 : 0.95;\n const borderRadius = cfg?.border_radius ?? 0;\n const itemSpacing = cfg?.item_spacing ?? 60;\n const pad = cfg?.padding !== undefined && cfg.padding >= 0 ? cfg.padding : 8;\n\n const label = cfg?.label ?? \"NEWS\";\n const labelLine2 = cfg?.label_line2 ?? \"\";\n const labelColor = cfg?.label_color ?? \"#f97316\";\n const labelTextColor = cfg?.label_text_color ?? \"#ffffff\";\n const accentColor = cfg?.accent_color ?? labelColor;\n const showAccentLine = cfg?.show_accent_line !== false;\n const isEquitiesStrip = cfg?.preset === \"equities_strip\";\n\n const isHorizontal = direction === \"left\" || direction === \"right\";\n const isReverse = direction === \"right\" || direction === \"down\";\n\n const fullText = segments.join(` ${sep} `);\n const durationSec = Math.max(6, (fullText.length * 9) / scrollSpeed);\n\n const animId = `sc-ticker-${overlay.id}-${uid}`;\n const keyframes = isHorizontal\n ? `@keyframes ${animId} {\n ${isReverse\n ? \"0% { transform: translateX(-50%); } 100% { transform: translateX(0%); }\"\n : \"0% { transform: translateX(0); } 100% { transform: translateX(-50%); }\"}\n }`\n : `@keyframes ${animId} {\n ${isReverse\n ? \"0% { transform: translateY(-50%); } 100% { transform: translateY(0%); }\"\n : \"0% { transform: translateY(0); } 100% { transform: translateY(-50%); }\"}\n }`;\n\n return (\n <>\n <style>{keyframes}</style>\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n borderRadius: borderRadius > 0 ? `${borderRadius}px` : undefined,\n backgroundColor: `rgba(${hexToRgb(bgColor)}, ${bgOpacity})`,\n fontFamily,\n fontSize: `${fontSize}px`,\n fontWeight,\n color: textColor,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n >\n {showAccentLine && (\n <div\n style={{\n height: isEquitiesStrip ? 2 : 3,\n background: accentColor,\n flexShrink: 0,\n width: \"100%\",\n }}\n />\n )}\n\n <div\n style={{\n display: \"flex\",\n flex: 1,\n overflow: \"hidden\",\n minHeight: 0,\n alignItems: \"center\",\n padding: isEquitiesStrip\n ? `${Math.max(2, pad * 0.5)}px ${pad}px`\n : `${Math.max(4, pad * 0.75)}px ${pad}px`,\n gap: isEquitiesStrip ? Math.max(4, Math.round(pad * 0.75)) : Math.max(6, pad),\n boxSizing: \"border-box\",\n }}\n >\n {label && (\n <div\n style={{\n background: labelColor,\n color: labelTextColor,\n padding: isEquitiesStrip ? \"6px 12px\" : \"10px 14px\",\n display: \"flex\",\n flexDirection: isEquitiesStrip ? \"row\" : \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n textAlign: \"center\",\n gap: isEquitiesStrip ? 0 : 2,\n borderRadius: Math.max(2, borderRadius > 0 ? borderRadius : 6),\n boxShadow: isEquitiesStrip\n ? \"inset 0 1px 0 rgba(255,255,255,0.08)\"\n : \"0 2px 8px rgba(0,0,0,0.35)\",\n alignSelf: \"stretch\",\n maxWidth: isEquitiesStrip ? \"min(200px, 28%)\" : undefined,\n }}\n >\n <span\n style={{\n fontWeight: isEquitiesStrip ? 700 : 800,\n fontSize: isEquitiesStrip ? \"0.82em\" : \"0.78em\",\n letterSpacing: isEquitiesStrip ? \"0.04em\" : \"0.08em\",\n lineHeight: 1.2,\n textTransform: isEquitiesStrip ? \"none\" : \"uppercase\",\n whiteSpace: isEquitiesStrip ? \"normal\" : \"nowrap\",\n textAlign: isEquitiesStrip ? \"left\" : \"center\",\n }}\n >\n {label}\n </span>\n {labelLine2 && !isEquitiesStrip && (\n <span\n style={{\n fontWeight: 600,\n fontSize: \"0.58em\",\n letterSpacing: \"0.06em\",\n lineHeight: 1.15,\n opacity: 0.92,\n whiteSpace: \"nowrap\",\n }}\n >\n {labelLine2}\n </span>\n )}\n </div>\n )}\n\n {label && (\n <div\n style={{\n width: isEquitiesStrip ? 1 : 2,\n alignSelf: \"stretch\",\n minHeight: isEquitiesStrip ? 20 : 24,\n background: accentColor,\n flexShrink: 0,\n borderRadius: 1,\n opacity: 0.85,\n }}\n />\n )}\n\n <div\n style={{\n flex: 1,\n overflow: \"hidden\",\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n minWidth: 0,\n }}\n >\n {isHorizontal ? (\n <div\n style={{\n display: \"inline-flex\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\",\n }}\n >\n {[0, 1].map((copy) => (\n <span key={copy} style={{ paddingRight: `${itemSpacing}px` }}>\n {segments.map((seg, i) => (\n <React.Fragment key={i}>\n {i > 0 && (\n <span style={{ opacity: 0.5, margin: \"0 8px\" }}>{sep}</span>\n )}\n <span style={{ textShadow: \"0 1px 3px rgba(0,0,0,0.6)\" }}>{seg}</span>\n </React.Fragment>\n ))}\n </span>\n ))}\n </div>\n ) : (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\",\n }}\n >\n {[0, 1].map((copy) =>\n segments.map((seg, i) => (\n <div key={`${copy}-${i}`} style={{ paddingBottom: `${itemSpacing / 4}px` }}>\n {seg}\n </div>\n ))\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n\nfunction parseConfig<T>(content?: string): T | null {\n if (!content) return null;\n try { return JSON.parse(content) as T; } catch { return null; }\n}\n\ninterface OverlaySize { w: number; h: number; }\n\ninterface ScoreBugCfg { homeTeam: string; awayTeam: string; homeScore: number; awayScore: number; period: string; clock: string; sponsorText: string; sponsorImageUrl: string; backgroundColor: string; textColor: string; accentColor: string; }\ninterface LowerThirdCfg { headline: string; subtitle: string; sponsorText: string; sponsorImageUrl: string; backgroundColor: string; textColor: string; accentColor: string; style: string; }\ninterface QrCodeCfg { url: string; ctaText: string; description: string; size: number; backgroundColor: string; textColor: string; accentColor: string; }\ninterface ComingUpNextCfg { title: string; subtitle: string; scheduledTime: string; thumbnailUrl: string; backgroundColor: string; textColor: string; accentColor: string; }\ninterface ContextualTriggerCfg { triggerType: string; headline: string; message: string; iconType: string; backgroundColor: string; textColor: string; accentColor: string; animationStyle: string; }\ninterface OddsBettingCfg { eventTitle: string; options: Array<{ label: string; odds: string }>; sponsorText: string; backgroundColor: string; textColor: string; accentColor: string; oddsFormat: string; }\ninterface BreakingNewsCfg { headline: string; body: string; urgency: string; backgroundColor: string; textColor: string; accentColor: string; }\ninterface CountdownCfg { eventName: string; targetTime: string; message: string; showDays: boolean; showHours: boolean; showMinutes: boolean; showSeconds: boolean; backgroundColor: string; textColor: string; accentColor: string; }\n\nfunction parseClockMMSS(clock: string | undefined): number | null {\n if (!clock) return null;\n const m = /^\\s*(\\d{1,3}):([0-5]?\\d)\\s*$/.exec(clock);\n if (!m) return null;\n return parseInt(m[1]!, 10) * 60 + parseInt(m[2]!, 10);\n}\n\nfunction formatClockMMSS(totalSec: number): string {\n const s = Math.max(0, Math.floor(totalSec));\n const mm = Math.floor(s / 60);\n const ss = s % 60;\n return `${mm}:${ss.toString().padStart(2, \"0\")}`;\n}\n\nfunction useScoreBugClock(overlayId: number, sourceClock: string | undefined): string | null {\n const initialSec = parseClockMMSS(sourceClock);\n const [now, setNow] = useState<number>(() => Date.now());\n const startRef = useRef<{ id: number; source: string; at: number; seconds: number } | null>(null);\n\n useEffect(() => {\n if (initialSec === null) {\n startRef.current = null;\n return;\n }\n startRef.current = {\n id: overlayId,\n source: sourceClock || \"\",\n at: Date.now(),\n seconds: initialSec,\n };\n setNow(Date.now());\n const tick = window.setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(tick);\n }, [overlayId, sourceClock, initialSec]);\n\n if (initialSec === null || !startRef.current) return null;\n const elapsed = Math.floor((now - startRef.current.at) / 1000);\n const remaining = Math.max(0, startRef.current.seconds - elapsed);\n return formatClockMMSS(remaining);\n}\n\nfunction ScoreBugOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<ScoreBugCfg>(overlay.content);\n const liveClock = useScoreBugClock(overlay.id, cfg?.clock);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n const displayClock = liveClock ?? cfg.clock ?? \"\";\n const displayPeriod = cfg.period ?? \"\";\n const showMiddleCol = Boolean(displayPeriod || displayClock);\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.028),\n display: \"flex\",\n flexDirection: \"column\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 8px 28px rgba(0,0,0,0.45)\",\n }}\n >\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n padding: `${f * 0.42}px ${f * 0.85}px`,\n gap: f * 0.45,\n minHeight: 0,\n }}\n >\n <div style={{ flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }}>\n <div\n style={{\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {cfg.homeTeam}\n </div>\n <div style={{ fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }}>\n {cfg.homeScore}\n </div>\n </div>\n {showMiddleCol && (\n <div\n style={{\n fontSize: \"0.88em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.92,\n color: cfg.textColor,\n padding: `0 ${f * 0.5}px`,\n flexShrink: 0,\n lineHeight: 1.25,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n }}\n >\n {displayPeriod && <div>{displayPeriod}</div>}\n {displayClock && (\n <div style={{ fontWeight: 700, opacity: 1 }}>{displayClock}</div>\n )}\n </div>\n )}\n <div style={{ flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }}>\n <div\n style={{\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {cfg.awayTeam}\n </div>\n <div style={{ fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }}>\n {cfg.awayScore}\n </div>\n </div>\n </div>\n {(cfg.sponsorText || cfg.sponsorImageUrl) && (\n <div\n style={{\n fontSize: \"0.72em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.88,\n padding: `${f * 0.34}px ${f * 0.55}px`,\n borderTop: `1px solid ${cfg.accentColor}55`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: f * 0.45,\n overflow: \"hidden\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n background: `linear-gradient(180deg, rgba(0,0,0,0.12) 0%, rgba(0,0,0,0.22) 100%)`,\n }}\n >\n {cfg.sponsorImageUrl && (\n <img src={cfg.sponsorImageUrl} alt=\"sponsor\" style={{ height: `${f * 1.35}px`, objectFit: \"contain\", flexShrink: 0 }} />\n )}\n {cfg.sponsorText && (\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.sponsorText}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction LowerThirdOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<LowerThirdCfg>(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.05);\n const accentH = Math.max(3, size.h * 0.038);\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.018),\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"flex-end\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 10px 32px rgba(0,0,0,0.4)\",\n }}\n >\n <div style={{ width: \"100%\", height: accentH, backgroundColor: cfg.accentColor, flexShrink: 0 }} />\n <div\n style={{\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: `${f * 0.62}px ${f * 1.05}px`,\n minHeight: 0,\n gap: f * 0.18,\n }}\n >\n <div\n style={{\n fontSize: \"1.28em\",\n fontWeight: 800,\n lineHeight: 1.22,\n letterSpacing: \"0.01em\",\n textShadow: \"0 2px 6px rgba(0,0,0,0.55)\",\n }}\n >\n {cfg.headline}\n </div>\n <div\n style={{\n fontSize: \"0.94em\",\n fontWeight: 500,\n opacity: 0.92,\n lineHeight: 1.35,\n color: cfg.textColor,\n }}\n >\n {cfg.subtitle}\n </div>\n </div>\n {(cfg.sponsorText || cfg.sponsorImageUrl) && (\n <div\n style={{\n fontSize: \"0.68em\",\n fontWeight: 600,\n opacity: 0.72,\n padding: `${f * 0.28}px ${f * 1.05}px ${f * 0.48}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: f * 0.4,\n overflow: \"hidden\",\n letterSpacing: \"0.06em\",\n textTransform: \"uppercase\",\n borderTop: `1px solid rgba(255,255,255,0.08)`,\n }}\n >\n {cfg.sponsorImageUrl && (\n <img src={cfg.sponsorImageUrl} alt=\"sponsor\" style={{ height: `${f * 1.25}px`, objectFit: \"contain\", flexShrink: 0 }} />\n )}\n {cfg.sponsorText && (\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.sponsorText}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction QrCodeOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<QrCodeCfg>(overlay.content);\n if (!cfg) return null;\n const qrSide = Math.max(32, Math.min(size.w, size.h) * 0.55);\n const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=${Math.round(qrSide * 2)}x${Math.round(qrSide * 2)}&data=${encodeURIComponent(cfg.url || \"https://example.com\")}`;\n const f = Math.max(6, size.w * 0.06);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", gap: f * 0.4, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", padding: f * 0.6, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", overflow: \"hidden\" }}>\n <div style={{ flexShrink: 0, background: \"#fff\", borderRadius: Math.max(2, qrSide * 0.06), padding: Math.max(2, qrSide * 0.06), lineHeight: 0 }}>\n <img src={qrUrl} alt=\"QR Code\" style={{ width: `${qrSide}px`, height: `${qrSide}px`, display: \"block\" }} />\n </div>\n <div style={{ fontSize: `${f * 1.1}px`, fontWeight: 700, textAlign: \"center\", color: cfg.accentColor, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }}>{cfg.ctaText}</div>\n {cfg.description && <div style={{ fontSize: `${f * 0.75}px`, opacity: 0.6, textAlign: \"center\", overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }}>{cfg.description}</div>}\n </div>\n );\n}\n\nfunction ComingUpNextOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<ComingUpNextCfg>(overlay.content);\n if (!cfg) return null;\n const f = Math.max(8, Math.min(size.h * 0.13, size.w * 0.048));\n const showSubtitle = size.h >= 60;\n const showThumbnail = false;\n const thumbW = 0;\n return (\n <div style={{\n width: \"100%\", height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.025),\n display: \"flex\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Arial', 'Helvetica Neue', Helvetica, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\", userSelect: \"none\",\n fontSize: `${f}px`,\n WebkitFontSmoothing: \"antialiased\",\n } as React.CSSProperties}>\n <div style={{ width: Math.max(3, size.w * 0.018), flexShrink: 0, backgroundColor: cfg.accentColor }} />\n <div style={{\n flex: 1, display: \"flex\", flexDirection: \"column\", justifyContent: \"center\",\n padding: `${f * 0.35}px ${f * 0.75}px`,\n minWidth: 0, gap: `${f * 0.08}px`,\n }}>\n <div style={{\n fontSize: \"0.7em\", fontWeight: 700,\n textTransform: \"uppercase\", letterSpacing: \"0.09em\",\n color: cfg.accentColor, lineHeight: 1,\n }}>\n Coming Up Next\n </div>\n <div style={{\n fontSize: \"1.2em\", fontWeight: 700, lineHeight: 1.2,\n overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\",\n }}>\n {cfg.title}\n </div>\n {showSubtitle && (\n <div style={{\n fontSize: \"0.82em\", opacity: 0.65, lineHeight: 1.1,\n overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\",\n }}>\n {cfg.subtitle}\n </div>\n )}\n {cfg.scheduledTime && (\n <div style={{\n fontSize: \"0.9em\", fontWeight: 700,\n color: cfg.accentColor, lineHeight: 1,\n }}>\n {cfg.scheduledTime}\n </div>\n )}\n </div>\n {showThumbnail && (\n <div style={{ flexShrink: 0, width: `${thumbW}px`, overflow: \"hidden\" }}>\n <img\n src={cfg.thumbnailUrl}\n alt=\"\"\n style={{ width: \"100%\", height: \"100%\", objectFit: \"cover\", display: \"block\" }}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction ContextualTriggerOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<ContextualTriggerCfg>(overlay.content);\n if (!cfg) return null;\n const icons: Record<string, string> = { alert: \"\\u26A0\\uFE0F\", celebration: \"\\uD83C\\uDF89\", info: \"\\u2139\\uFE0F\", warning: \"\\uD83D\\uDD14\" };\n const f = Math.max(6, size.w * 0.05);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", alignItems: \"center\", gap: f * 0.8, padding: `0 ${f * 1.2}px`, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", borderLeft: `${Math.max(2, size.w * 0.02)}px solid ${cfg.accentColor}`, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <span style={{ fontSize: \"2em\", flexShrink: 0 }}>{icons[cfg.iconType] || \"\\u26A1\"}</span>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.headline}</div>\n <div style={{ fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.message}</div>\n </div>\n </div>\n );\n}\n\nfunction OddsBettingOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<OddsBettingCfg>(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <div style={{ fontSize: \"0.9em\", fontWeight: 700, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }}>{cfg.eventTitle}</div>\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\", gap: f * 0.2, justifyContent: \"center\" }}>\n {(cfg.options || []).slice(0, 5).map((opt, i) => (\n <div key={i} style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", padding: `${f * 0.2}px ${f * 0.6}px`, borderRadius: Math.max(2, f * 0.3), background: `${cfg.accentColor}15`, fontSize: \"1em\" }}>\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", flex: 1 }}>{opt.label}</span>\n <span style={{ fontWeight: 700, marginLeft: f * 0.8, flexShrink: 0, color: cfg.accentColor }}>{opt.odds}</span>\n </div>\n ))}\n </div>\n {cfg.sponsorText && <div style={{ fontSize: \"0.7em\", opacity: 0.4, textAlign: \"center\", marginTop: f * 0.4 }}>{cfg.sponsorText}</div>}\n </div>\n );\n}\n\nfunction BreakingNewsOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<BreakingNewsCfg>(overlay.content);\n if (!cfg) return null;\n const urgencyColors: Record<string, string> = { breaking: \"#dc2626\", urgent: \"#ea580c\", normal: \"#2563eb\" };\n const labelBg = urgencyColors[cfg.urgency] || urgencyColors.normal;\n const label = cfg.urgency === \"breaking\" ? \"BREAKING\" : cfg.urgency === \"urgent\" ? \"URGENT\" : \"NEWS\";\n const f = Math.max(6, size.w * 0.05);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.02), display: \"flex\", alignItems: \"center\", background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", overflow: \"hidden\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <div style={{ padding: `0 ${f * 0.8}px`, height: \"100%\", display: \"flex\", alignItems: \"center\", background: labelBg, color: \"#fff\", fontSize: \"1em\", fontWeight: 900, textTransform: \"uppercase\", letterSpacing: \"0.05em\", flexShrink: 0 }}>{label}</div>\n <div style={{ flex: 1, padding: `0 ${f * 1.0}px`, minWidth: 0 }}>\n <div style={{ fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.headline}</div>\n {cfg.body && <div style={{ fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.body}</div>}\n </div>\n </div>\n );\n}\n\nfunction calcCountdownRemaining(targetTime: string) {\n const diff = Math.max(0, new Date(targetTime).getTime() - Date.now());\n return {\n d: Math.floor(diff / 86400000),\n h: Math.floor((diff % 86400000) / 3600000),\n m: Math.floor((diff % 3600000) / 60000),\n s: Math.floor((diff % 60000) / 1000),\n expired: diff === 0,\n };\n}\n\nfunction CountdownOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<CountdownCfg>(overlay.content);\n const targetTime = cfg?.targetTime ?? \"\";\n const [remaining, setRemaining] = useState(() =>\n targetTime ? calcCountdownRemaining(targetTime) : { d: 0, h: 0, m: 0, s: 0, expired: false }\n );\n\n useEffect(() => {\n if (!targetTime) return;\n setRemaining(calcCountdownRemaining(targetTime));\n const id = setInterval(() => setRemaining(calcCountdownRemaining(targetTime)), 1000);\n return () => clearInterval(id);\n }, [targetTime]);\n\n if (!cfg) return null;\n\n const f = Math.max(6, size.w * 0.055);\n const pad = (n: number) => String(n).padStart(2, \"0\");\n const units: Array<{ show: boolean; value: string; label: string }> = [\n { show: cfg.showDays, value: pad(remaining.d), label: \"DAYS\" },\n { show: cfg.showHours, value: pad(remaining.h), label: \"HRS\" },\n { show: cfg.showMinutes, value: pad(remaining.m), label: \"MIN\" },\n { show: cfg.showSeconds, value: pad(remaining.s), label: \"SEC\" },\n ];\n\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <div style={{ fontSize: \"0.8em\", fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }}>{cfg.eventName}</div>\n {remaining.expired ? (\n <div style={{ fontSize: \"1em\", fontWeight: 700, opacity: 0.6 }}>{cfg.message || \"Event ended\"}</div>\n ) : (\n <div style={{ display: \"flex\", gap: f * 0.6, alignItems: \"center\" }}>\n {units.filter(u => u.show).map((u, i, arr) => (\n <React.Fragment key={u.label}>\n <div style={{ textAlign: \"center\" }}>\n <div style={{ fontSize: \"2em\", fontWeight: 900, lineHeight: 1, borderRadius: Math.max(2, f * 0.4), padding: `${f * 0.2}px ${f * 0.4}px`, background: `${cfg.accentColor}20` }}>{u.value}</div>\n <div style={{ fontSize: \"0.5em\", opacity: 0.5, marginTop: f * 0.2 }}>{u.label}</div>\n </div>\n {i < arr.length - 1 && <div style={{ fontSize: \"1.8em\", fontWeight: 700, opacity: 0.3 }}>:</div>}\n </React.Fragment>\n ))}\n </div>\n )}\n {!remaining.expired && cfg.message && <div style={{ fontSize: \"0.8em\", opacity: 0.6, marginTop: f * 0.4, textAlign: \"center\" }}>{cfg.message}</div>}\n </div>\n );\n}\n\nfunction ShapeOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const f = Math.max(6, size.w * 0.05);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.03), background: \"rgba(99, 102, 241, 0.2)\", border: \"2px solid rgba(99, 102, 241, 0.4)\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\", pointerEvents: \"none\", userSelect: \"none\" }}>\n <div style={{ fontSize: `${f}px`, fontWeight: 500, color: \"rgba(163, 163, 163, 0.8)\", textTransform: \"uppercase\" }}>{overlay.name}</div>\n </div>\n );\n}\n\nfunction hexToRgb(hex: string): string {\n if (!hex || !hex.startsWith(\"#\")) return \"0,0,0\";\n const clean = hex.slice(1);\n const num = parseInt(clean.length === 3 ? clean.replace(/./g, \"$&$&\") : clean, 16);\n return `${(num >> 16) & 255},${(num >> 8) & 255},${num & 255}`;\n}\n\ninterface OverlayFadeState {\n overlay: SwirlOverlay;\n visible: boolean;\n}\n\nconst FADE_DURATION_MS = 1000;\n\ntype EnterAnimation =\n | \"fade\"\n | \"slide_left\"\n | \"slide_right\"\n | \"slide_up\"\n | \"slide_down\";\n\nconst VALID_ENTER_ANIMATIONS: ReadonlySet<EnterAnimation> = new Set([\n \"fade\",\n \"slide_left\",\n \"slide_right\",\n \"slide_up\",\n \"slide_down\",\n]);\n\nfunction getEnterAnimation(overlay: SwirlOverlay): EnterAnimation {\n const flat = (overlay as unknown as { enter_animation?: unknown })\n .enter_animation;\n if (typeof flat === \"string\" && VALID_ENTER_ANIMATIONS.has(flat as EnterAnimation)) {\n return flat as EnterAnimation;\n }\n if (overlay.content) {\n try {\n const parsed = JSON.parse(overlay.content) as Record<string, unknown>;\n const v = parsed?.enterAnimation;\n if (typeof v === \"string\" && VALID_ENTER_ANIMATIONS.has(v as EnterAnimation)) {\n return v as EnterAnimation;\n }\n } catch {\n // ignore malformed content\n }\n }\n return \"fade\";\n}\n\nfunction enterHiddenTransform(anim: EnterAnimation): string {\n switch (anim) {\n case \"slide_left\":\n return \"translateX(-120%)\";\n case \"slide_right\":\n return \"translateX(120%)\";\n case \"slide_up\":\n return \"translateY(-120%)\";\n case \"slide_down\":\n return \"translateY(120%)\";\n default:\n return \"\";\n }\n}\n\nconst SHOWCASE_CYCLE_MS_DEFAULT = 36_000;\nconst SHOWCASE_MIN_BEAT_MS = 6_000;\nconst BEAT_POP_IN_MS = 520;\nconst BEAT_POP_OUT_MS = 520;\n\nconst SHOWCASE_PERSISTENT_TYPES: ReadonlySet<string> = new Set([\n \"scroller\",\n \"breaking_news\",\n \"image\",\n \"text\",\n \"shape\",\n \"countdown\",\n \"qr_code\",\n \"coming_up_next\",\n \"score_bug\",\n]);\n\nfunction easeOutCubic(t: number): number {\n const u = 1 - t;\n return 1 - u * u * u;\n}\n\nfunction easeInCubic(t: number): number {\n return t * t * t;\n}\n\nfunction easeOutBack(t: number): number {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n return 1 + c3 * (t - 1) ** 3 + c1 * (t - 1) ** 2;\n}\n\nfunction beatOpacity(phase: number, beatMs: number): number {\n if (phase < BEAT_POP_IN_MS) return easeOutCubic(phase / BEAT_POP_IN_MS);\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return Math.max(\n 0,\n 1 - easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS)\n );\n }\n return 1;\n}\n\nfunction beatScale(phase: number, beatMs: number): number {\n if (phase < BEAT_POP_IN_MS) {\n return Math.min(1, 0.92 + 0.08 * easeOutBack(phase / BEAT_POP_IN_MS));\n }\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return 1 - 0.06 * easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS);\n }\n return 1;\n}\n\nfunction partitionShowcase(overlays: SwirlOverlay[]): {\n persistent: SwirlOverlay[];\n beats: SwirlOverlay[][];\n} {\n const visible = overlays.filter((o) => o.visible);\n const persistent: SwirlOverlay[] = [];\n const spotlight: SwirlOverlay[] = [];\n for (const o of visible) {\n if (SHOWCASE_PERSISTENT_TYPES.has(o.type)) persistent.push(o);\n else spotlight.push(o);\n }\n spotlight.sort(\n (a, b) => (a.z_index - b.z_index) || (a.id - b.id)\n );\n const beats: SwirlOverlay[][] = [];\n for (const o of spotlight) beats.push([o]);\n return { persistent, beats };\n}\n\nfunction useShowcaseBeat(\n enabled: boolean,\n cycleMs: number,\n beats: number\n): { beatIndex: number; beatPhase: number; beatMs: number } {\n const safeBeats = Math.max(1, beats);\n const beatMs = Math.max(\n SHOWCASE_MIN_BEAT_MS,\n Math.floor(cycleMs / safeBeats)\n );\n const totalMs = beatMs * safeBeats;\n const [now, setNow] = useState<number>(() => Date.now());\n useEffect(() => {\n if (!enabled) return;\n const id = window.setInterval(() => setNow(Date.now()), 64);\n return () => clearInterval(id);\n }, [enabled]);\n const phase = now % totalMs;\n const beatIndex = Math.min(safeBeats - 1, Math.floor(phase / beatMs));\n const beatPhase = phase - beatIndex * beatMs;\n return { beatIndex, beatPhase, beatMs };\n}\n\nexport const OverlayRenderer: React.FC<OverlayRendererProps> = ({\n overlays,\n currentTime,\n videoRef,\n coordinateSpace,\n showcaseMode = false,\n showcaseCycleMs = SHOWCASE_CYCLE_MS_DEFAULT,\n}) => {\n const [dims, setDims] = useState<VideoDimensions | null>(null);\n const rafRef = useRef<number | null>(null);\n const [fadeMap, setFadeMap] = useState<Map<number, OverlayFadeState>>(new Map());\n const removeTimers = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());\n\n const mountTimeRef = useRef<number>(Date.now());\n const [wallclockSec, setWallclockSec] = useState<number>(0);\n useEffect(() => {\n if (!showcaseMode) return;\n const tick = () =>\n setWallclockSec((Date.now() - mountTimeRef.current) / 1000);\n tick();\n const id = window.setInterval(tick, 200);\n return () => clearInterval(id);\n }, [showcaseMode]);\n\n const { persistent: showcasePersistent, beats: showcaseBeats } = useMemo(\n () => partitionShowcase(overlays),\n [overlays]\n );\n const {\n beatIndex: showcaseBeatIndex,\n beatPhase: showcaseBeatPhase,\n beatMs: showcaseBeatMs,\n } = useShowcaseBeat(showcaseMode, showcaseCycleMs, showcaseBeats.length);\n\n const showcasePersistentIds = useMemo(\n () => new Set(showcasePersistent.map((o) => o.id)),\n [showcasePersistent]\n );\n const showcaseSpotlightIds = useMemo(() => {\n const beat = showcaseBeats[showcaseBeatIndex];\n return new Set((beat ?? []).map((o) => o.id));\n }, [showcaseBeats, showcaseBeatIndex]);\n\n const updateDims = useCallback(() => {\n const video = videoRef.current;\n if (video) {\n const computed = computeVideoDimensions(video);\n setDims((prev) => {\n if (\n !computed ||\n (prev &&\n prev.nativeWidth === computed.nativeWidth &&\n prev.nativeHeight === computed.nativeHeight &&\n prev.displayWidth === computed.displayWidth &&\n prev.displayHeight === computed.displayHeight &&\n prev.offsetX === computed.offsetX &&\n prev.offsetY === computed.offsetY)\n ) {\n return prev;\n }\n return computed;\n });\n }\n }, [videoRef]);\n\n useEffect(() => {\n updateDims();\n const interval = setInterval(updateDims, 500);\n\n const handleResize = () => {\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(updateDims);\n };\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n clearInterval(interval);\n window.removeEventListener(\"resize\", handleResize);\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n };\n }, [updateDims]);\n\n const activeOverlays = useMemo(() => {\n if (showcaseMode) {\n const beat = showcaseBeats[showcaseBeatIndex] ?? [];\n const scheduledPersistent = showcasePersistent.filter((o) =>\n isOverlayActive(o, wallclockSec)\n );\n return [...scheduledPersistent, ...beat];\n }\n return overlays.filter((o) => isOverlayActive(o, currentTime));\n }, [\n overlays,\n currentTime,\n wallclockSec,\n showcaseMode,\n showcasePersistent,\n showcaseBeats,\n showcaseBeatIndex,\n ]);\n\n useLayoutEffect(() => {\n const activeIds = new Set(activeOverlays.map((o) => o.id));\n\n setFadeMap((prev) => {\n const next = new Map(prev);\n\n for (const overlay of activeOverlays) {\n if (!next.has(overlay.id)) {\n next.set(overlay.id, { overlay, visible: false });\n } else {\n const existing = next.get(overlay.id)!;\n next.set(overlay.id, { ...existing, overlay });\n }\n }\n\n for (const [id, state] of next) {\n if (!activeIds.has(id) && state.visible) {\n next.set(id, { ...state, visible: false });\n if (!removeTimers.current.has(id)) {\n const timer = setTimeout(() => {\n setFadeMap((m) => {\n const updated = new Map(m);\n updated.delete(id);\n return updated;\n });\n removeTimers.current.delete(id);\n }, FADE_DURATION_MS);\n removeTimers.current.set(id, timer);\n }\n } else if (!activeIds.has(id) && !state.visible) {\n }\n }\n\n return next;\n });\n }, [activeOverlays]);\n\n useEffect(() => {\n const toFadeIn: number[] = [];\n for (const [id, state] of fadeMap) {\n if (!state.visible) {\n const isActive = activeOverlays.some((o) => o.id === id);\n if (isActive) toFadeIn.push(id);\n }\n }\n if (toFadeIn.length === 0) return;\n\n const raf = requestAnimationFrame(() => {\n setFadeMap((prev) => {\n const next = new Map(prev);\n for (const id of toFadeIn) {\n const state = next.get(id);\n if (state) next.set(id, { ...state, visible: true });\n }\n return next;\n });\n });\n return () => cancelAnimationFrame(raf);\n }, [fadeMap, activeOverlays]);\n\n useEffect(() => {\n return () => {\n for (const timer of removeTimers.current.values()) clearTimeout(timer);\n };\n }, []);\n\n if (!dims || fadeMap.size === 0) return null;\n\n return (\n <div\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n left: `${dims.offsetX}px`,\n top: `${dims.offsetY}px`,\n width: `${dims.displayWidth}px`,\n height: `${dims.displayHeight}px`,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n zIndex: 8,\n }}\n >\n {[...fadeMap.values()].map(({ overlay, visible }) => {\n const scaleX = coordinateSpace?.width\n ? dims.displayWidth / coordinateSpace.width\n : dims.scaleX;\n const scaleY = coordinateSpace?.height\n ? dims.displayHeight / coordinateSpace.height\n : dims.scaleY;\n const left = overlay.x * scaleX;\n const top = overlay.y * scaleY;\n const width = overlay.width * scaleX;\n const height = overlay.height * scaleY;\n const baseOpacity = Math.max(0, Math.min(100, overlay.opacity)) / 100;\n const isShowcasePersistent =\n showcaseMode && showcasePersistentIds.has(overlay.id);\n const isShowcaseSpotlight =\n showcaseMode && showcaseSpotlightIds.has(overlay.id);\n\n const isShowcaseDormant =\n showcaseMode && !isShowcasePersistent && !isShowcaseSpotlight;\n const useShowcasePop = isShowcaseSpotlight;\n const opacity = useShowcasePop\n ? baseOpacity *\n beatOpacity(showcaseBeatPhase, showcaseBeatMs)\n : isShowcaseDormant\n ? 0\n : visible\n ? baseOpacity\n : 0;\n const popScale = useShowcasePop\n ? beatScale(showcaseBeatPhase, showcaseBeatMs)\n : 1;\n const sz: OverlaySize = { w: width, h: height };\n\n const enterAnim = getEnterAnimation(overlay);\n const hasSlide = enterAnim !== \"fade\" && !useShowcasePop;\n const slideTransform = hasSlide && !visible\n ? enterHiddenTransform(enterAnim)\n : \"\";\n const popTransform = showcaseMode && useShowcasePop\n ? `scale(${popScale})`\n : \"\";\n const combinedTransform = [slideTransform, popTransform]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n key={overlay.id}\n style={{\n position: \"absolute\",\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n opacity,\n transition: useShowcasePop\n ? \"none\"\n : hasSlide\n ? `opacity ${FADE_DURATION_MS}ms ease, transform ${FADE_DURATION_MS}ms cubic-bezier(0.22, 1, 0.36, 1)`\n : `opacity ${FADE_DURATION_MS}ms ease`,\n transform: combinedTransform || undefined,\n transformOrigin: showcaseMode && useShowcasePop ? \"center center\" : undefined,\n zIndex: overlay.z_index,\n overflow: \"hidden\",\n }}\n >\n {overlay.type === \"image\" && <ImageOverlay overlay={overlay} />}\n {overlay.type === \"text\" && <TextOverlay overlay={overlay} />}\n {overlay.type === \"scroller\" && <ScrollerOverlay overlay={overlay} />}\n {overlay.type === \"shape\" && <ShapeOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"score_bug\" && <ScoreBugOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"lower_third\" && <LowerThirdOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"qr_code\" && <QrCodeOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"coming_up_next\" && <ComingUpNextOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"contextual_trigger\" && <ContextualTriggerOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"odds_betting\" && <OddsBettingOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"breaking_news\" && <BreakingNewsOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"countdown\" && <CountdownOverlay overlay={overlay} size={sz} />}\n </div>\n );\n })}\n </div>\n );\n};\n","export const OVERLAY_API_BASE = \"https://adstorm.co/api-adstorm-dev\";\n\nexport interface OverlayCoordinateSpace {\n width: number;\n height: number;\n}\n\nexport interface SwirlScrollerConfig {\n rss_url?: string;\n update_interval?: number;\n scroll_speed?: number;\n direction?: string;\n font_size?: number;\n font_family?: string;\n font_weight?: string;\n text_color?: string;\n background_color?: string;\n background_opacity?: number;\n border_color?: string;\n border_width?: number;\n border_radius?: number;\n padding?: number;\n margin?: number;\n show_title?: boolean;\n show_description?: boolean;\n show_timestamp?: boolean;\n show_author?: boolean;\n show_category?: boolean;\n max_items?: number;\n item_spacing?: number;\n fade_in_out?: boolean;\n fade_distance?: number;\n auto_refresh?: boolean;\n use_custom_text?: boolean;\n custom_text?: string;\n label?: string;\n label_line2?: string;\n label_color?: string;\n label_text_color?: string;\n accent_color?: string;\n show_accent_line?: boolean;\n separator_char?: string;\n preset?: string;\n}\n\nexport type SwirlOverlayType =\n | \"image\"\n | \"text\"\n | \"scroller\"\n | \"shape\"\n | \"score_bug\"\n | \"lower_third\"\n | \"qr_code\"\n | \"coming_up_next\"\n | \"contextual_trigger\"\n | \"odds_betting\"\n | \"breaking_news\"\n | \"countdown\";\n\nexport interface SwirlOverlay {\n id: number;\n project_id: number;\n name: string;\n type: SwirlOverlayType | string;\n visible: boolean;\n x: number;\n y: number;\n width: number;\n height: number;\n opacity: number;\n start_time: string;\n duration: string;\n content?: string;\n image_url?: string;\n scroller_config?: SwirlScrollerConfig;\n z_index: number;\n created_at?: string;\n updated_at?: string;\n}\n\nexport function timeStringToSeconds(timeStr: string): number {\n if (!timeStr) return 0;\n\n const parts = timeStr.split(\":\");\n\n if (parts.length >= 3) {\n const hours = parseInt(parts[0] ?? \"0\", 10) || 0;\n const minutes = parseInt(parts[1] ?? \"0\", 10) || 0;\n const secStr = parts[2] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds =\n parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return hours * 3600 + minutes * 60 + seconds + ms / 1000;\n }\n\n if (parts.length === 2) {\n const minutes = parseInt(parts[0] ?? \"0\", 10) || 0;\n const secStr = parts[1] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds =\n parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return minutes * 60 + seconds + ms / 1000;\n }\n\n const num = parseFloat(timeStr);\n return isFinite(num) ? Math.max(0, num) : 0;\n}\n\nexport function isOverlayActive(\n overlay: SwirlOverlay,\n currentTime: number\n): boolean {\n if (!overlay.visible) return false;\n const startSec = timeStringToSeconds(overlay.start_time);\n const durationSec = timeStringToSeconds(overlay.duration);\n if (durationSec <= 0) return false;\n return currentTime >= startSec && currentTime < startSec + durationSec;\n}\n\nfunction normalizeScrollerConfig(\n raw: SwirlScrollerConfig | Record<string, unknown> | undefined\n): SwirlScrollerConfig | undefined {\n if (!raw || typeof raw !== \"object\") return undefined;\n const r = raw as Record<string, unknown>;\n const merged: SwirlScrollerConfig = { ...(raw as SwirlScrollerConfig) };\n if (merged.use_custom_text === undefined && typeof r.useCustomText === \"boolean\") {\n merged.use_custom_text = r.useCustomText;\n }\n if ((merged.custom_text === undefined || merged.custom_text === \"\") && typeof r.customText === \"string\") {\n merged.custom_text = r.customText;\n }\n if (!merged.rss_url && typeof r.rssUrl === \"string\") {\n merged.rss_url = r.rssUrl;\n }\n return merged;\n}\n\nexport function normalizeSwirlOverlay(raw: SwirlOverlay & Record<string, unknown>): SwirlOverlay {\n const o = { ...raw };\n if (o.type === \"scroller\") {\n const sc = raw.scroller_config ?? (raw as Record<string, unknown>).scrollerConfig;\n const normalized = normalizeScrollerConfig(sc as SwirlScrollerConfig);\n if (normalized) o.scroller_config = normalized;\n }\n return o;\n}\n\nexport async function fetchProjectOverlays(\n projectId: number,\n apiBaseUrl: string = OVERLAY_API_BASE\n): Promise<SwirlOverlay[]> {\n const base = apiBaseUrl.replace(/\\/$/, \"\");\n const response = await fetch(\n `${base}/adstorm/swirl/projects/${projectId}/overlays`\n );\n if (!response.ok) {\n throw new Error(\n `Failed to fetch overlays: ${response.status} ${response.statusText}`\n );\n }\n const data = await response.json();\n if (!Array.isArray(data)) return [];\n return data.map((row: SwirlOverlay & Record<string, unknown>) =>\n normalizeSwirlOverlay(row)\n );\n}\n\nexport function resolveImageUrl(\n imageUrl: string,\n apiBaseUrl: string = OVERLAY_API_BASE\n): string {\n if (!imageUrl) return \"\";\n if (imageUrl.startsWith(\"http://\") || imageUrl.startsWith(\"https://\")) {\n return imageUrl;\n }\n if (imageUrl.startsWith(\"/\")) {\n try {\n const url = new URL(apiBaseUrl);\n return `${url.origin}${imageUrl}`;\n } catch {\n return imageUrl;\n }\n }\n return `${apiBaseUrl}/${imageUrl}`;\n}\n"]}
1
+ {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/OverlayRenderer.cjs","../../src/ui/OverlayRenderer.tsx","../../src/utils/overlays.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","OverlayRenderer_exports","OverlayRenderer","module","exports","import_react","require","OVERLAY_API_BASE","timeStringToSeconds","timeStr","parts","split","length","hours","parseInt","minutes","secStr","dotIdx","indexOf","seconds","substring","msFrag","ms","padEnd","num","parseFloat","isFinite","Math","max","isOverlayActive","overlay","currentTime","visible","startSec","start_time","durationSec","duration","resolveImageUrl","imageUrl","apiBaseUrl","startsWith","url","URL","origin","import_jsx_runtime","computeVideoDimensions","video","nativeWidth","videoWidth","nativeHeight","videoHeight","displayWidth","offsetWidth","displayHeight","offsetHeight","videoAspect","displayAspect","renderWidth","renderHeight","offsetX","offsetY","image_url","jsx","src","pointerEvents","content","alignItems","justifyContent","fontSize","fontFamily","fontWeight","textAlign","boxSizing","wordBreak","textShadow","userSelect","lineHeight","text","parseRSSXml","xmlText","stripped","maxItems","replace","DOMParser","parseFromString","doc","querySelectorAll","map","item","querySelector","textContent","trim","description","pubDate","i","items","Map","cachedFetchRSSItems","rssUrl","rssCache","cached","expiresAt","now","promise","fetchRSSItems","catch","err","RSS_CACHE_TTL_MS","encoded","resp","data","window","location","fetch","ok","includes","json","contents","Error","scroller_config","useId","useState","rssItems","setRssItems","rssLoading","setRssLoading","rssError","setRssError","cfg","rss_url","max_items","auto_refresh","updateInterval","update_interval","useEffect","use_custom_text","custom_text","cancelled","finally","autoRefresh","interval","setInterval","delete","then","clearInterval","sep","separator_char","segments","show_title","title","push","show_description","show_timestamp","Date","toLocaleDateString","show_author","author","show_category","join","category","scrollSpeed","scroll_speed","font_size","font_family","font_weight","textColor","text_color","background_color","background_opacity","borderRadius","border_radius","itemSpacing","item_spacing","padding","label","labelLine2","label_line2","labelColor","label_color","accentColor","accent_color","showAccentLine","show_accent_line","isHorizontal","direction","isReverse","fullText","animId","uid","id","keyframes","jsxs","Fragment","children","style","width","height","display","flexDirection","overflow","backgroundColor","bgOpacity","hexToRgb","bgColor","color","isEquitiesStrip","background","flexShrink","flex","minHeight","pad","gap","round","labelTextColor","boxShadow","alignSelf","maxWidth","letterSpacing","textTransform","whiteSpace","opacity","position","minWidth","animation","willChange","copy","paddingRight","seg","React","margin","paddingBottom","parseConfig","JSON","parse","parseClockMMSS","clock","m","exec","formatClockMMSS","totalSec","s","floor","mm","ss","toString","padStart","useScoreBugClock","overlayId","sourceClock","initialSec","setNow","startRef","useRef","current","source","at","tick","elapsed","remaining","ScoreBugOverlay","size","liveClock","f","w","displayClock","displayPeriod","period","showMiddleCol","Boolean","homeTeam","marginTop","homeScore","textOverflow","awayTeam","awayScore","sponsorText","sponsorImageUrl","borderTop","alt","objectFit","LowerThirdOverlay","accentH","h","headline","subtitle","QrCodeOverlay","qrSide","min","qrUrl","encodeURIComponent"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/ui/OverlayRenderer.tsx\nvar OverlayRenderer_exports = {};\n__export(OverlayRenderer_exports, {\n OverlayRenderer: () => OverlayRenderer\n});\nmodule.exports = __toCommonJS(OverlayRenderer_exports);\nvar import_react = __toESM(require(\"react\"), 1);\n\n// src/utils/overlays.ts\nvar OVERLAY_API_BASE = \"https://adstorm.co/api-adstorm-dev\";\nfunction timeStringToSeconds(timeStr) {\n if (!timeStr) return 0;\n const parts = timeStr.split(\":\");\n if (parts.length >= 3) {\n const hours = parseInt(parts[0] ?? \"0\", 10) || 0;\n const minutes = parseInt(parts[1] ?? \"0\", 10) || 0;\n const secStr = parts[2] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds = parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return hours * 3600 + minutes * 60 + seconds + ms / 1e3;\n }\n if (parts.length === 2) {\n const minutes = parseInt(parts[0] ?? \"0\", 10) || 0;\n const secStr = parts[1] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds = parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return minutes * 60 + seconds + ms / 1e3;\n }\n const num = parseFloat(timeStr);\n return isFinite(num) ? Math.max(0, num) : 0;\n}\nfunction isOverlayActive(overlay, currentTime) {\n if (!overlay.visible) return false;\n const startSec = timeStringToSeconds(overlay.start_time);\n const durationSec = timeStringToSeconds(overlay.duration);\n if (durationSec <= 0) return false;\n return currentTime >= startSec && currentTime < startSec + durationSec;\n}\nfunction resolveImageUrl(imageUrl, apiBaseUrl = OVERLAY_API_BASE) {\n if (!imageUrl) return \"\";\n if (imageUrl.startsWith(\"http://\") || imageUrl.startsWith(\"https://\")) {\n return imageUrl;\n }\n if (imageUrl.startsWith(\"/\")) {\n try {\n const url = new URL(apiBaseUrl);\n return `${url.origin}${imageUrl}`;\n } catch {\n return imageUrl;\n }\n }\n return `${apiBaseUrl}/${imageUrl}`;\n}\n\n// src/ui/OverlayRenderer.tsx\nvar import_jsx_runtime = require(\"react/jsx-runtime\");\nfunction computeVideoDimensions(video) {\n const nativeWidth = video.videoWidth;\n const nativeHeight = video.videoHeight;\n if (!nativeWidth || !nativeHeight) return null;\n const displayWidth = video.offsetWidth;\n const displayHeight = video.offsetHeight;\n if (!displayWidth || !displayHeight) return null;\n const videoAspect = nativeWidth / nativeHeight;\n const displayAspect = displayWidth / displayHeight;\n let renderWidth;\n let renderHeight;\n let offsetX;\n let offsetY;\n if (videoAspect > displayAspect) {\n renderWidth = displayWidth;\n renderHeight = displayWidth / videoAspect;\n offsetX = 0;\n offsetY = (displayHeight - renderHeight) / 2;\n } else {\n renderHeight = displayHeight;\n renderWidth = displayHeight * videoAspect;\n offsetX = (displayWidth - renderWidth) / 2;\n offsetY = 0;\n }\n return {\n nativeWidth,\n nativeHeight,\n displayWidth: renderWidth,\n displayHeight: renderHeight,\n offsetX,\n offsetY,\n scaleX: renderWidth / nativeWidth,\n scaleY: renderHeight / nativeHeight\n };\n}\nfunction ImageOverlay({ overlay }) {\n const src = resolveImageUrl(overlay.image_url || \"\");\n if (!src) return null;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"img\",\n {\n src,\n alt: overlay.name,\n draggable: false,\n style: {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"contain\",\n display: \"block\",\n pointerEvents: \"none\",\n userSelect: \"none\"\n }\n }\n );\n}\nfunction TextOverlay({ overlay }) {\n const text = overlay.content || \"\";\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n fontSize: \"clamp(10px, 1.4vw, 20px)\",\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n fontWeight: 600,\n textAlign: \"center\",\n padding: \"4px 8px\",\n boxSizing: \"border-box\",\n wordBreak: \"break-word\",\n textShadow: \"0 1px 4px rgba(0,0,0,0.7)\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n lineHeight: 1.3\n },\n children: text\n }\n );\n}\nfunction parseRSSXml(xmlText, maxItems) {\n const stripped = xmlText.replace(/^<\\?xml[^?]*\\?>\\s*/, \"\");\n const parser = new DOMParser();\n const doc = parser.parseFromString(stripped, \"text/xml\");\n const items = Array.from(doc.querySelectorAll(\"item\")).map((item) => ({\n title: (item.querySelector(\"title\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n description: (item.querySelector(\"description\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n pubDate: item.querySelector(\"pubDate\")?.textContent || \"\",\n author: item.querySelector(\"author, dc\\\\:creator\")?.textContent || \"\",\n category: item.querySelector(\"category\")?.textContent || \"\"\n })).filter((i) => i.title).slice(0, maxItems);\n if (items.length === 0 && doc.querySelector(\"parsererror\")) {\n throw new Error(\"Invalid RSS XML\");\n }\n return items;\n}\nvar RSS_CACHE_TTL_MS = 6e4;\nvar rssCache = /* @__PURE__ */ new Map();\nfunction cachedFetchRSSItems(rssUrl, maxItems) {\n const now = Date.now();\n const cached = rssCache.get(rssUrl);\n if (cached && cached.expiresAt > now) return cached.promise;\n const promise = fetchRSSItems(rssUrl, maxItems).catch((err) => {\n rssCache.delete(rssUrl);\n throw err;\n });\n rssCache.set(rssUrl, { promise, expiresAt: now + RSS_CACHE_TTL_MS });\n return promise;\n}\nasync function fetchRSSItems(rssUrl, maxItems) {\n const encoded = encodeURIComponent(rssUrl);\n try {\n const origin = typeof window !== \"undefined\" ? window.location.origin : \"\";\n const resp = await fetch(`${origin}/api/rss-proxy?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text.includes(\"<item\")) return parseRSSXml(text, maxItems);\n }\n } catch {\n }\n try {\n const resp = await fetch(`https://api.allorigins.win/get?url=${encoded}`);\n if (resp.ok) {\n const data = await resp.json();\n if (data.contents) return parseRSSXml(data.contents, maxItems);\n }\n } catch {\n }\n try {\n const resp = await fetch(`https://corsproxy.io/?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text) return parseRSSXml(text, maxItems);\n }\n } catch {\n }\n throw new Error(\"All RSS proxies failed\");\n}\nfunction ScrollerOverlay({ overlay }) {\n const cfg = overlay.scroller_config;\n const uid = (0, import_react.useId)().replace(/:/g, \"\");\n const [rssItems, setRssItems] = (0, import_react.useState)([]);\n const [rssLoading, setRssLoading] = (0, import_react.useState)(true);\n const [rssError, setRssError] = (0, import_react.useState)(false);\n const rssUrl = cfg?.rss_url || \"\";\n const maxItems = cfg?.max_items ?? 10;\n const autoRefresh = cfg?.auto_refresh !== false;\n const updateInterval = cfg?.update_interval ?? 5;\n (0, import_react.useEffect)(() => {\n if (!rssUrl || cfg?.use_custom_text && cfg?.custom_text) {\n setRssLoading(false);\n return;\n }\n let cancelled = false;\n setRssLoading(true);\n setRssError(false);\n cachedFetchRSSItems(rssUrl, maxItems).then((items) => {\n if (!cancelled) {\n setRssItems(items);\n setRssError(false);\n }\n }).catch(() => {\n if (!cancelled) setRssError(true);\n }).finally(() => {\n if (!cancelled) setRssLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [rssUrl, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n (0, import_react.useEffect)(() => {\n if (!rssUrl || !autoRefresh || cfg?.use_custom_text && cfg?.custom_text) return;\n const interval = setInterval(() => {\n rssCache.delete(rssUrl);\n cachedFetchRSSItems(rssUrl, maxItems).then((items) => {\n setRssItems(items);\n setRssError(false);\n }).catch(() => {\n });\n }, updateInterval * 60 * 1e3);\n return () => clearInterval(interval);\n }, [rssUrl, autoRefresh, updateInterval, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n const sep = cfg?.separator_char ?? \"\\u25C6\";\n let segments;\n if (cfg?.use_custom_text && cfg?.custom_text) {\n segments = [cfg.custom_text];\n } else if (rssItems.length > 0) {\n segments = rssItems.map((item) => {\n const parts = [];\n if (cfg?.show_title !== false && item.title) parts.push(item.title);\n if (cfg?.show_description && item.description) parts.push(item.description);\n if (cfg?.show_timestamp && item.pubDate) {\n try {\n parts.push(new Date(item.pubDate).toLocaleDateString());\n } catch {\n }\n }\n if (cfg?.show_author && item.author) parts.push(`\\u2014 ${item.author}`);\n if (cfg?.show_category && item.category) parts.push(`[${item.category}]`);\n return parts.join(\" \");\n });\n } else if (rssLoading) {\n segments = [\"Loading feed\\u2026\"];\n } else if (rssError) {\n segments = overlay.content ? [overlay.content] : [\"RSS feed unavailable\"];\n } else if (overlay.content) {\n segments = [overlay.content];\n } else {\n segments = rssUrl ? [\"Loading feed\\u2026\"] : [\"RSS Ticker\"];\n }\n const scrollSpeed = cfg?.scroll_speed ?? 40;\n const direction = cfg?.direction ?? \"left\";\n const fontSize = cfg?.font_size ?? 15;\n const fontFamily = cfg?.font_family || \"Roboto, 'Segoe UI', Arial, sans-serif\";\n const fontWeight = cfg?.font_weight || \"700\";\n const textColor = cfg?.text_color || \"#ffffff\";\n const bgColor = cfg?.background_color || \"#0d0d1a\";\n const bgOpacity = cfg?.background_opacity !== void 0 ? cfg.background_opacity / 100 : 0.95;\n const borderRadius = cfg?.border_radius ?? 0;\n const itemSpacing = cfg?.item_spacing ?? 60;\n const pad = cfg?.padding !== void 0 && cfg.padding >= 0 ? cfg.padding : 8;\n const label = cfg?.label ?? \"NEWS\";\n const labelLine2 = cfg?.label_line2 ?? \"\";\n const labelColor = cfg?.label_color ?? \"#f97316\";\n const labelTextColor = cfg?.label_text_color ?? \"#ffffff\";\n const accentColor = cfg?.accent_color ?? labelColor;\n const showAccentLine = cfg?.show_accent_line !== false;\n const isEquitiesStrip = cfg?.preset === \"equities_strip\";\n const isHorizontal = direction === \"left\" || direction === \"right\";\n const isReverse = direction === \"right\" || direction === \"down\";\n const fullText = segments.join(` ${sep} `);\n const durationSec = Math.max(6, fullText.length * 9 / scrollSpeed);\n const animId = `sc-ticker-${overlay.id}-${uid}`;\n const keyframes = isHorizontal ? `@keyframes ${animId} {\n ${isReverse ? \"0% { transform: translateX(-50%); } 100% { transform: translateX(0%); }\" : \"0% { transform: translateX(0); } 100% { transform: translateX(-50%); }\"}\n }` : `@keyframes ${animId} {\n ${isReverse ? \"0% { transform: translateY(-50%); } 100% { transform: translateY(0%); }\" : \"0% { transform: translateY(0); } 100% { transform: translateY(-50%); }\"}\n }`;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: keyframes }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n borderRadius: borderRadius > 0 ? `${borderRadius}px` : void 0,\n backgroundColor: `rgba(${hexToRgb(bgColor)}, ${bgOpacity})`,\n fontFamily,\n fontSize: `${fontSize}px`,\n fontWeight,\n color: textColor,\n pointerEvents: \"none\",\n userSelect: \"none\"\n },\n children: [\n showAccentLine && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n height: isEquitiesStrip ? 2 : 3,\n background: accentColor,\n flexShrink: 0,\n width: \"100%\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n flex: 1,\n overflow: \"hidden\",\n minHeight: 0,\n alignItems: \"center\",\n padding: isEquitiesStrip ? `${Math.max(2, pad * 0.5)}px ${pad}px` : `${Math.max(4, pad * 0.75)}px ${pad}px`,\n gap: isEquitiesStrip ? Math.max(4, Math.round(pad * 0.75)) : Math.max(6, pad),\n boxSizing: \"border-box\"\n },\n children: [\n label && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n background: labelColor,\n color: labelTextColor,\n padding: isEquitiesStrip ? \"6px 12px\" : \"10px 14px\",\n display: \"flex\",\n flexDirection: isEquitiesStrip ? \"row\" : \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n textAlign: \"center\",\n gap: isEquitiesStrip ? 0 : 2,\n borderRadius: Math.max(2, borderRadius > 0 ? borderRadius : 6),\n boxShadow: isEquitiesStrip ? \"inset 0 1px 0 rgba(255,255,255,0.08)\" : \"0 2px 8px rgba(0,0,0,0.35)\",\n alignSelf: \"stretch\",\n maxWidth: isEquitiesStrip ? \"min(200px, 28%)\" : void 0\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"span\",\n {\n style: {\n fontWeight: isEquitiesStrip ? 700 : 800,\n fontSize: isEquitiesStrip ? \"0.82em\" : \"0.78em\",\n letterSpacing: isEquitiesStrip ? \"0.04em\" : \"0.08em\",\n lineHeight: 1.2,\n textTransform: isEquitiesStrip ? \"none\" : \"uppercase\",\n whiteSpace: isEquitiesStrip ? \"normal\" : \"nowrap\",\n textAlign: isEquitiesStrip ? \"left\" : \"center\"\n },\n children: label\n }\n ),\n labelLine2 && !isEquitiesStrip && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"span\",\n {\n style: {\n fontWeight: 600,\n fontSize: \"0.58em\",\n letterSpacing: \"0.06em\",\n lineHeight: 1.15,\n opacity: 0.92,\n whiteSpace: \"nowrap\"\n },\n children: labelLine2\n }\n )\n ]\n }\n ),\n label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: isEquitiesStrip ? 1 : 2,\n alignSelf: \"stretch\",\n minHeight: isEquitiesStrip ? 20 : 24,\n background: accentColor,\n flexShrink: 0,\n borderRadius: 1,\n opacity: 0.85\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n flex: 1,\n overflow: \"hidden\",\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n minWidth: 0\n },\n children: isHorizontal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n display: \"inline-flex\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\"\n },\n children: [0, 1].map((copy) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { paddingRight: `${itemSpacing}px` }, children: segments.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [\n i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { opacity: 0.5, margin: \"0 8px\" }, children: sep }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { textShadow: \"0 1px 3px rgba(0,0,0,0.6)\" }, children: seg })\n ] }, i)) }, copy))\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\"\n },\n children: [0, 1].map(\n (copy) => segments.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { paddingBottom: `${itemSpacing / 4}px` }, children: seg }, `${copy}-${i}`))\n )\n }\n )\n }\n )\n ]\n }\n )\n ]\n }\n )\n ] });\n}\nfunction parseConfig(content) {\n if (!content) return null;\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\nfunction parseClockMMSS(clock) {\n if (!clock) return null;\n const m = /^\\s*(\\d{1,3}):([0-5]?\\d)\\s*$/.exec(clock);\n if (!m) return null;\n return parseInt(m[1], 10) * 60 + parseInt(m[2], 10);\n}\nfunction formatClockMMSS(totalSec) {\n const s = Math.max(0, Math.floor(totalSec));\n const mm = Math.floor(s / 60);\n const ss = s % 60;\n return `${mm}:${ss.toString().padStart(2, \"0\")}`;\n}\nfunction useScoreBugClock(overlayId, sourceClock) {\n const initialSec = parseClockMMSS(sourceClock);\n const [now, setNow] = (0, import_react.useState)(() => Date.now());\n const startRef = (0, import_react.useRef)(null);\n (0, import_react.useEffect)(() => {\n if (initialSec === null) {\n startRef.current = null;\n return;\n }\n startRef.current = {\n id: overlayId,\n source: sourceClock || \"\",\n at: Date.now(),\n seconds: initialSec\n };\n setNow(Date.now());\n const tick = window.setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(tick);\n }, [overlayId, sourceClock, initialSec]);\n if (initialSec === null || !startRef.current) return null;\n const elapsed = Math.floor((now - startRef.current.at) / 1e3);\n const remaining = Math.max(0, startRef.current.seconds - elapsed);\n return formatClockMMSS(remaining);\n}\nfunction ScoreBugOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n const liveClock = useScoreBugClock(overlay.id, cfg?.clock);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n const displayClock = liveClock ?? cfg.clock ?? \"\";\n const displayPeriod = cfg.period ?? \"\";\n const showMiddleCol = Boolean(displayPeriod || displayClock);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.028),\n display: \"flex\",\n flexDirection: \"column\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 8px 28px rgba(0,0,0,0.45)\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n padding: `${f * 0.42}px ${f * 0.85}px`,\n gap: f * 0.45,\n minHeight: 0\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n },\n children: cfg.homeTeam\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }, children: cfg.homeScore })\n ] }),\n showMiddleCol && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"0.88em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.92,\n color: cfg.textColor,\n padding: `0 ${f * 0.5}px`,\n flexShrink: 0,\n lineHeight: 1.25,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\"\n },\n children: [\n displayPeriod && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { children: displayPeriod }),\n displayClock && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontWeight: 700, opacity: 1 }, children: displayClock })\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n },\n children: cfg.awayTeam\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }, children: cfg.awayScore })\n ] })\n ]\n }\n ),\n (cfg.sponsorText || cfg.sponsorImageUrl) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"0.72em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.88,\n padding: `${f * 0.34}px ${f * 0.55}px`,\n borderTop: `1px solid ${cfg.accentColor}55`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: f * 0.45,\n overflow: \"hidden\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n background: `linear-gradient(180deg, rgba(0,0,0,0.12) 0%, rgba(0,0,0,0.22) 100%)`\n },\n children: [\n cfg.sponsorImageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"img\", { src: cfg.sponsorImageUrl, alt: \"sponsor\", style: { height: `${f * 1.35}px`, objectFit: \"contain\", flexShrink: 0 } }),\n cfg.sponsorText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.sponsorText })\n ]\n }\n )\n ]\n }\n );\n}\nfunction LowerThirdOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.05);\n const accentH = Math.max(3, size.h * 0.038);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.018),\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"flex-end\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 10px 32px rgba(0,0,0,0.4)\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { width: \"100%\", height: accentH, backgroundColor: cfg.accentColor, flexShrink: 0 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: `${f * 0.62}px ${f * 1.05}px`,\n minHeight: 0,\n gap: f * 0.18\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"1.28em\",\n fontWeight: 800,\n lineHeight: 1.22,\n letterSpacing: \"0.01em\",\n textShadow: \"0 2px 6px rgba(0,0,0,0.55)\"\n },\n children: cfg.headline\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"0.94em\",\n fontWeight: 500,\n opacity: 0.92,\n lineHeight: 1.35,\n color: cfg.textColor\n },\n children: cfg.subtitle\n }\n )\n ]\n }\n ),\n (cfg.sponsorText || cfg.sponsorImageUrl) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"0.68em\",\n fontWeight: 600,\n opacity: 0.72,\n padding: `${f * 0.28}px ${f * 1.05}px ${f * 0.48}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: f * 0.4,\n overflow: \"hidden\",\n letterSpacing: \"0.06em\",\n textTransform: \"uppercase\",\n borderTop: `1px solid rgba(255,255,255,0.08)`\n },\n children: [\n cfg.sponsorImageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"img\", { src: cfg.sponsorImageUrl, alt: \"sponsor\", style: { height: `${f * 1.25}px`, objectFit: \"contain\", flexShrink: 0 } }),\n cfg.sponsorText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.sponsorText })\n ]\n }\n )\n ]\n }\n );\n}\nfunction QrCodeOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const qrSide = Math.max(32, Math.min(size.w, size.h) * 0.55);\n const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=${Math.round(qrSide * 2)}x${Math.round(qrSide * 2)}&data=${encodeURIComponent(cfg.url || \"https://example.com\")}`;\n const f = Math.max(6, size.w * 0.06);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", gap: f * 0.4, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", padding: f * 0.6, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", overflow: \"hidden\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { flexShrink: 0, background: \"#fff\", borderRadius: Math.max(2, qrSide * 0.06), padding: Math.max(2, qrSide * 0.06), lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"img\", { src: qrUrl, alt: \"QR Code\", style: { width: `${qrSide}px`, height: `${qrSide}px`, display: \"block\" } }) }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: `${f * 1.1}px`, fontWeight: 700, textAlign: \"center\", color: cfg.accentColor, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }, children: cfg.ctaText }),\n cfg.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: `${f * 0.75}px`, opacity: 0.6, textAlign: \"center\", overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }, children: cfg.description })\n ] });\n}\nfunction ComingUpNextOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const f = Math.max(8, Math.min(size.h * 0.13, size.w * 0.048));\n const showSubtitle = size.h >= 60;\n const showThumbnail = false;\n const thumbW = 0;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: {\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.025),\n display: \"flex\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Arial', 'Helvetica Neue', Helvetica, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n WebkitFontSmoothing: \"antialiased\"\n }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { width: Math.max(3, size.w * 0.018), flexShrink: 0, backgroundColor: cfg.accentColor } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: {\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: `${f * 0.35}px ${f * 0.75}px`,\n minWidth: 0,\n gap: `${f * 0.08}px`\n }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"0.7em\",\n fontWeight: 700,\n textTransform: \"uppercase\",\n letterSpacing: \"0.09em\",\n color: cfg.accentColor,\n lineHeight: 1\n }, children: \"Coming Up Next\" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"1.2em\",\n fontWeight: 700,\n lineHeight: 1.2,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n }, children: cfg.title }),\n showSubtitle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"0.82em\",\n opacity: 0.65,\n lineHeight: 1.1,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\"\n }, children: cfg.subtitle }),\n cfg.scheduledTime && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: {\n fontSize: \"0.9em\",\n fontWeight: 700,\n color: cfg.accentColor,\n lineHeight: 1\n }, children: cfg.scheduledTime })\n ] }),\n showThumbnail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { flexShrink: 0, width: `${thumbW}px`, overflow: \"hidden\" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"img\",\n {\n src: cfg.thumbnailUrl,\n alt: \"\",\n style: { width: \"100%\", height: \"100%\", objectFit: \"cover\", display: \"block\" }\n }\n ) })\n ] });\n}\nfunction ContextualTriggerOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const icons = { alert: \"\\u26A0\\uFE0F\", celebration: \"\\u{1F389}\", info: \"\\u2139\\uFE0F\", warning: \"\\u{1F514}\" };\n const f = Math.max(6, size.w * 0.05);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", alignItems: \"center\", gap: f * 0.8, padding: `0 ${f * 1.2}px`, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", borderLeft: `${Math.max(2, size.w * 0.02)}px solid ${cfg.accentColor}`, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { fontSize: \"2em\", flexShrink: 0 }, children: icons[cfg.iconType] || \"\\u26A1\" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, minWidth: 0 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.headline }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.message })\n ] })\n ] });\n}\nfunction OddsBettingOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.9em\", fontWeight: 700, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }, children: cfg.eventTitle }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { flex: 1, display: \"flex\", flexDirection: \"column\", gap: f * 0.2, justifyContent: \"center\" }, children: (cfg.options || []).slice(0, 5).map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", padding: `${f * 0.2}px ${f * 0.6}px`, borderRadius: Math.max(2, f * 0.3), background: `${cfg.accentColor}15`, fontSize: \"1em\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", flex: 1 }, children: opt.label }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { fontWeight: 700, marginLeft: f * 0.8, flexShrink: 0, color: cfg.accentColor }, children: opt.odds })\n ] }, i)) }),\n cfg.sponsorText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.7em\", opacity: 0.4, textAlign: \"center\", marginTop: f * 0.4 }, children: cfg.sponsorText })\n ] });\n}\nfunction BreakingNewsOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n if (!cfg) return null;\n const urgencyColors = { breaking: \"#dc2626\", urgent: \"#ea580c\", normal: \"#2563eb\" };\n const labelBg = urgencyColors[cfg.urgency] || urgencyColors.normal;\n const label = cfg.urgency === \"breaking\" ? \"BREAKING\" : cfg.urgency === \"urgent\" ? \"URGENT\" : \"NEWS\";\n const f = Math.max(6, size.w * 0.05);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.02), display: \"flex\", alignItems: \"center\", background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", overflow: \"hidden\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { padding: `0 ${f * 0.8}px`, height: \"100%\", display: \"flex\", alignItems: \"center\", background: labelBg, color: \"#fff\", fontSize: \"1em\", fontWeight: 900, textTransform: \"uppercase\", letterSpacing: \"0.05em\", flexShrink: 0 }, children: label }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { flex: 1, padding: `0 ${f * 1}px`, minWidth: 0 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.headline }),\n cfg.body && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }, children: cfg.body })\n ] })\n ] });\n}\nfunction calcCountdownRemaining(targetTime) {\n const diff = Math.max(0, new Date(targetTime).getTime() - Date.now());\n return {\n d: Math.floor(diff / 864e5),\n h: Math.floor(diff % 864e5 / 36e5),\n m: Math.floor(diff % 36e5 / 6e4),\n s: Math.floor(diff % 6e4 / 1e3),\n expired: diff === 0\n };\n}\nfunction CountdownOverlay({ overlay, size }) {\n const cfg = parseConfig(overlay.content);\n const targetTime = cfg?.targetTime ?? \"\";\n const [remaining, setRemaining] = (0, import_react.useState)(\n () => targetTime ? calcCountdownRemaining(targetTime) : { d: 0, h: 0, m: 0, s: 0, expired: false }\n );\n (0, import_react.useEffect)(() => {\n if (!targetTime) return;\n setRemaining(calcCountdownRemaining(targetTime));\n const id = setInterval(() => setRemaining(calcCountdownRemaining(targetTime)), 1e3);\n return () => clearInterval(id);\n }, [targetTime]);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.055);\n const pad = (n) => String(n).padStart(2, \"0\");\n const units = [\n { show: cfg.showDays, value: pad(remaining.d), label: \"DAYS\" },\n { show: cfg.showHours, value: pad(remaining.h), label: \"HRS\" },\n { show: cfg.showMinutes, value: pad(remaining.m), label: \"MIN\" },\n { show: cfg.showSeconds, value: pad(remaining.s), label: \"SEC\" }\n ];\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.8em\", fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }, children: cfg.eventName }),\n remaining.expired ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1em\", fontWeight: 700, opacity: 0.6 }, children: cfg.message || \"Event ended\" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { display: \"flex\", gap: f * 0.6, alignItems: \"center\" }, children: units.filter((u) => u.show).map((u, i, arr) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { textAlign: \"center\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"2em\", fontWeight: 900, lineHeight: 1, borderRadius: Math.max(2, f * 0.4), padding: `${f * 0.2}px ${f * 0.4}px`, background: `${cfg.accentColor}20` }, children: u.value }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.5em\", opacity: 0.5, marginTop: f * 0.2 }, children: u.label })\n ] }),\n i < arr.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"1.8em\", fontWeight: 700, opacity: 0.3 }, children: \":\" })\n ] }, u.label)) }),\n !remaining.expired && cfg.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"0.8em\", opacity: 0.6, marginTop: f * 0.4, textAlign: \"center\" }, children: cfg.message })\n ] });\n}\nfunction ShapeOverlay({ overlay, size }) {\n const f = Math.max(6, size.w * 0.05);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.03), background: \"rgba(99, 102, 241, 0.2)\", border: \"2px solid rgba(99, 102, 241, 0.4)\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\", pointerEvents: \"none\", userSelect: \"none\" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: `${f}px`, fontWeight: 500, color: \"rgba(163, 163, 163, 0.8)\", textTransform: \"uppercase\" }, children: overlay.name }) });\n}\nfunction hexToRgb(hex) {\n if (!hex || !hex.startsWith(\"#\")) return \"0,0,0\";\n const clean = hex.slice(1);\n const num = parseInt(clean.length === 3 ? clean.replace(/./g, \"$&$&\") : clean, 16);\n return `${num >> 16 & 255},${num >> 8 & 255},${num & 255}`;\n}\nvar FADE_DURATION_MS = 1e3;\nvar ENTER_ANIMATION_ALIASES = {\n fade: \"fade\",\n slide_from_left: \"slide_from_left\",\n slide_from_right: \"slide_from_right\",\n slide_from_top: \"slide_from_top\",\n slide_from_bottom: \"slide_from_bottom\",\n slide_left: \"slide_from_left\",\n slide_right: \"slide_from_right\",\n slide_up: \"slide_from_top\",\n slide_down: \"slide_from_bottom\"\n};\nfunction normalizeEnterAnimation(v) {\n if (typeof v !== \"string\") return null;\n return ENTER_ANIMATION_ALIASES[v] ?? null;\n}\nfunction getEnterAnimation(overlay) {\n const flat = overlay.enter_animation;\n const fromFlat = normalizeEnterAnimation(flat);\n if (fromFlat) return fromFlat;\n if (overlay.content) {\n try {\n const parsed = JSON.parse(overlay.content);\n const fromContent = normalizeEnterAnimation(parsed?.enterAnimation);\n if (fromContent) return fromContent;\n } catch {\n }\n }\n return \"fade\";\n}\nfunction enterHiddenTransform(anim) {\n switch (anim) {\n case \"slide_from_left\":\n return \"translateX(-120%)\";\n case \"slide_from_right\":\n return \"translateX(120%)\";\n case \"slide_from_top\":\n return \"translateY(-120%)\";\n case \"slide_from_bottom\":\n return \"translateY(120%)\";\n default:\n return \"\";\n }\n}\nvar SHOWCASE_CYCLE_MS_DEFAULT = 36e3;\nvar SHOWCASE_MIN_BEAT_MS = 6e3;\nvar BEAT_POP_IN_MS = 520;\nvar BEAT_POP_OUT_MS = 520;\nvar SHOWCASE_PERSISTENT_TYPES = /* @__PURE__ */ new Set([\n \"scroller\",\n \"breaking_news\",\n \"image\",\n \"text\",\n \"shape\",\n \"countdown\",\n \"qr_code\",\n \"coming_up_next\",\n \"score_bug\"\n]);\nfunction easeOutCubic(t) {\n const u = 1 - t;\n return 1 - u * u * u;\n}\nfunction easeInCubic(t) {\n return t * t * t;\n}\nfunction easeOutBack(t) {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n return 1 + c3 * (t - 1) ** 3 + c1 * (t - 1) ** 2;\n}\nfunction beatOpacity(phase, beatMs) {\n if (phase < BEAT_POP_IN_MS) return easeOutCubic(phase / BEAT_POP_IN_MS);\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return Math.max(\n 0,\n 1 - easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS)\n );\n }\n return 1;\n}\nfunction beatScale(phase, beatMs) {\n if (phase < BEAT_POP_IN_MS) {\n return Math.min(1, 0.92 + 0.08 * easeOutBack(phase / BEAT_POP_IN_MS));\n }\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return 1 - 0.06 * easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS);\n }\n return 1;\n}\nfunction partitionShowcase(overlays) {\n const visible = overlays.filter((o) => o.visible);\n const persistent = [];\n const spotlight = [];\n for (const o of visible) {\n if (SHOWCASE_PERSISTENT_TYPES.has(o.type)) persistent.push(o);\n else spotlight.push(o);\n }\n spotlight.sort(\n (a, b) => a.z_index - b.z_index || a.id - b.id\n );\n const beats = [];\n for (const o of spotlight) beats.push([o]);\n return { persistent, beats };\n}\nfunction useShowcaseBeat(enabled, cycleMs, beats) {\n const safeBeats = Math.max(1, beats);\n const beatMs = Math.max(\n SHOWCASE_MIN_BEAT_MS,\n Math.floor(cycleMs / safeBeats)\n );\n const totalMs = beatMs * safeBeats;\n const [now, setNow] = (0, import_react.useState)(() => Date.now());\n (0, import_react.useEffect)(() => {\n if (!enabled) return;\n const id = window.setInterval(() => setNow(Date.now()), 64);\n return () => clearInterval(id);\n }, [enabled]);\n const phase = now % totalMs;\n const beatIndex = Math.min(safeBeats - 1, Math.floor(phase / beatMs));\n const beatPhase = phase - beatIndex * beatMs;\n return { beatIndex, beatPhase, beatMs };\n}\nvar OverlayRenderer = ({\n overlays,\n currentTime,\n videoRef,\n coordinateSpace,\n showcaseMode = false,\n showcaseCycleMs = SHOWCASE_CYCLE_MS_DEFAULT\n}) => {\n const [dims, setDims] = (0, import_react.useState)(null);\n const rafRef = (0, import_react.useRef)(null);\n const [fadeMap, setFadeMap] = (0, import_react.useState)(/* @__PURE__ */ new Map());\n const removeTimers = (0, import_react.useRef)(/* @__PURE__ */ new Map());\n const mountTimeRef = (0, import_react.useRef)(Date.now());\n const [wallclockSec, setWallclockSec] = (0, import_react.useState)(0);\n (0, import_react.useEffect)(() => {\n if (!showcaseMode) return;\n const tick = () => setWallclockSec((Date.now() - mountTimeRef.current) / 1e3);\n tick();\n const id = window.setInterval(tick, 200);\n return () => clearInterval(id);\n }, [showcaseMode]);\n const { persistent: showcasePersistent, beats: showcaseBeats } = (0, import_react.useMemo)(\n () => partitionShowcase(overlays),\n [overlays]\n );\n const {\n beatIndex: showcaseBeatIndex,\n beatPhase: showcaseBeatPhase,\n beatMs: showcaseBeatMs\n } = useShowcaseBeat(showcaseMode, showcaseCycleMs, showcaseBeats.length);\n const showcasePersistentIds = (0, import_react.useMemo)(\n () => new Set(showcasePersistent.map((o) => o.id)),\n [showcasePersistent]\n );\n const showcaseSpotlightIds = (0, import_react.useMemo)(() => {\n const beat = showcaseBeats[showcaseBeatIndex];\n return new Set((beat ?? []).map((o) => o.id));\n }, [showcaseBeats, showcaseBeatIndex]);\n const updateDims = (0, import_react.useCallback)(() => {\n const video = videoRef.current;\n if (video) {\n const computed = computeVideoDimensions(video);\n setDims((prev) => {\n if (!computed || prev && prev.nativeWidth === computed.nativeWidth && prev.nativeHeight === computed.nativeHeight && prev.displayWidth === computed.displayWidth && prev.displayHeight === computed.displayHeight && prev.offsetX === computed.offsetX && prev.offsetY === computed.offsetY) {\n return prev;\n }\n return computed;\n });\n }\n }, [videoRef]);\n (0, import_react.useEffect)(() => {\n updateDims();\n const interval = setInterval(updateDims, 500);\n const handleResize = () => {\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(updateDims);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => {\n clearInterval(interval);\n window.removeEventListener(\"resize\", handleResize);\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n };\n }, [updateDims]);\n const activeOverlays = (0, import_react.useMemo)(() => {\n if (showcaseMode) {\n const beat = showcaseBeats[showcaseBeatIndex] ?? [];\n const scheduledPersistent = showcasePersistent.filter(\n (o) => isOverlayActive(o, wallclockSec)\n );\n return [...scheduledPersistent, ...beat];\n }\n return overlays.filter((o) => isOverlayActive(o, currentTime));\n }, [\n overlays,\n currentTime,\n wallclockSec,\n showcaseMode,\n showcasePersistent,\n showcaseBeats,\n showcaseBeatIndex\n ]);\n (0, import_react.useLayoutEffect)(() => {\n const activeIds = new Set(activeOverlays.map((o) => o.id));\n setFadeMap((prev) => {\n const next = new Map(prev);\n for (const overlay of activeOverlays) {\n if (!next.has(overlay.id)) {\n next.set(overlay.id, { overlay, visible: false });\n } else {\n const existing = next.get(overlay.id);\n next.set(overlay.id, { ...existing, overlay });\n }\n }\n for (const [id, state] of next) {\n if (!activeIds.has(id) && state.visible) {\n next.set(id, { ...state, visible: false });\n if (!removeTimers.current.has(id)) {\n const timer = setTimeout(() => {\n setFadeMap((m) => {\n const updated = new Map(m);\n updated.delete(id);\n return updated;\n });\n removeTimers.current.delete(id);\n }, FADE_DURATION_MS);\n removeTimers.current.set(id, timer);\n }\n } else if (!activeIds.has(id) && !state.visible) {\n }\n }\n return next;\n });\n }, [activeOverlays]);\n (0, import_react.useEffect)(() => {\n const toFadeIn = [];\n for (const [id, state] of fadeMap) {\n if (!state.visible) {\n const isActive = activeOverlays.some((o) => o.id === id);\n if (isActive) toFadeIn.push(id);\n }\n }\n if (toFadeIn.length === 0) return;\n const raf = requestAnimationFrame(() => {\n setFadeMap((prev) => {\n const next = new Map(prev);\n for (const id of toFadeIn) {\n const state = next.get(id);\n if (state) next.set(id, { ...state, visible: true });\n }\n return next;\n });\n });\n return () => cancelAnimationFrame(raf);\n }, [fadeMap, activeOverlays]);\n (0, import_react.useEffect)(() => {\n return () => {\n for (const timer of removeTimers.current.values()) clearTimeout(timer);\n };\n }, []);\n if (!dims || fadeMap.size === 0) return null;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n \"aria-hidden\": \"true\",\n style: {\n position: \"absolute\",\n left: `${dims.offsetX}px`,\n top: `${dims.offsetY}px`,\n width: `${dims.displayWidth}px`,\n height: `${dims.displayHeight}px`,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n zIndex: 8\n },\n children: [...fadeMap.values()].map(({ overlay, visible }) => {\n const scaleX = coordinateSpace?.width ? dims.displayWidth / coordinateSpace.width : dims.scaleX;\n const scaleY = coordinateSpace?.height ? dims.displayHeight / coordinateSpace.height : dims.scaleY;\n const left = overlay.x * scaleX;\n const top = overlay.y * scaleY;\n const width = overlay.width * scaleX;\n const height = overlay.height * scaleY;\n const baseOpacity = Math.max(0, Math.min(100, overlay.opacity)) / 100;\n const isShowcasePersistent = showcaseMode && showcasePersistentIds.has(overlay.id);\n const isShowcaseSpotlight = showcaseMode && showcaseSpotlightIds.has(overlay.id);\n const isShowcaseDormant = showcaseMode && !isShowcasePersistent && !isShowcaseSpotlight;\n const useShowcasePop = isShowcaseSpotlight;\n const opacity = useShowcasePop ? baseOpacity * beatOpacity(showcaseBeatPhase, showcaseBeatMs) : isShowcaseDormant ? 0 : visible ? baseOpacity : 0;\n const popScale = useShowcasePop ? beatScale(showcaseBeatPhase, showcaseBeatMs) : 1;\n const sz = { w: width, h: height };\n const enterAnim = getEnterAnimation(overlay);\n const hasSlide = enterAnim !== \"fade\" && !useShowcasePop;\n const slideTransform = hasSlide && !visible ? enterHiddenTransform(enterAnim) : \"\";\n const popTransform = showcaseMode && useShowcasePop ? `scale(${popScale})` : \"\";\n const combinedTransform = [slideTransform, popTransform].filter(Boolean).join(\" \");\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n opacity,\n transition: useShowcasePop ? \"none\" : hasSlide ? `opacity ${FADE_DURATION_MS}ms ease, transform ${FADE_DURATION_MS}ms cubic-bezier(0.22, 1, 0.36, 1)` : `opacity ${FADE_DURATION_MS}ms ease`,\n transform: combinedTransform || void 0,\n transformOrigin: showcaseMode && useShowcasePop ? \"center center\" : void 0,\n zIndex: overlay.z_index,\n overflow: \"hidden\"\n },\n children: [\n overlay.type === \"image\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageOverlay, { overlay }),\n overlay.type === \"text\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextOverlay, { overlay }),\n overlay.type === \"scroller\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollerOverlay, { overlay }),\n overlay.type === \"shape\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShapeOverlay, { overlay, size: sz }),\n overlay.type === \"score_bug\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScoreBugOverlay, { overlay, size: sz }),\n overlay.type === \"lower_third\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LowerThirdOverlay, { overlay, size: sz }),\n overlay.type === \"qr_code\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(QrCodeOverlay, { overlay, size: sz }),\n overlay.type === \"coming_up_next\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComingUpNextOverlay, { overlay, size: sz }),\n overlay.type === \"contextual_trigger\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextualTriggerOverlay, { overlay, size: sz }),\n overlay.type === \"odds_betting\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OddsBettingOverlay, { overlay, size: sz }),\n overlay.type === \"breaking_news\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BreakingNewsOverlay, { overlay, size: sz }),\n overlay.type === \"countdown\" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CountdownOverlay, { overlay, size: sz })\n ]\n },\n overlay.id\n );\n })\n }\n );\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n OverlayRenderer\n});\n","import React, {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useCallback,\n useMemo,\n useId,\n} from \"react\";\nimport {\n type SwirlOverlay,\n isOverlayActive,\n resolveImageUrl,\n} from \"../utils/overlays\";\n\ninterface VideoDimensions {\n nativeWidth: number;\n nativeHeight: number;\n displayWidth: number;\n displayHeight: number;\n offsetX: number;\n offsetY: number;\n scaleX: number;\n scaleY: number;\n}\n\ninterface OverlayRendererProps {\n overlays: SwirlOverlay[];\n currentTime: number;\n videoRef: React.RefObject<HTMLVideoElement | null>;\n coordinateSpace?: { width: number; height: number } | null;\n showcaseMode?: boolean;\n showcaseCycleMs?: number;\n}\n\nfunction computeVideoDimensions(\n video: HTMLVideoElement\n): VideoDimensions | null {\n const nativeWidth = video.videoWidth;\n const nativeHeight = video.videoHeight;\n if (!nativeWidth || !nativeHeight) return null;\n\n const displayWidth = video.offsetWidth;\n const displayHeight = video.offsetHeight;\n if (!displayWidth || !displayHeight) return null;\n\n const videoAspect = nativeWidth / nativeHeight;\n const displayAspect = displayWidth / displayHeight;\n\n let renderWidth: number;\n let renderHeight: number;\n let offsetX: number;\n let offsetY: number;\n\n if (videoAspect > displayAspect) {\n renderWidth = displayWidth;\n renderHeight = displayWidth / videoAspect;\n offsetX = 0;\n offsetY = (displayHeight - renderHeight) / 2;\n } else {\n renderHeight = displayHeight;\n renderWidth = displayHeight * videoAspect;\n offsetX = (displayWidth - renderWidth) / 2;\n offsetY = 0;\n }\n\n return {\n nativeWidth,\n nativeHeight,\n displayWidth: renderWidth,\n displayHeight: renderHeight,\n offsetX,\n offsetY,\n scaleX: renderWidth / nativeWidth,\n scaleY: renderHeight / nativeHeight,\n };\n}\n\nfunction ImageOverlay({ overlay }: { overlay: SwirlOverlay }) {\n const src = resolveImageUrl(overlay.image_url || \"\");\n if (!src) return null;\n return (\n <img\n src={src}\n alt={overlay.name}\n draggable={false}\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: \"contain\",\n display: \"block\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n );\n}\n\nfunction TextOverlay({ overlay }: { overlay: SwirlOverlay }) {\n const text = overlay.content || \"\";\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n fontSize: \"clamp(10px, 1.4vw, 20px)\",\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n fontWeight: 600,\n textAlign: \"center\",\n padding: \"4px 8px\",\n boxSizing: \"border-box\",\n wordBreak: \"break-word\",\n textShadow: \"0 1px 4px rgba(0,0,0,0.7)\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n lineHeight: 1.3,\n }}\n >\n {text}\n </div>\n );\n}\n\ninterface RSSItem {\n title: string;\n description: string;\n pubDate: string;\n author: string;\n category: string;\n}\n\nfunction parseRSSXml(xmlText: string, maxItems: number): RSSItem[] {\n const stripped = xmlText.replace(/^<\\?xml[^?]*\\?>\\s*/, \"\");\n const parser = new DOMParser();\n const doc = parser.parseFromString(stripped, \"text/xml\");\n const items = Array.from(doc.querySelectorAll(\"item\"))\n .map((item) => ({\n title: (item.querySelector(\"title\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n description: (item.querySelector(\"description\")?.textContent || \"\").replace(/<[^>]*>/g, \"\").trim(),\n pubDate: item.querySelector(\"pubDate\")?.textContent || \"\",\n author: item.querySelector(\"author, dc\\\\:creator\")?.textContent || \"\",\n category: item.querySelector(\"category\")?.textContent || \"\",\n }))\n .filter((i) => i.title)\n .slice(0, maxItems);\n if (items.length === 0 && doc.querySelector(\"parsererror\")) {\n throw new Error(\"Invalid RSS XML\");\n }\n return items;\n}\n\nconst RSS_CACHE_TTL_MS = 60_000;\nconst rssCache = new Map<string, { promise: Promise<RSSItem[]>; expiresAt: number }>();\n\nfunction cachedFetchRSSItems(rssUrl: string, maxItems: number): Promise<RSSItem[]> {\n const now = Date.now();\n const cached = rssCache.get(rssUrl);\n if (cached && cached.expiresAt > now) return cached.promise;\n const promise = fetchRSSItems(rssUrl, maxItems).catch((err) => {\n rssCache.delete(rssUrl);\n throw err;\n });\n rssCache.set(rssUrl, { promise, expiresAt: now + RSS_CACHE_TTL_MS });\n return promise;\n}\n\nasync function fetchRSSItems(rssUrl: string, maxItems: number): Promise<RSSItem[]> {\n const encoded = encodeURIComponent(rssUrl);\n\n try {\n const origin = typeof window !== \"undefined\" ? window.location.origin : \"\";\n const resp = await fetch(`${origin}/api/rss-proxy?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text.includes(\"<item\")) return parseRSSXml(text, maxItems);\n }\n } catch { /* fall through */ }\n\n try {\n const resp = await fetch(`https://api.allorigins.win/get?url=${encoded}`);\n if (resp.ok) {\n const data = await resp.json();\n if (data.contents) return parseRSSXml(data.contents, maxItems);\n }\n } catch { /* fall through */ }\n\n try {\n const resp = await fetch(`https://corsproxy.io/?url=${encoded}`);\n if (resp.ok) {\n const text = await resp.text();\n if (text) return parseRSSXml(text, maxItems);\n }\n } catch { /* fall through */ }\n\n throw new Error(\"All RSS proxies failed\");\n}\n\nfunction ScrollerOverlay({ overlay }: { overlay: SwirlOverlay }) {\n const cfg = overlay.scroller_config;\n const uid = useId().replace(/:/g, \"\");\n\n const [rssItems, setRssItems] = useState<RSSItem[]>([]);\n const [rssLoading, setRssLoading] = useState(true);\n const [rssError, setRssError] = useState(false);\n\n const rssUrl = cfg?.rss_url || \"\";\n const maxItems = cfg?.max_items ?? 10;\n const autoRefresh = cfg?.auto_refresh !== false;\n const updateInterval = cfg?.update_interval ?? 5;\n\n useEffect(() => {\n if (!rssUrl || (cfg?.use_custom_text && cfg?.custom_text)) {\n setRssLoading(false);\n return;\n }\n let cancelled = false;\n setRssLoading(true);\n setRssError(false);\n cachedFetchRSSItems(rssUrl, maxItems)\n .then((items) => { if (!cancelled) { setRssItems(items); setRssError(false); } })\n .catch(() => { if (!cancelled) setRssError(true); })\n .finally(() => { if (!cancelled) setRssLoading(false); });\n return () => { cancelled = true; };\n }, [rssUrl, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n\n useEffect(() => {\n if (!rssUrl || !autoRefresh || (cfg?.use_custom_text && cfg?.custom_text)) return;\n const interval = setInterval(() => {\n rssCache.delete(rssUrl);\n cachedFetchRSSItems(rssUrl, maxItems)\n .then((items) => { setRssItems(items); setRssError(false); })\n .catch(() => { /* keep showing last good items */ });\n }, updateInterval * 60 * 1000);\n return () => clearInterval(interval);\n }, [rssUrl, autoRefresh, updateInterval, maxItems, cfg?.use_custom_text, cfg?.custom_text]);\n\n const sep = cfg?.separator_char ?? \"◆\";\n\n let segments: string[];\n if (cfg?.use_custom_text && cfg?.custom_text) {\n segments = [cfg.custom_text];\n } else if (rssItems.length > 0) {\n segments = rssItems.map((item) => {\n const parts: string[] = [];\n if (cfg?.show_title !== false && item.title) parts.push(item.title);\n if (cfg?.show_description && item.description) parts.push(item.description);\n if (cfg?.show_timestamp && item.pubDate) {\n try { parts.push(new Date(item.pubDate).toLocaleDateString()); } catch { /* ignore */ }\n }\n if (cfg?.show_author && item.author) parts.push(`— ${item.author}`);\n if (cfg?.show_category && item.category) parts.push(`[${item.category}]`);\n return parts.join(\" \");\n });\n } else if (rssLoading) {\n segments = [\"Loading feed…\"];\n } else if (rssError) {\n segments = overlay.content ? [overlay.content] : [\"RSS feed unavailable\"];\n } else if (overlay.content) {\n segments = [overlay.content];\n } else {\n segments = rssUrl ? [\"Loading feed…\"] : [\"RSS Ticker\"];\n }\n\n const scrollSpeed = cfg?.scroll_speed ?? 40;\n const direction = cfg?.direction ?? \"left\";\n const fontSize = cfg?.font_size ?? 15;\n const fontFamily = cfg?.font_family || \"Roboto, 'Segoe UI', Arial, sans-serif\";\n const fontWeight = cfg?.font_weight || \"700\";\n const textColor = cfg?.text_color || \"#ffffff\";\n const bgColor = cfg?.background_color || \"#0d0d1a\";\n const bgOpacity = cfg?.background_opacity !== undefined ? cfg.background_opacity / 100 : 0.95;\n const borderRadius = cfg?.border_radius ?? 0;\n const itemSpacing = cfg?.item_spacing ?? 60;\n const pad = cfg?.padding !== undefined && cfg.padding >= 0 ? cfg.padding : 8;\n\n const label = cfg?.label ?? \"NEWS\";\n const labelLine2 = cfg?.label_line2 ?? \"\";\n const labelColor = cfg?.label_color ?? \"#f97316\";\n const labelTextColor = cfg?.label_text_color ?? \"#ffffff\";\n const accentColor = cfg?.accent_color ?? labelColor;\n const showAccentLine = cfg?.show_accent_line !== false;\n const isEquitiesStrip = cfg?.preset === \"equities_strip\";\n\n const isHorizontal = direction === \"left\" || direction === \"right\";\n const isReverse = direction === \"right\" || direction === \"down\";\n\n const fullText = segments.join(` ${sep} `);\n const durationSec = Math.max(6, (fullText.length * 9) / scrollSpeed);\n\n const animId = `sc-ticker-${overlay.id}-${uid}`;\n const keyframes = isHorizontal\n ? `@keyframes ${animId} {\n ${isReverse\n ? \"0% { transform: translateX(-50%); } 100% { transform: translateX(0%); }\"\n : \"0% { transform: translateX(0); } 100% { transform: translateX(-50%); }\"}\n }`\n : `@keyframes ${animId} {\n ${isReverse\n ? \"0% { transform: translateY(-50%); } 100% { transform: translateY(0%); }\"\n : \"0% { transform: translateY(0); } 100% { transform: translateY(-50%); }\"}\n }`;\n\n return (\n <>\n <style>{keyframes}</style>\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n borderRadius: borderRadius > 0 ? `${borderRadius}px` : undefined,\n backgroundColor: `rgba(${hexToRgb(bgColor)}, ${bgOpacity})`,\n fontFamily,\n fontSize: `${fontSize}px`,\n fontWeight,\n color: textColor,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n >\n {showAccentLine && (\n <div\n style={{\n height: isEquitiesStrip ? 2 : 3,\n background: accentColor,\n flexShrink: 0,\n width: \"100%\",\n }}\n />\n )}\n\n <div\n style={{\n display: \"flex\",\n flex: 1,\n overflow: \"hidden\",\n minHeight: 0,\n alignItems: \"center\",\n padding: isEquitiesStrip\n ? `${Math.max(2, pad * 0.5)}px ${pad}px`\n : `${Math.max(4, pad * 0.75)}px ${pad}px`,\n gap: isEquitiesStrip ? Math.max(4, Math.round(pad * 0.75)) : Math.max(6, pad),\n boxSizing: \"border-box\",\n }}\n >\n {label && (\n <div\n style={{\n background: labelColor,\n color: labelTextColor,\n padding: isEquitiesStrip ? \"6px 12px\" : \"10px 14px\",\n display: \"flex\",\n flexDirection: isEquitiesStrip ? \"row\" : \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n textAlign: \"center\",\n gap: isEquitiesStrip ? 0 : 2,\n borderRadius: Math.max(2, borderRadius > 0 ? borderRadius : 6),\n boxShadow: isEquitiesStrip\n ? \"inset 0 1px 0 rgba(255,255,255,0.08)\"\n : \"0 2px 8px rgba(0,0,0,0.35)\",\n alignSelf: \"stretch\",\n maxWidth: isEquitiesStrip ? \"min(200px, 28%)\" : undefined,\n }}\n >\n <span\n style={{\n fontWeight: isEquitiesStrip ? 700 : 800,\n fontSize: isEquitiesStrip ? \"0.82em\" : \"0.78em\",\n letterSpacing: isEquitiesStrip ? \"0.04em\" : \"0.08em\",\n lineHeight: 1.2,\n textTransform: isEquitiesStrip ? \"none\" : \"uppercase\",\n whiteSpace: isEquitiesStrip ? \"normal\" : \"nowrap\",\n textAlign: isEquitiesStrip ? \"left\" : \"center\",\n }}\n >\n {label}\n </span>\n {labelLine2 && !isEquitiesStrip && (\n <span\n style={{\n fontWeight: 600,\n fontSize: \"0.58em\",\n letterSpacing: \"0.06em\",\n lineHeight: 1.15,\n opacity: 0.92,\n whiteSpace: \"nowrap\",\n }}\n >\n {labelLine2}\n </span>\n )}\n </div>\n )}\n\n {label && (\n <div\n style={{\n width: isEquitiesStrip ? 1 : 2,\n alignSelf: \"stretch\",\n minHeight: isEquitiesStrip ? 20 : 24,\n background: accentColor,\n flexShrink: 0,\n borderRadius: 1,\n opacity: 0.85,\n }}\n />\n )}\n\n <div\n style={{\n flex: 1,\n overflow: \"hidden\",\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n minWidth: 0,\n }}\n >\n {isHorizontal ? (\n <div\n style={{\n display: \"inline-flex\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\",\n }}\n >\n {[0, 1].map((copy) => (\n <span key={copy} style={{ paddingRight: `${itemSpacing}px` }}>\n {segments.map((seg, i) => (\n <React.Fragment key={i}>\n {i > 0 && (\n <span style={{ opacity: 0.5, margin: \"0 8px\" }}>{sep}</span>\n )}\n <span style={{ textShadow: \"0 1px 3px rgba(0,0,0,0.6)\" }}>{seg}</span>\n </React.Fragment>\n ))}\n </span>\n ))}\n </div>\n ) : (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n whiteSpace: \"nowrap\",\n animation: `${animId} ${durationSec}s linear infinite`,\n willChange: \"transform\",\n }}\n >\n {[0, 1].map((copy) =>\n segments.map((seg, i) => (\n <div key={`${copy}-${i}`} style={{ paddingBottom: `${itemSpacing / 4}px` }}>\n {seg}\n </div>\n ))\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n\nfunction parseConfig<T>(content?: string): T | null {\n if (!content) return null;\n try { return JSON.parse(content) as T; } catch { return null; }\n}\n\ninterface OverlaySize { w: number; h: number; }\n\ninterface ScoreBugCfg { homeTeam: string; awayTeam: string; homeScore: number; awayScore: number; period: string; clock: string; sponsorText: string; sponsorImageUrl: string; backgroundColor: string; textColor: string; accentColor: string; }\ninterface LowerThirdCfg { headline: string; subtitle: string; sponsorText: string; sponsorImageUrl: string; backgroundColor: string; textColor: string; accentColor: string; style: string; }\ninterface QrCodeCfg { url: string; ctaText: string; description: string; size: number; backgroundColor: string; textColor: string; accentColor: string; }\ninterface ComingUpNextCfg { title: string; subtitle: string; scheduledTime: string; thumbnailUrl: string; backgroundColor: string; textColor: string; accentColor: string; }\ninterface ContextualTriggerCfg { triggerType: string; headline: string; message: string; iconType: string; backgroundColor: string; textColor: string; accentColor: string; animationStyle: string; }\ninterface OddsBettingCfg { eventTitle: string; options: Array<{ label: string; odds: string }>; sponsorText: string; backgroundColor: string; textColor: string; accentColor: string; oddsFormat: string; }\ninterface BreakingNewsCfg { headline: string; body: string; urgency: string; backgroundColor: string; textColor: string; accentColor: string; }\ninterface CountdownCfg { eventName: string; targetTime: string; message: string; showDays: boolean; showHours: boolean; showMinutes: boolean; showSeconds: boolean; backgroundColor: string; textColor: string; accentColor: string; }\n\nfunction parseClockMMSS(clock: string | undefined): number | null {\n if (!clock) return null;\n const m = /^\\s*(\\d{1,3}):([0-5]?\\d)\\s*$/.exec(clock);\n if (!m) return null;\n return parseInt(m[1]!, 10) * 60 + parseInt(m[2]!, 10);\n}\n\nfunction formatClockMMSS(totalSec: number): string {\n const s = Math.max(0, Math.floor(totalSec));\n const mm = Math.floor(s / 60);\n const ss = s % 60;\n return `${mm}:${ss.toString().padStart(2, \"0\")}`;\n}\n\nfunction useScoreBugClock(overlayId: number, sourceClock: string | undefined): string | null {\n const initialSec = parseClockMMSS(sourceClock);\n const [now, setNow] = useState<number>(() => Date.now());\n const startRef = useRef<{ id: number; source: string; at: number; seconds: number } | null>(null);\n\n useEffect(() => {\n if (initialSec === null) {\n startRef.current = null;\n return;\n }\n startRef.current = {\n id: overlayId,\n source: sourceClock || \"\",\n at: Date.now(),\n seconds: initialSec,\n };\n setNow(Date.now());\n const tick = window.setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(tick);\n }, [overlayId, sourceClock, initialSec]);\n\n if (initialSec === null || !startRef.current) return null;\n const elapsed = Math.floor((now - startRef.current.at) / 1000);\n const remaining = Math.max(0, startRef.current.seconds - elapsed);\n return formatClockMMSS(remaining);\n}\n\nfunction ScoreBugOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<ScoreBugCfg>(overlay.content);\n const liveClock = useScoreBugClock(overlay.id, cfg?.clock);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n const displayClock = liveClock ?? cfg.clock ?? \"\";\n const displayPeriod = cfg.period ?? \"\";\n const showMiddleCol = Boolean(displayPeriod || displayClock);\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.028),\n display: \"flex\",\n flexDirection: \"column\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 8px 28px rgba(0,0,0,0.45)\",\n }}\n >\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n padding: `${f * 0.42}px ${f * 0.85}px`,\n gap: f * 0.45,\n minHeight: 0,\n }}\n >\n <div style={{ flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }}>\n <div\n style={{\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {cfg.homeTeam}\n </div>\n <div style={{ fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }}>\n {cfg.homeScore}\n </div>\n </div>\n {showMiddleCol && (\n <div\n style={{\n fontSize: \"0.88em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.92,\n color: cfg.textColor,\n padding: `0 ${f * 0.5}px`,\n flexShrink: 0,\n lineHeight: 1.25,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n }}\n >\n {displayPeriod && <div>{displayPeriod}</div>}\n {displayClock && (\n <div style={{ fontWeight: 700, opacity: 1 }}>{displayClock}</div>\n )}\n </div>\n )}\n <div style={{ flex: 1, textAlign: \"center\", minWidth: 0, padding: `0 ${f * 0.15}px` }}>\n <div\n style={{\n fontSize: \"1.05em\",\n fontWeight: 800,\n letterSpacing: \"0.02em\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {cfg.awayTeam}\n </div>\n <div style={{ fontSize: \"1.75em\", fontWeight: 900, lineHeight: 1.05, marginTop: f * 0.08 }}>\n {cfg.awayScore}\n </div>\n </div>\n </div>\n {(cfg.sponsorText || cfg.sponsorImageUrl) && (\n <div\n style={{\n fontSize: \"0.72em\",\n textAlign: \"center\",\n fontWeight: 600,\n opacity: 0.88,\n padding: `${f * 0.34}px ${f * 0.55}px`,\n borderTop: `1px solid ${cfg.accentColor}55`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: f * 0.45,\n overflow: \"hidden\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n background: `linear-gradient(180deg, rgba(0,0,0,0.12) 0%, rgba(0,0,0,0.22) 100%)`,\n }}\n >\n {cfg.sponsorImageUrl && (\n <img src={cfg.sponsorImageUrl} alt=\"sponsor\" style={{ height: `${f * 1.35}px`, objectFit: \"contain\", flexShrink: 0 }} />\n )}\n {cfg.sponsorText && (\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.sponsorText}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction LowerThirdOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<LowerThirdCfg>(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.05);\n const accentH = Math.max(3, size.h * 0.038);\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.018),\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"flex-end\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Inter', 'Roboto', 'Segoe UI', system-ui, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n fontSize: `${f}px`,\n boxShadow: \"0 10px 32px rgba(0,0,0,0.4)\",\n }}\n >\n <div style={{ width: \"100%\", height: accentH, backgroundColor: cfg.accentColor, flexShrink: 0 }} />\n <div\n style={{\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: `${f * 0.62}px ${f * 1.05}px`,\n minHeight: 0,\n gap: f * 0.18,\n }}\n >\n <div\n style={{\n fontSize: \"1.28em\",\n fontWeight: 800,\n lineHeight: 1.22,\n letterSpacing: \"0.01em\",\n textShadow: \"0 2px 6px rgba(0,0,0,0.55)\",\n }}\n >\n {cfg.headline}\n </div>\n <div\n style={{\n fontSize: \"0.94em\",\n fontWeight: 500,\n opacity: 0.92,\n lineHeight: 1.35,\n color: cfg.textColor,\n }}\n >\n {cfg.subtitle}\n </div>\n </div>\n {(cfg.sponsorText || cfg.sponsorImageUrl) && (\n <div\n style={{\n fontSize: \"0.68em\",\n fontWeight: 600,\n opacity: 0.72,\n padding: `${f * 0.28}px ${f * 1.05}px ${f * 0.48}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: f * 0.4,\n overflow: \"hidden\",\n letterSpacing: \"0.06em\",\n textTransform: \"uppercase\",\n borderTop: `1px solid rgba(255,255,255,0.08)`,\n }}\n >\n {cfg.sponsorImageUrl && (\n <img src={cfg.sponsorImageUrl} alt=\"sponsor\" style={{ height: `${f * 1.25}px`, objectFit: \"contain\", flexShrink: 0 }} />\n )}\n {cfg.sponsorText && (\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.sponsorText}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction QrCodeOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<QrCodeCfg>(overlay.content);\n if (!cfg) return null;\n const qrSide = Math.max(32, Math.min(size.w, size.h) * 0.55);\n const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=${Math.round(qrSide * 2)}x${Math.round(qrSide * 2)}&data=${encodeURIComponent(cfg.url || \"https://example.com\")}`;\n const f = Math.max(6, size.w * 0.06);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", gap: f * 0.4, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", padding: f * 0.6, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", overflow: \"hidden\" }}>\n <div style={{ flexShrink: 0, background: \"#fff\", borderRadius: Math.max(2, qrSide * 0.06), padding: Math.max(2, qrSide * 0.06), lineHeight: 0 }}>\n <img src={qrUrl} alt=\"QR Code\" style={{ width: `${qrSide}px`, height: `${qrSide}px`, display: \"block\" }} />\n </div>\n <div style={{ fontSize: `${f * 1.1}px`, fontWeight: 700, textAlign: \"center\", color: cfg.accentColor, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }}>{cfg.ctaText}</div>\n {cfg.description && <div style={{ fontSize: `${f * 0.75}px`, opacity: 0.6, textAlign: \"center\", overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", width: \"100%\" }}>{cfg.description}</div>}\n </div>\n );\n}\n\nfunction ComingUpNextOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<ComingUpNextCfg>(overlay.content);\n if (!cfg) return null;\n const f = Math.max(8, Math.min(size.h * 0.13, size.w * 0.048));\n const showSubtitle = size.h >= 60;\n const showThumbnail = false;\n const thumbW = 0;\n return (\n <div style={{\n width: \"100%\", height: \"100%\",\n borderRadius: Math.max(2, size.w * 0.025),\n display: \"flex\",\n background: cfg.backgroundColor,\n color: cfg.textColor,\n fontFamily: \"'Arial', 'Helvetica Neue', Helvetica, sans-serif\",\n overflow: \"hidden\",\n pointerEvents: \"none\", userSelect: \"none\",\n fontSize: `${f}px`,\n WebkitFontSmoothing: \"antialiased\",\n } as React.CSSProperties}>\n <div style={{ width: Math.max(3, size.w * 0.018), flexShrink: 0, backgroundColor: cfg.accentColor }} />\n <div style={{\n flex: 1, display: \"flex\", flexDirection: \"column\", justifyContent: \"center\",\n padding: `${f * 0.35}px ${f * 0.75}px`,\n minWidth: 0, gap: `${f * 0.08}px`,\n }}>\n <div style={{\n fontSize: \"0.7em\", fontWeight: 700,\n textTransform: \"uppercase\", letterSpacing: \"0.09em\",\n color: cfg.accentColor, lineHeight: 1,\n }}>\n Coming Up Next\n </div>\n <div style={{\n fontSize: \"1.2em\", fontWeight: 700, lineHeight: 1.2,\n overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\",\n }}>\n {cfg.title}\n </div>\n {showSubtitle && (\n <div style={{\n fontSize: \"0.82em\", opacity: 0.65, lineHeight: 1.1,\n overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\",\n }}>\n {cfg.subtitle}\n </div>\n )}\n {cfg.scheduledTime && (\n <div style={{\n fontSize: \"0.9em\", fontWeight: 700,\n color: cfg.accentColor, lineHeight: 1,\n }}>\n {cfg.scheduledTime}\n </div>\n )}\n </div>\n {showThumbnail && (\n <div style={{ flexShrink: 0, width: `${thumbW}px`, overflow: \"hidden\" }}>\n <img\n src={cfg.thumbnailUrl}\n alt=\"\"\n style={{ width: \"100%\", height: \"100%\", objectFit: \"cover\", display: \"block\" }}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction ContextualTriggerOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<ContextualTriggerCfg>(overlay.content);\n if (!cfg) return null;\n const icons: Record<string, string> = { alert: \"\\u26A0\\uFE0F\", celebration: \"\\uD83C\\uDF89\", info: \"\\u2139\\uFE0F\", warning: \"\\uD83D\\uDD14\" };\n const f = Math.max(6, size.w * 0.05);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", alignItems: \"center\", gap: f * 0.8, padding: `0 ${f * 1.2}px`, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", borderLeft: `${Math.max(2, size.w * 0.02)}px solid ${cfg.accentColor}`, boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <span style={{ fontSize: \"2em\", flexShrink: 0 }}>{icons[cfg.iconType] || \"\\u26A1\"}</span>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.headline}</div>\n <div style={{ fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.message}</div>\n </div>\n </div>\n );\n}\n\nfunction OddsBettingOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<OddsBettingCfg>(overlay.content);\n if (!cfg) return null;\n const f = Math.max(6, size.w * 0.052);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <div style={{ fontSize: \"0.9em\", fontWeight: 700, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }}>{cfg.eventTitle}</div>\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\", gap: f * 0.2, justifyContent: \"center\" }}>\n {(cfg.options || []).slice(0, 5).map((opt, i) => (\n <div key={i} style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", padding: `${f * 0.2}px ${f * 0.6}px`, borderRadius: Math.max(2, f * 0.3), background: `${cfg.accentColor}15`, fontSize: \"1em\" }}>\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\", flex: 1 }}>{opt.label}</span>\n <span style={{ fontWeight: 700, marginLeft: f * 0.8, flexShrink: 0, color: cfg.accentColor }}>{opt.odds}</span>\n </div>\n ))}\n </div>\n {cfg.sponsorText && <div style={{ fontSize: \"0.7em\", opacity: 0.4, textAlign: \"center\", marginTop: f * 0.4 }}>{cfg.sponsorText}</div>}\n </div>\n );\n}\n\nfunction BreakingNewsOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<BreakingNewsCfg>(overlay.content);\n if (!cfg) return null;\n const urgencyColors: Record<string, string> = { breaking: \"#dc2626\", urgent: \"#ea580c\", normal: \"#2563eb\" };\n const labelBg = urgencyColors[cfg.urgency] || urgencyColors.normal;\n const label = cfg.urgency === \"breaking\" ? \"BREAKING\" : cfg.urgency === \"urgent\" ? \"URGENT\" : \"NEWS\";\n const f = Math.max(6, size.w * 0.05);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.02), display: \"flex\", alignItems: \"center\", background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", overflow: \"hidden\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <div style={{ padding: `0 ${f * 0.8}px`, height: \"100%\", display: \"flex\", alignItems: \"center\", background: labelBg, color: \"#fff\", fontSize: \"1em\", fontWeight: 900, textTransform: \"uppercase\", letterSpacing: \"0.05em\", flexShrink: 0 }}>{label}</div>\n <div style={{ flex: 1, padding: `0 ${f * 1.0}px`, minWidth: 0 }}>\n <div style={{ fontSize: \"1.3em\", fontWeight: 700, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.headline}</div>\n {cfg.body && <div style={{ fontSize: \"0.9em\", opacity: 0.7, overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>{cfg.body}</div>}\n </div>\n </div>\n );\n}\n\nfunction calcCountdownRemaining(targetTime: string) {\n const diff = Math.max(0, new Date(targetTime).getTime() - Date.now());\n return {\n d: Math.floor(diff / 86400000),\n h: Math.floor((diff % 86400000) / 3600000),\n m: Math.floor((diff % 3600000) / 60000),\n s: Math.floor((diff % 60000) / 1000),\n expired: diff === 0,\n };\n}\n\nfunction CountdownOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const cfg = parseConfig<CountdownCfg>(overlay.content);\n const targetTime = cfg?.targetTime ?? \"\";\n const [remaining, setRemaining] = useState(() =>\n targetTime ? calcCountdownRemaining(targetTime) : { d: 0, h: 0, m: 0, s: 0, expired: false }\n );\n\n useEffect(() => {\n if (!targetTime) return;\n setRemaining(calcCountdownRemaining(targetTime));\n const id = setInterval(() => setRemaining(calcCountdownRemaining(targetTime)), 1000);\n return () => clearInterval(id);\n }, [targetTime]);\n\n if (!cfg) return null;\n\n const f = Math.max(6, size.w * 0.055);\n const pad = (n: number) => String(n).padStart(2, \"0\");\n const units: Array<{ show: boolean; value: string; label: string }> = [\n { show: cfg.showDays, value: pad(remaining.d), label: \"DAYS\" },\n { show: cfg.showHours, value: pad(remaining.h), label: \"HRS\" },\n { show: cfg.showMinutes, value: pad(remaining.m), label: \"MIN\" },\n { show: cfg.showSeconds, value: pad(remaining.s), label: \"SEC\" },\n ];\n\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.035), display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\", padding: f * 0.8, background: cfg.backgroundColor, color: cfg.textColor, fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\", boxSizing: \"border-box\", pointerEvents: \"none\", userSelect: \"none\", fontSize: `${f}px` }}>\n <div style={{ fontSize: \"0.8em\", fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.05em\", color: cfg.accentColor, marginBottom: f * 0.4 }}>{cfg.eventName}</div>\n {remaining.expired ? (\n <div style={{ fontSize: \"1em\", fontWeight: 700, opacity: 0.6 }}>{cfg.message || \"Event ended\"}</div>\n ) : (\n <div style={{ display: \"flex\", gap: f * 0.6, alignItems: \"center\" }}>\n {units.filter(u => u.show).map((u, i, arr) => (\n <React.Fragment key={u.label}>\n <div style={{ textAlign: \"center\" }}>\n <div style={{ fontSize: \"2em\", fontWeight: 900, lineHeight: 1, borderRadius: Math.max(2, f * 0.4), padding: `${f * 0.2}px ${f * 0.4}px`, background: `${cfg.accentColor}20` }}>{u.value}</div>\n <div style={{ fontSize: \"0.5em\", opacity: 0.5, marginTop: f * 0.2 }}>{u.label}</div>\n </div>\n {i < arr.length - 1 && <div style={{ fontSize: \"1.8em\", fontWeight: 700, opacity: 0.3 }}>:</div>}\n </React.Fragment>\n ))}\n </div>\n )}\n {!remaining.expired && cfg.message && <div style={{ fontSize: \"0.8em\", opacity: 0.6, marginTop: f * 0.4, textAlign: \"center\" }}>{cfg.message}</div>}\n </div>\n );\n}\n\nfunction ShapeOverlay({ overlay, size }: { overlay: SwirlOverlay; size: OverlaySize }) {\n const f = Math.max(6, size.w * 0.05);\n return (\n <div style={{ width: \"100%\", height: \"100%\", borderRadius: Math.max(2, size.w * 0.03), background: \"rgba(99, 102, 241, 0.2)\", border: \"2px solid rgba(99, 102, 241, 0.4)\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\", pointerEvents: \"none\", userSelect: \"none\" }}>\n <div style={{ fontSize: `${f}px`, fontWeight: 500, color: \"rgba(163, 163, 163, 0.8)\", textTransform: \"uppercase\" }}>{overlay.name}</div>\n </div>\n );\n}\n\nfunction hexToRgb(hex: string): string {\n if (!hex || !hex.startsWith(\"#\")) return \"0,0,0\";\n const clean = hex.slice(1);\n const num = parseInt(clean.length === 3 ? clean.replace(/./g, \"$&$&\") : clean, 16);\n return `${(num >> 16) & 255},${(num >> 8) & 255},${num & 255}`;\n}\n\ninterface OverlayFadeState {\n overlay: SwirlOverlay;\n visible: boolean;\n}\n\nconst FADE_DURATION_MS = 1000;\n\ntype EnterAnimation =\n | \"fade\"\n | \"slide_from_left\"\n | \"slide_from_right\"\n | \"slide_from_top\"\n | \"slide_from_bottom\";\n\nconst ENTER_ANIMATION_ALIASES: Record<string, EnterAnimation> = {\n fade: \"fade\",\n slide_from_left: \"slide_from_left\",\n slide_from_right: \"slide_from_right\",\n slide_from_top: \"slide_from_top\",\n slide_from_bottom: \"slide_from_bottom\",\n slide_left: \"slide_from_left\",\n slide_right: \"slide_from_right\",\n slide_up: \"slide_from_top\",\n slide_down: \"slide_from_bottom\",\n};\n\nfunction normalizeEnterAnimation(v: unknown): EnterAnimation | null {\n if (typeof v !== \"string\") return null;\n return ENTER_ANIMATION_ALIASES[v] ?? null;\n}\n\nfunction getEnterAnimation(overlay: SwirlOverlay): EnterAnimation {\n const flat = (overlay as unknown as { enter_animation?: unknown })\n .enter_animation;\n const fromFlat = normalizeEnterAnimation(flat);\n if (fromFlat) return fromFlat;\n if (overlay.content) {\n try {\n const parsed = JSON.parse(overlay.content) as Record<string, unknown>;\n const fromContent = normalizeEnterAnimation(parsed?.enterAnimation);\n if (fromContent) return fromContent;\n } catch {\n // ignore malformed content\n }\n }\n return \"fade\";\n}\n\nfunction enterHiddenTransform(anim: EnterAnimation): string {\n switch (anim) {\n case \"slide_from_left\":\n return \"translateX(-120%)\";\n case \"slide_from_right\":\n return \"translateX(120%)\";\n case \"slide_from_top\":\n return \"translateY(-120%)\";\n case \"slide_from_bottom\":\n return \"translateY(120%)\";\n default:\n return \"\";\n }\n}\n\nconst SHOWCASE_CYCLE_MS_DEFAULT = 36_000;\nconst SHOWCASE_MIN_BEAT_MS = 6_000;\nconst BEAT_POP_IN_MS = 520;\nconst BEAT_POP_OUT_MS = 520;\n\nconst SHOWCASE_PERSISTENT_TYPES: ReadonlySet<string> = new Set([\n \"scroller\",\n \"breaking_news\",\n \"image\",\n \"text\",\n \"shape\",\n \"countdown\",\n \"qr_code\",\n \"coming_up_next\",\n \"score_bug\",\n]);\n\nfunction easeOutCubic(t: number): number {\n const u = 1 - t;\n return 1 - u * u * u;\n}\n\nfunction easeInCubic(t: number): number {\n return t * t * t;\n}\n\nfunction easeOutBack(t: number): number {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n return 1 + c3 * (t - 1) ** 3 + c1 * (t - 1) ** 2;\n}\n\nfunction beatOpacity(phase: number, beatMs: number): number {\n if (phase < BEAT_POP_IN_MS) return easeOutCubic(phase / BEAT_POP_IN_MS);\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return Math.max(\n 0,\n 1 - easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS)\n );\n }\n return 1;\n}\n\nfunction beatScale(phase: number, beatMs: number): number {\n if (phase < BEAT_POP_IN_MS) {\n return Math.min(1, 0.92 + 0.08 * easeOutBack(phase / BEAT_POP_IN_MS));\n }\n const holdEnd = beatMs - BEAT_POP_OUT_MS;\n if (phase >= holdEnd) {\n return 1 - 0.06 * easeInCubic((phase - holdEnd) / BEAT_POP_OUT_MS);\n }\n return 1;\n}\n\nfunction partitionShowcase(overlays: SwirlOverlay[]): {\n persistent: SwirlOverlay[];\n beats: SwirlOverlay[][];\n} {\n const visible = overlays.filter((o) => o.visible);\n const persistent: SwirlOverlay[] = [];\n const spotlight: SwirlOverlay[] = [];\n for (const o of visible) {\n if (SHOWCASE_PERSISTENT_TYPES.has(o.type)) persistent.push(o);\n else spotlight.push(o);\n }\n spotlight.sort(\n (a, b) => (a.z_index - b.z_index) || (a.id - b.id)\n );\n const beats: SwirlOverlay[][] = [];\n for (const o of spotlight) beats.push([o]);\n return { persistent, beats };\n}\n\nfunction useShowcaseBeat(\n enabled: boolean,\n cycleMs: number,\n beats: number\n): { beatIndex: number; beatPhase: number; beatMs: number } {\n const safeBeats = Math.max(1, beats);\n const beatMs = Math.max(\n SHOWCASE_MIN_BEAT_MS,\n Math.floor(cycleMs / safeBeats)\n );\n const totalMs = beatMs * safeBeats;\n const [now, setNow] = useState<number>(() => Date.now());\n useEffect(() => {\n if (!enabled) return;\n const id = window.setInterval(() => setNow(Date.now()), 64);\n return () => clearInterval(id);\n }, [enabled]);\n const phase = now % totalMs;\n const beatIndex = Math.min(safeBeats - 1, Math.floor(phase / beatMs));\n const beatPhase = phase - beatIndex * beatMs;\n return { beatIndex, beatPhase, beatMs };\n}\n\nexport const OverlayRenderer: React.FC<OverlayRendererProps> = ({\n overlays,\n currentTime,\n videoRef,\n coordinateSpace,\n showcaseMode = false,\n showcaseCycleMs = SHOWCASE_CYCLE_MS_DEFAULT,\n}) => {\n const [dims, setDims] = useState<VideoDimensions | null>(null);\n const rafRef = useRef<number | null>(null);\n const [fadeMap, setFadeMap] = useState<Map<number, OverlayFadeState>>(new Map());\n const removeTimers = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());\n\n const mountTimeRef = useRef<number>(Date.now());\n const [wallclockSec, setWallclockSec] = useState<number>(0);\n useEffect(() => {\n if (!showcaseMode) return;\n const tick = () =>\n setWallclockSec((Date.now() - mountTimeRef.current) / 1000);\n tick();\n const id = window.setInterval(tick, 200);\n return () => clearInterval(id);\n }, [showcaseMode]);\n\n const { persistent: showcasePersistent, beats: showcaseBeats } = useMemo(\n () => partitionShowcase(overlays),\n [overlays]\n );\n const {\n beatIndex: showcaseBeatIndex,\n beatPhase: showcaseBeatPhase,\n beatMs: showcaseBeatMs,\n } = useShowcaseBeat(showcaseMode, showcaseCycleMs, showcaseBeats.length);\n\n const showcasePersistentIds = useMemo(\n () => new Set(showcasePersistent.map((o) => o.id)),\n [showcasePersistent]\n );\n const showcaseSpotlightIds = useMemo(() => {\n const beat = showcaseBeats[showcaseBeatIndex];\n return new Set((beat ?? []).map((o) => o.id));\n }, [showcaseBeats, showcaseBeatIndex]);\n\n const updateDims = useCallback(() => {\n const video = videoRef.current;\n if (video) {\n const computed = computeVideoDimensions(video);\n setDims((prev) => {\n if (\n !computed ||\n (prev &&\n prev.nativeWidth === computed.nativeWidth &&\n prev.nativeHeight === computed.nativeHeight &&\n prev.displayWidth === computed.displayWidth &&\n prev.displayHeight === computed.displayHeight &&\n prev.offsetX === computed.offsetX &&\n prev.offsetY === computed.offsetY)\n ) {\n return prev;\n }\n return computed;\n });\n }\n }, [videoRef]);\n\n useEffect(() => {\n updateDims();\n const interval = setInterval(updateDims, 500);\n\n const handleResize = () => {\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(updateDims);\n };\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n clearInterval(interval);\n window.removeEventListener(\"resize\", handleResize);\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n };\n }, [updateDims]);\n\n const activeOverlays = useMemo(() => {\n if (showcaseMode) {\n const beat = showcaseBeats[showcaseBeatIndex] ?? [];\n const scheduledPersistent = showcasePersistent.filter((o) =>\n isOverlayActive(o, wallclockSec)\n );\n return [...scheduledPersistent, ...beat];\n }\n return overlays.filter((o) => isOverlayActive(o, currentTime));\n }, [\n overlays,\n currentTime,\n wallclockSec,\n showcaseMode,\n showcasePersistent,\n showcaseBeats,\n showcaseBeatIndex,\n ]);\n\n useLayoutEffect(() => {\n const activeIds = new Set(activeOverlays.map((o) => o.id));\n\n setFadeMap((prev) => {\n const next = new Map(prev);\n\n for (const overlay of activeOverlays) {\n if (!next.has(overlay.id)) {\n next.set(overlay.id, { overlay, visible: false });\n } else {\n const existing = next.get(overlay.id)!;\n next.set(overlay.id, { ...existing, overlay });\n }\n }\n\n for (const [id, state] of next) {\n if (!activeIds.has(id) && state.visible) {\n next.set(id, { ...state, visible: false });\n if (!removeTimers.current.has(id)) {\n const timer = setTimeout(() => {\n setFadeMap((m) => {\n const updated = new Map(m);\n updated.delete(id);\n return updated;\n });\n removeTimers.current.delete(id);\n }, FADE_DURATION_MS);\n removeTimers.current.set(id, timer);\n }\n } else if (!activeIds.has(id) && !state.visible) {\n }\n }\n\n return next;\n });\n }, [activeOverlays]);\n\n useEffect(() => {\n const toFadeIn: number[] = [];\n for (const [id, state] of fadeMap) {\n if (!state.visible) {\n const isActive = activeOverlays.some((o) => o.id === id);\n if (isActive) toFadeIn.push(id);\n }\n }\n if (toFadeIn.length === 0) return;\n\n const raf = requestAnimationFrame(() => {\n setFadeMap((prev) => {\n const next = new Map(prev);\n for (const id of toFadeIn) {\n const state = next.get(id);\n if (state) next.set(id, { ...state, visible: true });\n }\n return next;\n });\n });\n return () => cancelAnimationFrame(raf);\n }, [fadeMap, activeOverlays]);\n\n useEffect(() => {\n return () => {\n for (const timer of removeTimers.current.values()) clearTimeout(timer);\n };\n }, []);\n\n if (!dims || fadeMap.size === 0) return null;\n\n return (\n <div\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n left: `${dims.offsetX}px`,\n top: `${dims.offsetY}px`,\n width: `${dims.displayWidth}px`,\n height: `${dims.displayHeight}px`,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n zIndex: 8,\n }}\n >\n {[...fadeMap.values()].map(({ overlay, visible }) => {\n const scaleX = coordinateSpace?.width\n ? dims.displayWidth / coordinateSpace.width\n : dims.scaleX;\n const scaleY = coordinateSpace?.height\n ? dims.displayHeight / coordinateSpace.height\n : dims.scaleY;\n const left = overlay.x * scaleX;\n const top = overlay.y * scaleY;\n const width = overlay.width * scaleX;\n const height = overlay.height * scaleY;\n const baseOpacity = Math.max(0, Math.min(100, overlay.opacity)) / 100;\n const isShowcasePersistent =\n showcaseMode && showcasePersistentIds.has(overlay.id);\n const isShowcaseSpotlight =\n showcaseMode && showcaseSpotlightIds.has(overlay.id);\n\n const isShowcaseDormant =\n showcaseMode && !isShowcasePersistent && !isShowcaseSpotlight;\n const useShowcasePop = isShowcaseSpotlight;\n const opacity = useShowcasePop\n ? baseOpacity *\n beatOpacity(showcaseBeatPhase, showcaseBeatMs)\n : isShowcaseDormant\n ? 0\n : visible\n ? baseOpacity\n : 0;\n const popScale = useShowcasePop\n ? beatScale(showcaseBeatPhase, showcaseBeatMs)\n : 1;\n const sz: OverlaySize = { w: width, h: height };\n\n const enterAnim = getEnterAnimation(overlay);\n const hasSlide = enterAnim !== \"fade\" && !useShowcasePop;\n const slideTransform = hasSlide && !visible\n ? enterHiddenTransform(enterAnim)\n : \"\";\n const popTransform = showcaseMode && useShowcasePop\n ? `scale(${popScale})`\n : \"\";\n const combinedTransform = [slideTransform, popTransform]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n key={overlay.id}\n style={{\n position: \"absolute\",\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n opacity,\n transition: useShowcasePop\n ? \"none\"\n : hasSlide\n ? `opacity ${FADE_DURATION_MS}ms ease, transform ${FADE_DURATION_MS}ms cubic-bezier(0.22, 1, 0.36, 1)`\n : `opacity ${FADE_DURATION_MS}ms ease`,\n transform: combinedTransform || undefined,\n transformOrigin: showcaseMode && useShowcasePop ? \"center center\" : undefined,\n zIndex: overlay.z_index,\n overflow: \"hidden\",\n }}\n >\n {overlay.type === \"image\" && <ImageOverlay overlay={overlay} />}\n {overlay.type === \"text\" && <TextOverlay overlay={overlay} />}\n {overlay.type === \"scroller\" && <ScrollerOverlay overlay={overlay} />}\n {overlay.type === \"shape\" && <ShapeOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"score_bug\" && <ScoreBugOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"lower_third\" && <LowerThirdOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"qr_code\" && <QrCodeOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"coming_up_next\" && <ComingUpNextOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"contextual_trigger\" && <ContextualTriggerOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"odds_betting\" && <OddsBettingOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"breaking_news\" && <BreakingNewsOverlay overlay={overlay} size={sz} />}\n {overlay.type === \"countdown\" && <CountdownOverlay overlay={overlay} size={sz} />}\n </div>\n );\n })}\n </div>\n );\n};\n","export const OVERLAY_API_BASE = \"https://adstorm.co/api-adstorm-dev\";\n\nexport interface OverlayCoordinateSpace {\n width: number;\n height: number;\n}\n\nexport interface SwirlScrollerConfig {\n rss_url?: string;\n update_interval?: number;\n scroll_speed?: number;\n direction?: string;\n font_size?: number;\n font_family?: string;\n font_weight?: string;\n text_color?: string;\n background_color?: string;\n background_opacity?: number;\n border_color?: string;\n border_width?: number;\n border_radius?: number;\n padding?: number;\n margin?: number;\n show_title?: boolean;\n show_description?: boolean;\n show_timestamp?: boolean;\n show_author?: boolean;\n show_category?: boolean;\n max_items?: number;\n item_spacing?: number;\n fade_in_out?: boolean;\n fade_distance?: number;\n auto_refresh?: boolean;\n use_custom_text?: boolean;\n custom_text?: string;\n label?: string;\n label_line2?: string;\n label_color?: string;\n label_text_color?: string;\n accent_color?: string;\n show_accent_line?: boolean;\n separator_char?: string;\n preset?: string;\n}\n\nexport type SwirlOverlayType =\n | \"image\"\n | \"text\"\n | \"scroller\"\n | \"shape\"\n | \"score_bug\"\n | \"lower_third\"\n | \"qr_code\"\n | \"coming_up_next\"\n | \"contextual_trigger\"\n | \"odds_betting\"\n | \"breaking_news\"\n | \"countdown\";\n\nexport interface SwirlOverlay {\n id: number;\n project_id: number;\n name: string;\n type: SwirlOverlayType | string;\n visible: boolean;\n x: number;\n y: number;\n width: number;\n height: number;\n opacity: number;\n start_time: string;\n duration: string;\n content?: string;\n image_url?: string;\n scroller_config?: SwirlScrollerConfig;\n z_index: number;\n created_at?: string;\n updated_at?: string;\n}\n\nexport function timeStringToSeconds(timeStr: string): number {\n if (!timeStr) return 0;\n\n const parts = timeStr.split(\":\");\n\n if (parts.length >= 3) {\n const hours = parseInt(parts[0] ?? \"0\", 10) || 0;\n const minutes = parseInt(parts[1] ?? \"0\", 10) || 0;\n const secStr = parts[2] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds =\n parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return hours * 3600 + minutes * 60 + seconds + ms / 1000;\n }\n\n if (parts.length === 2) {\n const minutes = parseInt(parts[0] ?? \"0\", 10) || 0;\n const secStr = parts[1] ?? \"0\";\n const dotIdx = secStr.indexOf(\".\");\n const seconds =\n parseInt(dotIdx >= 0 ? secStr.substring(0, dotIdx) : secStr, 10) || 0;\n const msFrag = dotIdx >= 0 ? secStr.substring(dotIdx + 1) : \"\";\n const ms = msFrag ? parseInt(msFrag.padEnd(3, \"0\").substring(0, 3), 10) || 0 : 0;\n return minutes * 60 + seconds + ms / 1000;\n }\n\n const num = parseFloat(timeStr);\n return isFinite(num) ? Math.max(0, num) : 0;\n}\n\nexport function isOverlayActive(\n overlay: SwirlOverlay,\n currentTime: number\n): boolean {\n if (!overlay.visible) return false;\n const startSec = timeStringToSeconds(overlay.start_time);\n const durationSec = timeStringToSeconds(overlay.duration);\n if (durationSec <= 0) return false;\n return currentTime >= startSec && currentTime < startSec + durationSec;\n}\n\nfunction normalizeScrollerConfig(\n raw: SwirlScrollerConfig | Record<string, unknown> | undefined\n): SwirlScrollerConfig | undefined {\n if (!raw || typeof raw !== \"object\") return undefined;\n const r = raw as Record<string, unknown>;\n const merged: SwirlScrollerConfig = { ...(raw as SwirlScrollerConfig) };\n if (merged.use_custom_text === undefined && typeof r.useCustomText === \"boolean\") {\n merged.use_custom_text = r.useCustomText;\n }\n if ((merged.custom_text === undefined || merged.custom_text === \"\") && typeof r.customText === \"string\") {\n merged.custom_text = r.customText;\n }\n if (!merged.rss_url && typeof r.rssUrl === \"string\") {\n merged.rss_url = r.rssUrl;\n }\n return merged;\n}\n\nexport function normalizeSwirlOverlay(raw: SwirlOverlay & Record<string, unknown>): SwirlOverlay {\n const o = { ...raw };\n if (o.type === \"scroller\") {\n const sc = raw.scroller_config ?? (raw as Record<string, unknown>).scrollerConfig;\n const normalized = normalizeScrollerConfig(sc as SwirlScrollerConfig);\n if (normalized) o.scroller_config = normalized;\n }\n return o;\n}\n\nexport async function fetchProjectOverlays(\n projectId: number,\n apiBaseUrl: string = OVERLAY_API_BASE\n): Promise<SwirlOverlay[]> {\n const base = apiBaseUrl.replace(/\\/$/, \"\");\n const response = await fetch(\n `${base}/adstorm/swirl/projects/${projectId}/overlays`\n );\n if (!response.ok) {\n throw new Error(\n `Failed to fetch overlays: ${response.status} ${response.statusText}`\n );\n }\n const data = await response.json();\n if (!Array.isArray(data)) return [];\n return data.map((row: SwirlOverlay & Record<string, unknown>) =>\n normalizeSwirlOverlay(row)\n );\n}\n\nexport function resolveImageUrl(\n imageUrl: string,\n apiBaseUrl: string = OVERLAY_API_BASE\n): string {\n if (!imageUrl) return \"\";\n if (imageUrl.startsWith(\"http://\") || imageUrl.startsWith(\"https://\")) {\n return imageUrl;\n }\n if (imageUrl.startsWith(\"/\")) {\n try {\n const url = new URL(apiBaseUrl);\n return `${url.origin}${imageUrl}`;\n } catch {\n return imageUrl;\n }\n }\n return `${apiBaseUrl}/${imageUrl}`;\n}\n"]}