@mottosports/motto-video-player 1.0.1-rc.8 → 1.0.1-rc.81

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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,8 @@
1
1
  "use client";
2
2
 
3
+ // src/index.ts
4
+ import "shaka-player/dist/controls.css";
5
+
3
6
  // #style-inject:#style-inject
4
7
  function styleInject(css, { insertAt } = {}) {
5
8
  if (!css || typeof document === "undefined") return;
@@ -22,73 +25,1031 @@ function styleInject(css, { insertAt } = {}) {
22
25
  }
23
26
  }
24
27
 
25
- // src/index.css
26
- styleInject('/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wide: 0.025em;\n --tracking-widest: 0.1em;\n --radius-md: 0.375rem;\n --radius-2xl: 1rem;\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --aspect-video: 16 / 9;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-auto {\n pointer-events: auto;\n }\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-4 {\n top: calc(var(--spacing) * 4);\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .bottom-0 {\n bottom: calc(var(--spacing) * 0);\n }\n .bottom-4 {\n bottom: calc(var(--spacing) * 4);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .z-10 {\n z-index: 10;\n }\n .z-50 {\n z-index: 50;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .m-6 {\n margin: calc(var(--spacing) * 6);\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-3 {\n margin-top: calc(var(--spacing) * 3);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .aspect-video {\n aspect-ratio: var(--aspect-video);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-8 {\n height: calc(var(--spacing) * 8);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-8 {\n width: calc(var(--spacing) * 8);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-full {\n width: 100%;\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .auto-cols-max {\n grid-auto-columns: max-content;\n }\n .grid-flow-col {\n grid-auto-flow: column;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-stretch {\n justify-content: stretch;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-5 {\n gap: calc(var(--spacing) * 5);\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-white {\n border-color: var(--color-white);\n }\n .bg-\\[\\#151515\\] {\n background-color: #151515;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-gradient-to-t {\n --tw-gradient-position: to top in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black\\/70 {\n --tw-gradient-from: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-transparent {\n --tw-gradient-to: transparent;\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .bg-no-repeat {\n background-repeat: no-repeat;\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .font-mono {\n font-family: var(--font-mono);\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-5xl {\n font-size: var(--text-5xl);\n line-height: var(--tw-leading, var(--text-5xl--line-height));\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .text-\\[10px\\] {\n font-size: 10px;\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wide {\n --tw-tracking: var(--tracking-wide);\n letter-spacing: var(--tracking-wide);\n }\n .tracking-widest {\n --tw-tracking: var(--tracking-widest);\n letter-spacing: var(--tracking-widest);\n }\n .text-white {\n color: var(--color-white);\n }\n .uppercase {\n text-transform: uppercase;\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .md\\:rounded-2xl {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl);\n }\n }\n .md\\:rounded-2xl\\! {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl) !important;\n }\n }\n .md\\:text-base {\n @media (width >= 48rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n .md\\:text-sm {\n @media (width >= 48rem) {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n }\n .md\\:text-xl {\n @media (width >= 48rem) {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n }\n}\n@layer components {\n .motto-video-container {\n position: relative;\n width: 100%;\n min-height: 300px;\n }\n @supports (aspect-ratio: 16/9) {\n .motto-video-container {\n min-height: auto;\n }\n }\n .motto-video-responsive {\n position: absolute;\n top: calc(var(--spacing) * 0);\n left: calc(var(--spacing) * 0);\n height: 100%;\n width: 100%;\n }\n .motto-skip-button {\n position: absolute;\n top: calc(1/2 * 100%);\n z-index: 10;\n display: flex;\n height: calc(var(--spacing) * 16);\n width: calc(var(--spacing) * 16);\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n color: var(--color-white);\n opacity: 80%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 110%;\n --tw-scale-y: 110%;\n --tw-scale-z: 110%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n &:hover {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .motto-skip-button-back {\n left: calc(var(--spacing) * 5);\n }\n .motto-skip-button-forward {\n right: calc(var(--spacing) * 5);\n }\n .motto-mobile-controls-overlay {\n position: absolute;\n inset: calc(var(--spacing) * 0);\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 300ms;\n transition-duration: 300ms;\n pointer-events: none;\n }\n .motto-mobile-controls-group {\n display: flex;\n align-items: center;\n gap: calc(var(--spacing) * 8);\n opacity: 100%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: none;\n }\n .motto-mobile-play-button {\n display: flex;\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-play-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-play-button svg {\n height: calc(var(--spacing) * 7);\n width: calc(var(--spacing) * 7);\n }\n .motto-mobile-skip-button {\n display: flex;\n height: calc(var(--spacing) * 10);\n width: calc(var(--spacing) * 10);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-skip-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-skip-button svg {\n height: calc(var(--spacing) * 6);\n width: calc(var(--spacing) * 6);\n }\n}\n@media (min-width: 768px) {\n .motto-mobile-controls-overlay {\n display: none !important;\n }\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-button[title*="Skip back"],\n .shaka-controls-container .shaka-button[title*="Skip forward"],\n .shaka-controls-container .shaka-button[aria-label*="Skip back"],\n .shaka-controls-container .shaka-button[aria-label*="Skip forward"],\n .shaka-controls-container button[title*="Skip back"],\n .shaka-controls-container button[title*="Skip forward"],\n .shaka-controls-container button[aria-label*="Skip back"],\n .shaka-controls-container button[aria-label*="Skip forward"],\n .motto-native-skip-button:not(.motto-mobile-skip-button),\n .motto-skip-back-button:not(.motto-mobile-skip-button),\n .motto-skip-forward-button:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button),\n button[title*="Skip back"]:not(.motto-mobile-skip-button),\n button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button) {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n width: 0 !important;\n height: 0 !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n .motto-mobile-skip-button {\n display: flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n.shaka-seek-bar-container {\n height: 6px !important;\n width: 100% !important;\n margin: 8px 0 !important;\n border-radius: 4px !important;\n position: relative !important;\n border-top: none !important;\n border-bottom: none !important;\n box-shadow: none !important;\n}\n.shaka-seek-bar {\n height: 6px !important;\n width: 100% !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n background: transparent !important;\n cursor: pointer !important;\n border: none !important;\n outline: none !important;\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n border-radius: 4px !important;\n}\n.shaka-seek-bar::-webkit-slider-runnable-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-moz-range-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-webkit-slider-thumb {\n -webkit-appearance: none !important;\n appearance: none !important;\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.shaka-seek-bar::-moz-range-thumb {\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.motto-skip-back-button,\n.motto-skip-forward-button,\n.motto-native-skip-button {\n background: transparent !important;\n border: none !important;\n padding: 4px !important;\n margin: 0px !important;\n cursor: pointer !important;\n color: #ffffff !important;\n transition: all 0.2s ease !important;\n min-width: 32px !important;\n height: 32px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n border-radius: 4px !important;\n width: 25px;\n}\n.motto-skip-back-button:hover,\n.motto-skip-forward-button:hover,\n.motto-native-skip-button:hover {\n opacity: 0.8 !important;\n background: transparent !important;\n transform: scale(1.05) !important;\n}\n.motto-skip-back-button:active,\n.motto-skip-forward-button:active,\n.motto-native-skip-button:active {\n transform: scale(0.95) !important;\n}\n.motto-skip-back-button svg,\n.motto-skip-forward-button svg,\n.motto-native-skip-button svg {\n width: 24px !important;\n height: 24px !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-play-button,\n .shaka-controls-container .shaka-pause-button {\n display: none !important;\n }\n}\n.shaka-spinner-svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-spinner-path {\n stroke: white !important;\n fill: none !important;\n}\n.shaka-spinner-container {\n color: white !important;\n}\n.shaka-buffering-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner path {\n stroke: white !important;\n fill: none !important;\n}\n[data-shaka-player-container] .shaka-spinner,\n[data-shaka-player-container] .spinner {\n color: white !important;\n border-color: white !important;\n}\n.material-icons.shaka-spinner {\n color: white !important;\n}\n.shaka-controls-container .shaka-spinner,\n.shaka-video-container .shaka-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner svg,\n.shaka-video-container .shaka-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner path,\n.shaka-video-container .shaka-spinner path {\n stroke: white !important;\n}\n.motto-video-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n linear-gradient(\n 135deg,\n #1a1a1a 0%,\n #2d2d2d 100%);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: opacity 0.3s ease;\n}\n.motto-video-loading-overlay.hidden {\n opacity: 0;\n pointer-events: none;\n}\n.motto-video-loading-content {\n text-align: center;\n color: white;\n}\n.motto-video-loading-icon {\n width: 64px;\n height: 64px;\n margin-bottom: 16px;\n opacity: 0.7;\n}\n.motto-video-loading-text {\n font-size: 16px;\n font-weight: 500;\n margin-bottom: 8px;\n}\n.motto-video-loading-subtext {\n font-size: 14px;\n opacity: 0.7;\n}\n@keyframes pulse-live {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n.shaka-play-button-container {\n display: none !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container {\n z-index: 90 !important;\n height: 100px !important;\n bottom: 0 !important;\n top: unset !important;\n }\n}\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-gradient-position { syntax: "*"; inherits: false; }\n@property --tw-gradient-from { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-via { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-to { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-via-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-from-position { syntax: "<length-percentage>"; inherits: false; initial-value: 0%; }\n@property --tw-gradient-via-position { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }\n@property --tw-gradient-to-position { syntax: "<length-percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-tracking { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@property --tw-translate-x { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-y { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-z { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-duration { syntax: "*"; inherits: false; }\n@property --tw-scale-x { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-y { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-z { syntax: "*"; inherits: false; initial-value: 1; }\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
28
+ // src/styles.css
29
+ styleInject(`@layer components {
30
+ video::-webkit-media-controls {
31
+ display: none !important;
32
+ }
33
+ video::-webkit-media-controls-panel {
34
+ display: none !important;
35
+ }
36
+ video::-webkit-media-controls-play-button {
37
+ display: none !important;
38
+ }
39
+ video::-webkit-media-controls-timeline {
40
+ display: none !important;
41
+ }
42
+ video::-webkit-media-controls-current-time-display {
43
+ display: none !important;
44
+ }
45
+ video::-webkit-media-controls-time-remaining-display {
46
+ display: none !important;
47
+ }
48
+ video::-webkit-media-controls-mute-button {
49
+ display: none !important;
50
+ }
51
+ video::-webkit-media-controls-volume-slider {
52
+ display: none !important;
53
+ }
54
+ video::-webkit-media-controls-fullscreen-button {
55
+ display: none !important;
56
+ }
57
+ video::-webkit-media-controls-overlay-play-button {
58
+ display: none !important;
59
+ }
60
+ video::-moz-media-controls {
61
+ display: none !important;
62
+ }
63
+ video {
64
+ outline: none !important;
65
+ }
66
+ video[controls] {
67
+ -webkit-appearance: none !important;
68
+ appearance: none !important;
69
+ }
70
+ video::-webkit-media-controls-enclosure {
71
+ display: none !important;
72
+ }
73
+ video::-webkit-media-controls-start-playback-button {
74
+ display: none !important;
75
+ }
76
+ video[controls]::-webkit-media-controls,
77
+ video[controls]::-webkit-media-controls-panel,
78
+ video[controls]::-webkit-media-controls-play-button,
79
+ video[controls]::-webkit-media-controls-timeline,
80
+ video[controls]::-webkit-media-controls-current-time-display,
81
+ video[controls]::-webkit-media-controls-time-remaining-display,
82
+ video[controls]::-webkit-media-controls-mute-button,
83
+ video[controls]::-webkit-media-controls-volume-slider,
84
+ video[controls]::-webkit-media-controls-fullscreen-button,
85
+ video[controls]::-webkit-media-controls-overlay-play-button,
86
+ video[controls]::-webkit-media-controls-enclosure,
87
+ video[controls]::-webkit-media-controls-start-playback-button {
88
+ display: none !important;
89
+ visibility: hidden !important;
90
+ opacity: 0 !important;
91
+ pointer-events: none !important;
92
+ }
93
+ video[controls]::-moz-media-controls {
94
+ display: none !important;
95
+ visibility: hidden !important;
96
+ opacity: 0 !important;
97
+ }
98
+ .motto-video-container {
99
+ @apply relative w-full;
100
+ min-height: 300px;
101
+ }
102
+ @supports (aspect-ratio: 16/9) {
103
+ .motto-video-container {
104
+ min-height: auto;
105
+ }
106
+ }
107
+ .motto-video-responsive {
108
+ @apply absolute top-0 left-0 w-full h-full;
109
+ }
110
+ .motto-skip-button {
111
+ @apply absolute top-1/2 -translate-y-1/2 bg-black/70 text-white border-0 rounded-full w-16 h-16 text-2xl cursor-pointer flex items-center justify-center transition-all duration-200 z-10 opacity-80 hover:opacity-100 hover:scale-110 active:scale-95;
112
+ }
113
+ .motto-skip-button-back {
114
+ @apply left-5;
115
+ }
116
+ .motto-skip-button-forward {
117
+ @apply right-5;
118
+ }
119
+ }
120
+ .shaka-seek-bar-container {
121
+ height: 6px !important;
122
+ width: 100% !important;
123
+ margin: 8px 0 !important;
124
+ border-radius: 4px !important;
125
+ position: relative !important;
126
+ border-top: none !important;
127
+ border-bottom: none !important;
128
+ box-shadow: none !important;
129
+ }
130
+ .shaka-seek-bar {
131
+ height: 6px !important;
132
+ width: 100% !important;
133
+ -webkit-appearance: none !important;
134
+ appearance: none !important;
135
+ background: transparent !important;
136
+ cursor: pointer !important;
137
+ border: none !important;
138
+ outline: none !important;
139
+ position: absolute !important;
140
+ top: 0 !important;
141
+ left: 0 !important;
142
+ border-radius: 4px !important;
143
+ }
144
+ .shaka-seek-bar::-webkit-slider-runnable-track {
145
+ height: 6px !important;
146
+ background: transparent !important;
147
+ border-radius: 4px !important;
148
+ border: none !important;
149
+ }
150
+ .shaka-seek-bar::-moz-range-track {
151
+ height: 6px !important;
152
+ background: transparent !important;
153
+ border-radius: 4px !important;
154
+ border: none !important;
155
+ }
156
+ .shaka-seek-bar::-webkit-slider-thumb {
157
+ -webkit-appearance: none !important;
158
+ appearance: none !important;
159
+ width: 16px !important;
160
+ height: 16px !important;
161
+ border-radius: 50% !important;
162
+ background: #ffffff !important;
163
+ cursor: pointer !important;
164
+ border: 2px solid #ffffff !important;
165
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;
166
+ margin-top: -4px !important;
167
+ }
168
+ .shaka-seek-bar::-moz-range-thumb {
169
+ width: 16px !important;
170
+ height: 16px !important;
171
+ border-radius: 50% !important;
172
+ background: #ffffff !important;
173
+ cursor: pointer !important;
174
+ border: 2px solid #ffffff !important;
175
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;
176
+ margin-top: -4px !important;
177
+ }
178
+ .motto-skip-back-button,
179
+ .motto-skip-forward-button,
180
+ .motto-native-skip-button {
181
+ background: transparent !important;
182
+ border: none !important;
183
+ padding: 4px !important;
184
+ margin: 0px !important;
185
+ cursor: pointer !important;
186
+ color: #ffffff !important;
187
+ transition: all 0.2s ease !important;
188
+ min-width: 32px !important;
189
+ height: 32px !important;
190
+ display: flex !important;
191
+ align-items: center !important;
192
+ justify-content: center !important;
193
+ border-radius: 4px !important;
194
+ width: 25px;
195
+ }
196
+ .motto-skip-back-button:hover,
197
+ .motto-skip-forward-button:hover,
198
+ .motto-native-skip-button:hover {
199
+ opacity: 0.8 !important;
200
+ background: transparent !important;
201
+ transform: scale(1.05) !important;
202
+ }
203
+ .motto-skip-back-button:active,
204
+ .motto-skip-forward-button:active,
205
+ .motto-native-skip-button:active {
206
+ transform: scale(0.95) !important;
207
+ }
208
+ .motto-skip-back-button svg,
209
+ .motto-skip-forward-button svg,
210
+ .motto-native-skip-button svg {
211
+ width: 24px !important;
212
+ height: 24px !important;
213
+ }
214
+ .shaka-spinner-svg {
215
+ color: white !important;
216
+ fill: white !important;
217
+ }
218
+ .shaka-spinner-path {
219
+ stroke: white !important;
220
+ fill: none !important;
221
+ }
222
+ .shaka-spinner-container {
223
+ color: white !important;
224
+ }
225
+ .shaka-buffering-spinner {
226
+ color: white !important;
227
+ fill: white !important;
228
+ }
229
+ .shaka-buffering-spinner svg {
230
+ color: white !important;
231
+ fill: white !important;
232
+ }
233
+ .shaka-buffering-spinner path {
234
+ stroke: white !important;
235
+ fill: none !important;
236
+ }
237
+ [data-shaka-player-container] .shaka-spinner,
238
+ [data-shaka-player-container] .spinner {
239
+ color: white !important;
240
+ border-color: white !important;
241
+ }
242
+ .material-icons.shaka-spinner {
243
+ color: white !important;
244
+ }
245
+ .shaka-controls-container .shaka-spinner,
246
+ .shaka-video-container .shaka-spinner {
247
+ color: white !important;
248
+ fill: white !important;
249
+ }
250
+ .shaka-controls-container .shaka-spinner svg,
251
+ .shaka-video-container .shaka-spinner svg {
252
+ color: white !important;
253
+ fill: white !important;
254
+ }
255
+ .shaka-controls-container .shaka-spinner path,
256
+ .shaka-video-container .shaka-spinner path {
257
+ stroke: white !important;
258
+ }
259
+ .motto-video-loading-overlay {
260
+ position: absolute;
261
+ top: 0;
262
+ left: 0;
263
+ width: 100%;
264
+ height: 100%;
265
+ background:
266
+ linear-gradient(
267
+ 135deg,
268
+ #1a1a1a 0%,
269
+ #2d2d2d 100%);
270
+ display: flex;
271
+ flex-direction: column;
272
+ align-items: center;
273
+ justify-content: center;
274
+ z-index: 10;
275
+ transition: opacity 0.3s ease;
276
+ }
277
+ .motto-video-loading-overlay.hidden {
278
+ opacity: 0;
279
+ pointer-events: none;
280
+ }
281
+ .motto-video-loading-content {
282
+ text-align: center;
283
+ color: white;
284
+ }
285
+ .motto-video-loading-icon {
286
+ width: 64px;
287
+ height: 64px;
288
+ margin-bottom: 16px;
289
+ opacity: 0.7;
290
+ }
291
+ .motto-video-loading-text {
292
+ font-size: 16px;
293
+ font-weight: 500;
294
+ margin-bottom: 8px;
295
+ }
296
+ .motto-video-loading-subtext {
297
+ font-size: 14px;
298
+ opacity: 0.7;
299
+ }
300
+ @keyframes pulse-live {
301
+ 0% {
302
+ opacity: 1;
303
+ transform: scale(1);
304
+ }
305
+ 50% {
306
+ opacity: 0.7;
307
+ transform: scale(1.1);
308
+ }
309
+ 100% {
310
+ opacity: 1;
311
+ transform: scale(1);
312
+ }
313
+ }
314
+ .shaka-play-button {
315
+ background: rgba(255, 255, 255, 0.1) !important;
316
+ border: none !important;
317
+ color: white !important;
318
+ padding: 10px !important;
319
+ border-radius: 100% !important;
320
+ transition: all 0.2s ease !important;
321
+ display: flex !important;
322
+ align-items: center !important;
323
+ justify-content: center !important;
324
+ min-width: 55px !important;
325
+ height: 55px !important;
326
+ }
327
+ .shaka-play-button-container {
328
+ background: transparent;
329
+ transition: all 0.2s ease !important;
330
+ }
331
+ .motto-video-container:not(.no-cursor) .shaka-play-button-container {
332
+ background: rgba(0, 0, 0, 0.3);
333
+ transition: all 0.s ease !important;
334
+ }
335
+ .shaka-play-button:hover {
336
+ background: rgba(255, 255, 255, 0.2) !important;
337
+ transform: scale(1.05) !important;
338
+ }
339
+ .shaka-play-button:active {
340
+ transform: scale(0.95) !important;
341
+ }
342
+ .shaka-play-button > * {
343
+ display: none !important;
344
+ }
345
+ .shaka-play-button::after {
346
+ content: "" !important;
347
+ width: 35px !important;
348
+ height: 35px !important;
349
+ background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" /></svg>') !important;
350
+ background-repeat: no-repeat !important;
351
+ background-size: contain !important;
352
+ background-position: center !important;
353
+ display: block !important;
354
+ }
355
+ .shaka-play-button[aria-label*=Play]::after {
356
+ background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" /></svg>') !important;
357
+ }
358
+ .shaka-play-button[aria-label*=Pause]::after {
359
+ background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" /></svg>') !important;
360
+ }
361
+ .motto-video-container {
362
+ background: #111111;
363
+ }
364
+ .motto-video-container video {
365
+ width: 100% !important;
366
+ height: 100% !important;
367
+ margin-left: auto !important;
368
+ margin-right: auto !important;
369
+ }
370
+ html[dir=rtl] .shaka-controls-container,
371
+ html[dir=rtl] .shaka-bottom-controls,
372
+ html[dir=rtl] .shaka-controls-button-panel {
373
+ direction: ltr !important;
374
+ }
375
+ html[dir=rtl] .shaka-overflow-menu,
376
+ html[dir=rtl] .shaka-settings-menu {
377
+ direction: rtl !important;
378
+ text-align: right !important;
379
+ }
380
+ html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:not(:first-child) {
381
+ margin-right: 12px !important;
382
+ margin-left: 0 !important;
383
+ }
384
+ html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:first-child {
385
+ margin-right: 0 !important;
386
+ margin-left: 12px !important;
387
+ }
388
+ .shaka-hidden-fast-forward-container,
389
+ .shaka-hidden-rewind-container {
390
+ pointer-events: none !important;
391
+ display: none !important;
392
+ }
393
+ `);
27
394
 
28
395
  // src/Player.tsx
29
- import { forwardRef, useEffect as useEffect4, useRef as useRef8, useImperativeHandle } from "react";
30
- import shaka2 from "shaka-player/dist/shaka-player.ui";
396
+ import { forwardRef, useEffect as useEffect4, useRef as useRef8, useImperativeHandle, useCallback as useCallback9, useState as useState3 } from "react";
397
+ import shaka3 from "shaka-player/dist/shaka-player.ui";
398
+
399
+ // src/hooks/useShakaPlayer.ts
400
+ import { useRef, useCallback, useState } from "react";
401
+ import shaka from "shaka-player/dist/shaka-player.ui";
402
+
403
+ // src/utils/devices.ts
404
+ var isAppleDevice = () => {
405
+ if (typeof navigator === "undefined") return false;
406
+ const ua = navigator.userAgent || "";
407
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
408
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
409
+ const isMacSafari = /Macintosh/.test(ua) && isSafari;
410
+ return isIOS || isMacSafari;
411
+ };
412
+ var isPlayReadySupported = () => {
413
+ if (typeof navigator === "undefined" || typeof window === "undefined") {
414
+ return false;
415
+ }
416
+ if (!navigator.requestMediaKeySystemAccess) {
417
+ return false;
418
+ }
419
+ const userAgent = navigator.userAgent || "";
420
+ const isXbox = /Xbox/.test(userAgent);
421
+ const isEdge = /Edg/.test(userAgent);
422
+ const isIE = /Trident|MSIE/.test(userAgent);
423
+ const isWindows = /Windows/.test(userAgent);
424
+ return isXbox || (isEdge || isIE) && isWindows;
425
+ };
426
+ var supportsWidevinePersistentLicenses = () => {
427
+ return false;
428
+ if (typeof navigator === "undefined") {
429
+ return false;
430
+ }
431
+ const userAgent = navigator.userAgent || "";
432
+ const isChromeMatch = userAgent.match(/Chrome\/(\d+)/);
433
+ if (!isChromeMatch) {
434
+ return false;
435
+ }
436
+ if (/Edg|OPR|Opera/.test(userAgent)) {
437
+ return false;
438
+ }
439
+ const chromeVersion = parseInt(isChromeMatch[1], 10);
440
+ if (chromeVersion < 64) {
441
+ return false;
442
+ }
443
+ const isMacOS = /Mac OS X|Macintosh/.test(userAgent);
444
+ const isWindows = /Windows/.test(userAgent);
445
+ return isMacOS || isWindows;
446
+ };
447
+
448
+ // src/hooks/useShakaPlayer.ts
449
+ import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
450
+
451
+ // package.json
452
+ var version = "1.0.1-rc.81";
453
+
454
+ // src/utils/licenseCache.ts
455
+ var PERSISTENT_LICENSE_PREFIX = "motto_lic_";
456
+ var LICENSE_EXPIRY_MS = 2 * 60 * 60 * 1e3;
457
+ var LICENSE_MAX_RETRY_ATTEMPTS = 10;
458
+ var getAllLicenseCacheKeys = () => {
459
+ const keys = [];
460
+ for (let i = 0; i < localStorage.length; i++) {
461
+ const key = localStorage.key(i);
462
+ if (key?.startsWith(PERSISTENT_LICENSE_PREFIX)) {
463
+ keys.push(key);
464
+ }
465
+ }
466
+ return keys;
467
+ };
468
+ var getAllLicenseCacheEntries = () => {
469
+ const keys = getAllLicenseCacheKeys();
470
+ const entries = [];
471
+ for (const key of keys) {
472
+ try {
473
+ const stored = localStorage.getItem(key);
474
+ if (stored) {
475
+ const data = JSON.parse(stored);
476
+ entries.push({ key, data });
477
+ }
478
+ } catch (error) {
479
+ console.warn(`Failed to parse license cache entry for key ${key}:`, error);
480
+ localStorage.removeItem(key);
481
+ }
482
+ }
483
+ return entries;
484
+ };
485
+ var evictLRUEntry = () => {
486
+ const entries = getAllLicenseCacheEntries();
487
+ if (entries.length === 0) {
488
+ return false;
489
+ }
490
+ entries.sort((a, b) => {
491
+ const oldestA = Math.min(...a.data.map((session) => session.timestamp));
492
+ const oldestB = Math.min(...b.data.map((session) => session.timestamp));
493
+ return oldestA - oldestB;
494
+ });
495
+ const lruEntry = entries[0];
496
+ localStorage.removeItem(lruEntry.key);
497
+ console.log(`Evicted LRU license cache entry: ${lruEntry.key}`);
498
+ return true;
499
+ };
500
+ var storeWithQuotaHandling = (key, data) => {
501
+ let attempts = 0;
502
+ while (attempts < LICENSE_MAX_RETRY_ATTEMPTS) {
503
+ try {
504
+ localStorage.setItem(key, data);
505
+ return true;
506
+ } catch (error) {
507
+ if (error instanceof DOMException && (error.code === 22 || // QUOTA_EXCEEDED_ERR
508
+ error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED")) {
509
+ console.warn(`QuotaExceededError on attempt ${attempts + 1}, attempting LRU eviction...`);
510
+ if (!evictLRUEntry()) {
511
+ console.error("No more entries to evict, storage operation failed");
512
+ return false;
513
+ }
514
+ attempts++;
515
+ } else {
516
+ console.error("Failed to store license cache data:", error);
517
+ return false;
518
+ }
519
+ }
520
+ }
521
+ console.error(`Failed to store license cache data after ${LICENSE_MAX_RETRY_ATTEMPTS} eviction attempts`);
522
+ return false;
523
+ };
524
+ var managePersistentLicenseStorage = (playlistId, licenseCacheKey, newSessionMetadata) => {
525
+ try {
526
+ const storageKey = `${PERSISTENT_LICENSE_PREFIX}${playlistId}_${licenseCacheKey}`;
527
+ const stored = localStorage.getItem(storageKey);
528
+ let existingSessions = [];
529
+ if (stored) {
530
+ try {
531
+ existingSessions = JSON.parse(stored);
532
+ } catch (parseError) {
533
+ console.warn("Failed to parse existing persistent license data:", parseError);
534
+ existingSessions = [];
535
+ }
536
+ }
537
+ const now = Date.now();
538
+ let validSessions = existingSessions.filter(
539
+ (session) => now - session.timestamp < LICENSE_EXPIRY_MS
540
+ );
541
+ if (newSessionMetadata && newSessionMetadata.length > 0) {
542
+ const newSessions = newSessionMetadata.map((session) => {
543
+ const uint8Array = new Uint8Array(session.initData);
544
+ const binaryString = Array.from(uint8Array).map((byte) => String.fromCharCode(byte)).join("");
545
+ return {
546
+ sessionId: session.sessionId,
547
+ initData: btoa(binaryString),
548
+ initDataType: session.initDataType,
549
+ keySystem: session.keySystem,
550
+ timestamp: now
551
+ };
552
+ });
553
+ const newSessionIds = new Set(newSessions.map((s) => s.sessionId));
554
+ validSessions = validSessions.filter((session) => !newSessionIds.has(session.sessionId));
555
+ validSessions = [...validSessions, ...newSessions];
556
+ }
557
+ if (validSessions.length === 0) {
558
+ localStorage.removeItem(storageKey);
559
+ } else {
560
+ const dataToStore = JSON.stringify(validSessions);
561
+ const success = storeWithQuotaHandling(storageKey, dataToStore);
562
+ if (!success) {
563
+ console.error(`Failed to store license cache for ${storageKey} after quota handling`);
564
+ return validSessions;
565
+ }
566
+ }
567
+ return validSessions;
568
+ } catch (error) {
569
+ console.warn("Failed to manage persistent license storage:", error);
570
+ return [];
571
+ }
572
+ };
573
+ var storePersistentLicense = (playlistId, licenseCacheKey, sessionMetadata) => {
574
+ managePersistentLicenseStorage(playlistId, licenseCacheKey, sessionMetadata);
575
+ };
576
+ var retrievePersistentLicense = (playlistId, licenseCacheKey) => {
577
+ try {
578
+ const validSessions = managePersistentLicenseStorage(playlistId, licenseCacheKey);
579
+ return validSessions.map((session) => ({
580
+ sessionId: session.sessionId,
581
+ initData: Uint8Array.from(atob(session.initData), (c) => c.charCodeAt(0)).buffer,
582
+ initDataType: session.initDataType,
583
+ keySystem: session.keySystem
584
+ }));
585
+ } catch (error) {
586
+ console.warn("Failed to retrieve persistent license:", error);
587
+ return [];
588
+ }
589
+ };
590
+ var clearAllPersistentLicenses = () => {
591
+ try {
592
+ const keys = getAllLicenseCacheKeys();
593
+ for (const key of keys) {
594
+ localStorage.removeItem(key);
595
+ }
596
+ console.log(`Cleared ${keys.length} persistent license cache entries`);
597
+ return keys.length;
598
+ } catch (error) {
599
+ console.error("Failed to clear persistent licenses:", error);
600
+ return 0;
601
+ }
602
+ };
31
603
 
32
- // src/hooks/useShakePlayer.ts
33
- import { useRef, useCallback } from "react";
34
- import { Player as ShakaPlayer, polyfill } from "shaka-player/dist/shaka-player.ui";
35
- var useShakePlayer = ({
604
+ // src/hooks/useShakaPlayer.ts
605
+ var normalizeSource = (src) => {
606
+ if (typeof src === "string") {
607
+ return {
608
+ id: "",
609
+ url: src,
610
+ format: "auto",
611
+ drm: {}
612
+ };
613
+ }
614
+ return src;
615
+ };
616
+ var useShakaPlayer = ({
36
617
  src,
37
618
  shakaConfig,
38
619
  drmConfig,
39
620
  onError,
40
- onPlayerReady
621
+ onPlayerReady,
622
+ muxConfig,
623
+ onMuxReady,
624
+ onMuxDataUpdate,
625
+ publicKey,
626
+ mottoToken,
627
+ hasAds = false,
628
+ hasSystem73 = false,
629
+ apiToken
41
630
  }) => {
42
631
  const playerRef = useRef(null);
43
- const initializePlayer = useCallback(async (video) => {
632
+ const [isRetrying, setIsRetrying] = useState(false);
633
+ const videoElementRef = useRef(null);
634
+ const destroyInProgressRef = useRef(null);
635
+ const isDestroyingRef = useRef(false);
636
+ const initSequenceRef = useRef(0);
637
+ const activeInitIdRef = useRef(null);
638
+ const waitingForKeyTimerRef = useRef(null);
639
+ const waitingForKeyHandlerRef = useRef(null);
640
+ const playbackResumedHandlerRef = useRef(null);
641
+ const usingPersistentLicenseRef = useRef(false);
642
+ const storedPersistentThisLoadRef = useRef(false);
643
+ const drmExpirationHandlerRef = useRef(null);
644
+ const getManifestUrl = useCallback(() => {
645
+ const playlistSrc = normalizeSource(src);
646
+ let manifestUrl = playlistSrc.url;
647
+ const isDRM = Boolean(playlistSrc.drm?.widevine || playlistSrc.drm?.fairplay || playlistSrc.drm?.playready);
648
+ if (isDRM) {
649
+ const isPlayReady = isPlayReadySupported();
650
+ if (isAppleDevice() && playlistSrc.drm?.fairplay?.certificateUrl) {
651
+ manifestUrl = playlistSrc.drm.fairplay.playlistUrl;
652
+ } else if (isPlayReady && playlistSrc.drm?.playready?.licenseUrl) {
653
+ manifestUrl = playlistSrc.drm.playready.playlistUrl;
654
+ } else {
655
+ manifestUrl = playlistSrc.drm?.widevine?.playlistUrl || "";
656
+ }
657
+ }
658
+ return manifestUrl;
659
+ }, [src]);
660
+ const initializePlayerInternal = useCallback(async (video) => {
44
661
  try {
45
- polyfill.installAll();
46
- if (!ShakaPlayer.isBrowserSupported()) {
662
+ if (destroyInProgressRef.current) {
663
+ try {
664
+ await destroyInProgressRef.current;
665
+ } catch {
666
+ }
667
+ }
668
+ const myInitId = ++initSequenceRef.current;
669
+ activeInitIdRef.current = myInitId;
670
+ videoElementRef.current = video;
671
+ shaka.polyfill.installAll();
672
+ if (!shaka.Player.isBrowserSupported()) {
47
673
  throw new Error("Browser not supported by Shaka Player");
48
674
  }
49
- const player = new ShakaPlayer(video);
675
+ if (isDestroyingRef.current) {
676
+ return;
677
+ }
678
+ const player = new shaka.Player();
50
679
  playerRef.current = player;
51
680
  await player.attach(video);
681
+ const defaultConfig = {
682
+ manifest: {
683
+ // Override availability window to allow DVR window to grow from start
684
+ // Set to a very large value (24 hours in seconds) to effectively allow unlimited growth
685
+ availabilityWindowOverride: 86400
686
+ // 24 hours in seconds
687
+ },
688
+ streaming: {
689
+ // Allow seeking to any point within the availability window
690
+ safeSeekOffset: 5,
691
+ // 5 seconds from live edge to prevent buffering
692
+ // Increase tolerance for manifest timing inaccuracies in live streams
693
+ inaccurateManifestTolerance: 2
694
+ }
695
+ };
696
+ player.configure(defaultConfig);
52
697
  if (shakaConfig) {
53
698
  player.configure(shakaConfig);
54
699
  }
55
- if (drmConfig) {
56
- if (drmConfig.clearKeys) {
57
- player.configure({ "drm.clearKeys": drmConfig.clearKeys });
700
+ const playlistSrc = normalizeSource(src);
701
+ const manifestUrl = getManifestUrl();
702
+ let playlistId = playlistSrc.id;
703
+ const isDRM = Boolean(playlistSrc.drm?.widevine || playlistSrc.drm?.fairplay || playlistSrc.drm?.playready);
704
+ storedPersistentThisLoadRef.current = false;
705
+ if (activeInitIdRef.current !== myInitId || isDestroyingRef.current) {
706
+ try {
707
+ await player.destroy();
708
+ } catch {
709
+ }
710
+ if (playerRef.current === player) playerRef.current = null;
711
+ return;
712
+ }
713
+ let storedSessionsMetadata = [];
714
+ if (isDRM && playlistId) {
715
+ storedSessionsMetadata = retrievePersistentLicense(playlistId, playlistSrc.drm?.licenseCacheKey ?? "");
716
+ }
717
+ if (isDRM) {
718
+ const drmConfig2 = {
719
+ servers: {
720
+ "com.widevine.alpha": playlistSrc.drm?.widevine?.licenseUrl,
721
+ "com.microsoft.playready": playlistSrc.drm?.playready?.licenseUrl,
722
+ "com.apple.fps": playlistSrc.drm?.fairplay?.licenseUrl
723
+ },
724
+ keySystemsMapping: {
725
+ // Fall back or reroute to the platform's recommended PlayReady CDM if needed
726
+ "com.microsoft.playready": "com.microsoft.playready.recommendation"
727
+ },
728
+ ...playlistSrc.drm?.fairplay && {
729
+ advanced: {
730
+ "com.apple.fps": {
731
+ serverCertificateUri: playlistSrc.drm.fairplay.certificateUrl
732
+ }
733
+ }
734
+ }
735
+ };
736
+ drmConfig2.advanced = {
737
+ ...drmConfig2.advanced,
738
+ "com.widevine.alpha": {
739
+ ...drmConfig2.advanced?.["com.widevine.alpha"],
740
+ sessionType: supportsWidevinePersistentLicenses() ? "persistent-license" : "temporary"
741
+ },
742
+ "com.microsoft.playready": {
743
+ ...drmConfig2.advanced?.["com.microsoft.playready"],
744
+ sessionType: "persistent-license"
745
+ // PlayReady seems to always require persistent-license (temporary won't work, not compatible with license server response)
746
+ },
747
+ "com.apple.fps": {
748
+ ...drmConfig2.advanced?.["com.apple.fps"],
749
+ sessionType: "temporary"
750
+ // FairPlay always uses temporary sessions - Safari won't play with persistent-license
751
+ }
752
+ };
753
+ if (storedSessionsMetadata.length > 0) {
754
+ drmConfig2.persistentSessionOnlinePlayback = true;
755
+ drmConfig2.persistentSessionsMetadata = storedSessionsMetadata.map((session) => ({
756
+ sessionId: session.sessionId,
757
+ initData: new Uint8Array(session.initData),
758
+ initDataType: session.initDataType
759
+ }));
760
+ }
761
+ usingPersistentLicenseRef.current = storedSessionsMetadata.length > 0;
762
+ player.configure({ drm: drmConfig2 });
763
+ const clearWaitingForKeyTimer = () => {
764
+ if (waitingForKeyTimerRef.current !== null) {
765
+ window.clearTimeout(waitingForKeyTimerRef.current);
766
+ waitingForKeyTimerRef.current = null;
767
+ }
768
+ };
769
+ const onPlaybackResumed = () => {
770
+ clearWaitingForKeyTimer();
771
+ };
772
+ const onWaitingForKey = () => {
773
+ if (!usingPersistentLicenseRef.current) return;
774
+ if (isRetrying) return;
775
+ clearWaitingForKeyTimer();
776
+ waitingForKeyTimerRef.current = window.setTimeout(async () => {
777
+ try {
778
+ if (isRetrying) return;
779
+ console.warn("Stuck waiting for decryption key; attempting license cache reset and reload...");
780
+ const clearedCount = clearAllPersistentLicenses();
781
+ if (clearedCount > 0 && playerRef.current) {
782
+ setIsRetrying(true);
783
+ await playerRef.current.load(getManifestUrl());
784
+ console.log("Reloaded manifest after clearing cached licenses");
785
+ } else {
786
+ console.warn("No cached licenses found to clear, skipping reload");
787
+ }
788
+ } catch (e) {
789
+ console.error("Failed during recovery from waitingforkey state:", e);
790
+ onError?.(e);
791
+ } finally {
792
+ setIsRetrying(false);
793
+ clearWaitingForKeyTimer();
794
+ }
795
+ }, 3e3);
796
+ };
797
+ try {
798
+ video.addEventListener("waitingforkey", onWaitingForKey);
799
+ video.addEventListener("playing", onPlaybackResumed);
800
+ video.addEventListener("ended", onPlaybackResumed);
801
+ video.addEventListener("pause", onPlaybackResumed);
802
+ waitingForKeyHandlerRef.current = onWaitingForKey;
803
+ playbackResumedHandlerRef.current = onPlaybackResumed;
804
+ } catch (e) {
805
+ console.warn("Failed to attach waitingforkey/playback listeners:", e);
806
+ }
807
+ const netEngine = player.getNetworkingEngine();
808
+ if (netEngine) {
809
+ netEngine.registerRequestFilter((type, request) => {
810
+ switch (type) {
811
+ case shaka.net.NetworkingEngine.RequestType.LICENSE:
812
+ if (publicKey) {
813
+ request.headers["authorization"] = `Bearer ${publicKey}`;
814
+ }
815
+ if (mottoToken) {
816
+ request.headers["x-motto-token"] = mottoToken;
817
+ }
818
+ break;
819
+ case shaka.net.NetworkingEngine.RequestType.MANIFEST:
820
+ case shaka.net.NetworkingEngine.RequestType.SEGMENT:
821
+ request.allowCrossSiteCredentials = true;
822
+ break;
823
+ }
824
+ });
825
+ netEngine.registerResponseFilter((type, response) => {
826
+ if (type === shaka.net.NetworkingEngine.RequestType.LICENSE) {
827
+ const ks = player.keySystem && player.keySystem();
828
+ if (ks === "com.apple.fps") {
829
+ const responseText = shaka.util.StringUtils.fromUTF8(response.data);
830
+ response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
831
+ }
832
+ }
833
+ });
834
+ }
835
+ }
836
+ if (apiToken) {
837
+ const netEngine = player.getNetworkingEngine();
838
+ if (netEngine) {
839
+ netEngine.registerRequestFilter((type, request) => {
840
+ if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST) {
841
+ request.headers["authorization"] = `Bearer ${apiToken}`;
842
+ }
843
+ });
58
844
  }
59
- if (drmConfig.servers) {
60
- player.configure({ "drm.servers": drmConfig.servers });
845
+ }
846
+ if (isDRM && playlistId) {
847
+ const onDRMSessionUpdate = () => {
848
+ try {
849
+ if (storedPersistentThisLoadRef.current) return;
850
+ const activeDrmSessions = player.getActiveSessionsMetadata?.();
851
+ if (!activeDrmSessions) return;
852
+ const persistentSessions = activeDrmSessions.filter(
853
+ (session) => session.sessionType === "persistent-license"
854
+ );
855
+ if (persistentSessions.length > 0) {
856
+ const sessionsToStore = persistentSessions.map((session) => ({
857
+ sessionId: session.sessionId,
858
+ initData: session.initData,
859
+ initDataType: session.initDataType,
860
+ keySystem: session.keySystem || "com.widevine.alpha"
861
+ }));
862
+ storePersistentLicense(playlistId, playlistSrc.drm?.licenseCacheKey ?? "", sessionsToStore);
863
+ storedPersistentThisLoadRef.current = true;
864
+ }
865
+ } catch (e) {
866
+ console.warn("Failed to persist licenses on expiration update:", e);
867
+ }
868
+ };
869
+ try {
870
+ player.addEventListener("drmsessionupdate", onDRMSessionUpdate);
871
+ drmExpirationHandlerRef.current = onDRMSessionUpdate;
872
+ } catch (e) {
873
+ console.warn("Failed to attach drmsessionupdate listener:", e);
61
874
  }
62
875
  }
63
- player.addEventListener("error", (event) => {
876
+ player?.addEventListener("error", (event) => {
64
877
  const error = event.detail;
878
+ if (error?.code === 7e3) {
879
+ return;
880
+ }
881
+ if (error?.code >= 6e3 && error?.code < 7e3 && !isRetrying && videoElementRef.current) {
882
+ console.warn(`DRM error detected (code: ${error.code}), checking for cached licenses...`);
883
+ const clearedCount = clearAllPersistentLicenses();
884
+ if (clearedCount > 0) {
885
+ console.warn(`Cleared ${clearedCount} cached licenses, retrying...`);
886
+ setIsRetrying(true);
887
+ setTimeout(async () => {
888
+ try {
889
+ const video2 = videoElementRef.current;
890
+ const currentPlayer = playerRef.current;
891
+ if (video2 && currentPlayer) {
892
+ console.log("Reloading manifest after license cache clear...");
893
+ await currentPlayer.load(getManifestUrl());
894
+ console.log("Manifest reloaded successfully");
895
+ }
896
+ } catch (retryError) {
897
+ console.error("Failed to retry after license clear:", retryError);
898
+ onError?.(retryError);
899
+ } finally {
900
+ setIsRetrying(false);
901
+ }
902
+ }, 500);
903
+ return;
904
+ } else {
905
+ console.warn(`No cached licenses found to clear for error code ${error.code}, not retrying to avoid infinite loop`);
906
+ }
907
+ }
65
908
  console.error("Shaka Player Error:", error);
66
909
  onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
67
910
  });
68
- await player.load(src);
911
+ if (muxConfig) {
912
+ try {
913
+ const playerInitTime = initShakaPlayerMux.utils.now();
914
+ const muxOptions = {
915
+ debug: muxConfig.debug || false,
916
+ disableCookies: muxConfig.disableCookies || false,
917
+ respectDoNotTrack: muxConfig.respectDoNotTrack || false,
918
+ automaticErrorTracking: muxConfig.automaticErrorTracking !== false,
919
+ ...muxConfig.beaconCollectionDomain && { beaconCollectionDomain: muxConfig.beaconCollectionDomain },
920
+ ...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
921
+ data: {
922
+ env_key: muxConfig.envKey,
923
+ player_name: muxConfig?.metadata?.player_name,
924
+ player_version: version,
925
+ player_init_time: playerInitTime,
926
+ video_title: muxConfig?.metadata?.video_title ?? "",
927
+ video_id: muxConfig?.metadata?.video_id ?? "",
928
+ viewer_user_id: muxConfig?.metadata?.viewer_user_id ?? "",
929
+ ...muxConfig.metadata
930
+ }
931
+ };
932
+ initShakaPlayerMux(player, muxOptions, shaka);
933
+ onMuxReady?.();
934
+ } catch (error) {
935
+ console.error("Failed to initialize Mux Analytics:", error);
936
+ }
937
+ }
938
+ if (activeInitIdRef.current !== myInitId || isDestroyingRef.current) {
939
+ try {
940
+ await player.destroy();
941
+ } catch {
942
+ }
943
+ if (playerRef.current === player) playerRef.current = null;
944
+ return;
945
+ }
946
+ if (!hasAds && !hasSystem73) {
947
+ console.log("\u{1F4FA} [Shaka] Auto-loading manifest:", manifestUrl);
948
+ await player.load(manifestUrl);
949
+ console.log("\u2705 [Shaka] Manifest auto-loaded successfully");
950
+ } else {
951
+ console.log("\u23ED\uFE0F [Shaka] Skipping auto-load (hasAds:", hasAds, ", hasSystem73:", hasSystem73, ")");
952
+ }
69
953
  onPlayerReady?.(player);
70
954
  return player;
71
955
  } catch (error) {
956
+ if (error?.code === 7e3) {
957
+ return;
958
+ }
72
959
  console.error("Error initializing Shaka Player:", error);
73
960
  onError?.(error);
74
961
  throw error;
75
962
  }
76
- }, [shakaConfig, drmConfig, src, onError, onPlayerReady]);
963
+ }, [shakaConfig, drmConfig, src, onError, onPlayerReady, muxConfig, onMuxReady, isRetrying, getManifestUrl, apiToken]);
964
+ const initializePlayer = useCallback(async (video) => {
965
+ return initializePlayerInternal(video);
966
+ }, [initializePlayerInternal]);
967
+ const loadManifest = useCallback(async () => {
968
+ const player = playerRef.current;
969
+ if (!player) {
970
+ console.warn("\u26A0\uFE0F [Shaka] Cannot load manifest: player not initialized");
971
+ return;
972
+ }
973
+ try {
974
+ const manifestUrl = getManifestUrl();
975
+ console.log("\u{1F4FA} [Shaka] Loading manifest:", manifestUrl);
976
+ await player.load(manifestUrl);
977
+ console.log("\u2705 [Shaka] Manifest loaded successfully");
978
+ } catch (error) {
979
+ if (error?.code === 7e3) {
980
+ return;
981
+ }
982
+ console.error("\u274C [Shaka] Error loading manifest:", error);
983
+ onError?.(error);
984
+ throw error;
985
+ }
986
+ }, [getManifestUrl, onError]);
77
987
  const destroyPlayer = useCallback(async () => {
78
- if (playerRef.current) {
988
+ const playerInstance = playerRef.current;
989
+ if (playerInstance) {
79
990
  try {
80
- await playerRef.current.destroy();
991
+ isDestroyingRef.current = true;
992
+ activeInitIdRef.current = null;
993
+ if (videoElementRef.current) {
994
+ try {
995
+ if (waitingForKeyHandlerRef.current) {
996
+ videoElementRef.current.removeEventListener("waitingforkey", waitingForKeyHandlerRef.current);
997
+ }
998
+ if (playbackResumedHandlerRef.current) {
999
+ videoElementRef.current.removeEventListener("playing", playbackResumedHandlerRef.current);
1000
+ videoElementRef.current.removeEventListener("ended", playbackResumedHandlerRef.current);
1001
+ videoElementRef.current.removeEventListener("pause", playbackResumedHandlerRef.current);
1002
+ }
1003
+ } catch (e) {
1004
+ console.warn("Error removing media event listeners:", e);
1005
+ }
1006
+ }
1007
+ if (waitingForKeyTimerRef.current !== null) {
1008
+ window.clearTimeout(waitingForKeyTimerRef.current);
1009
+ waitingForKeyTimerRef.current = null;
1010
+ }
1011
+ try {
1012
+ if (drmExpirationHandlerRef.current && playerInstance.removeEventListener) {
1013
+ playerInstance.removeEventListener("drmsessionupdate", drmExpirationHandlerRef.current);
1014
+ }
1015
+ } catch (e) {
1016
+ console.warn("Error removing DRM expiration listener:", e);
1017
+ } finally {
1018
+ drmExpirationHandlerRef.current = null;
1019
+ }
1020
+ const performDestroy = async () => {
1021
+ try {
1022
+ await playerInstance.destroy();
1023
+ } finally {
1024
+ try {
1025
+ if (videoElementRef.current) {
1026
+ videoElementRef.current.removeAttribute("src");
1027
+ videoElementRef.current.load();
1028
+ }
1029
+ } catch {
1030
+ }
1031
+ }
1032
+ };
1033
+ destroyInProgressRef.current = performDestroy();
1034
+ await destroyInProgressRef.current;
81
1035
  } catch (error) {
82
1036
  console.warn("Error destroying Shaka Player:", error);
83
1037
  } finally {
84
- playerRef.current = null;
1038
+ if (playerRef.current === playerInstance) {
1039
+ playerRef.current = null;
1040
+ }
1041
+ storedPersistentThisLoadRef.current = false;
1042
+ isDestroyingRef.current = false;
1043
+ destroyInProgressRef.current = null;
85
1044
  }
86
1045
  }
87
- }, []);
1046
+ }, [playerRef]);
88
1047
  return {
89
1048
  playerRef,
90
1049
  initializePlayer,
91
- destroyPlayer
1050
+ loadManifest,
1051
+ destroyPlayer,
1052
+ isRetrying
92
1053
  };
93
1054
  };
94
1055
 
@@ -111,11 +1072,25 @@ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
111
1072
  if (!playerRef.current) return;
112
1073
  if (height === 0) {
113
1074
  playerRef.current.configure({
114
- abr: { enabled: true }
1075
+ abr: {
1076
+ enabled: true,
1077
+ switchInterval: 2,
1078
+ // quicker re-checks
1079
+ clearBufferSwitch: true,
1080
+ safeMarginSwitch: 10
1081
+ // leave ~10 s in front of the playhead }
1082
+ }
115
1083
  });
116
1084
  } else {
117
1085
  playerRef.current.configure({
118
- abr: { enabled: false }
1086
+ abr: {
1087
+ enabled: false,
1088
+ switchInterval: 2,
1089
+ // quicker re-checks
1090
+ clearBufferSwitch: true,
1091
+ safeMarginSwitch: 10
1092
+ // leave ~10 s in front of the playhead }
1093
+ }
119
1094
  });
120
1095
  const tracks = playerRef.current.getVariantTracks();
121
1096
  const targetTrack = tracks.find((track) => track.height === height);
@@ -194,14 +1169,14 @@ var useSkipControls = (videoRef, onSkipBack, onSkipForward) => {
194
1169
 
195
1170
  // src/hooks/useMuxAnalytics.ts
196
1171
  import { useCallback as useCallback4, useRef as useRef3 } from "react";
197
- import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
198
- import shaka from "shaka-player/dist/shaka-player.ui";
1172
+ import initShakaPlayerMux2 from "@mux/mux-data-shakaplayer";
1173
+ import shaka2 from "shaka-player/dist/shaka-player.ui";
199
1174
  var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
200
1175
  const shakaPlayerMuxRef = useRef3(null);
201
1176
  const initializeMux = useCallback4(() => {
202
1177
  if (!muxConfig || !playerRef.current) return;
203
1178
  try {
204
- const playerInitTime = initShakaPlayerMux.utils.now();
1179
+ const playerInitTime = initShakaPlayerMux2.utils.now();
205
1180
  const muxOptions = {
206
1181
  debug: muxConfig.debug || false,
207
1182
  disableCookies: muxConfig.disableCookies || false,
@@ -211,13 +1186,16 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
211
1186
  ...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
212
1187
  data: {
213
1188
  env_key: muxConfig.envKey,
214
- player_name: "Motto Video Player",
215
- player_version: "1.0.0",
1189
+ player_name: muxConfig?.metadata?.player_name,
1190
+ player_version: version,
216
1191
  player_init_time: playerInitTime,
1192
+ video_title: muxConfig?.metadata?.video_title ?? "",
1193
+ video_id: muxConfig?.metadata?.video_id ?? "",
1194
+ viewer_user_id: muxConfig?.metadata?.viewer_user_id ?? "",
217
1195
  ...muxConfig.metadata
218
1196
  }
219
1197
  };
220
- shakaPlayerMuxRef.current = initShakaPlayerMux(playerRef.current, muxOptions, shaka);
1198
+ shakaPlayerMuxRef.current = initShakaPlayerMux2(playerRef.current, muxOptions, shaka2);
221
1199
  onMuxReady?.();
222
1200
  } catch (error) {
223
1201
  console.error("Failed to initialize Mux Analytics:", error);
@@ -262,8 +1240,155 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
262
1240
  // src/hooks/useShakaUI.ts
263
1241
  import { useCallback as useCallback5, useRef as useRef4 } from "react";
264
1242
  import { ui as ShakaUI } from "shaka-player/dist/shaka-player.ui";
1243
+
1244
+ // src/icons/SkipBackIcon.tsx
1245
+ import { jsx, jsxs } from "react/jsx-runtime";
1246
+ var SkipBackIcon = ({ size = 24, className = "" }) => {
1247
+ return /* @__PURE__ */ jsxs(
1248
+ "svg",
1249
+ {
1250
+ width: size,
1251
+ height: size,
1252
+ strokeWidth: "2",
1253
+ viewBox: "0 0 24 24",
1254
+ fill: "none",
1255
+ xmlns: "http://www.w3.org/2000/svg",
1256
+ className,
1257
+ children: [
1258
+ /* @__PURE__ */ jsx(
1259
+ "path",
1260
+ {
1261
+ d: "M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4",
1262
+ stroke: "currentColor",
1263
+ strokeWidth: "2",
1264
+ strokeLinecap: "round",
1265
+ strokeLinejoin: "round"
1266
+ }
1267
+ ),
1268
+ /* @__PURE__ */ jsx(
1269
+ "path",
1270
+ {
1271
+ d: "M9 9L9 16",
1272
+ stroke: "currentColor",
1273
+ strokeWidth: "2",
1274
+ strokeLinecap: "round",
1275
+ strokeLinejoin: "round"
1276
+ }
1277
+ ),
1278
+ /* @__PURE__ */ jsx(
1279
+ "path",
1280
+ {
1281
+ d: "M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16",
1282
+ stroke: "currentColor",
1283
+ strokeWidth: "2",
1284
+ strokeLinecap: "round",
1285
+ strokeLinejoin: "round"
1286
+ }
1287
+ ),
1288
+ /* @__PURE__ */ jsx(
1289
+ "path",
1290
+ {
1291
+ d: "M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6",
1292
+ stroke: "currentColor",
1293
+ strokeWidth: "2",
1294
+ strokeLinecap: "round",
1295
+ strokeLinejoin: "round"
1296
+ }
1297
+ )
1298
+ ]
1299
+ }
1300
+ );
1301
+ };
1302
+
1303
+ // src/icons/SkipForwardIcon.tsx
1304
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1305
+ var SkipForwardIcon = ({ size = 24, className = "" }) => {
1306
+ return /* @__PURE__ */ jsxs2(
1307
+ "svg",
1308
+ {
1309
+ width: size,
1310
+ height: size,
1311
+ strokeWidth: "2",
1312
+ viewBox: "0 0 24 24",
1313
+ fill: "none",
1314
+ xmlns: "http://www.w3.org/2000/svg",
1315
+ className,
1316
+ children: [
1317
+ /* @__PURE__ */ jsx2(
1318
+ "path",
1319
+ {
1320
+ d: "M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4",
1321
+ stroke: "currentColor",
1322
+ strokeLinecap: "round",
1323
+ strokeLinejoin: "round"
1324
+ }
1325
+ ),
1326
+ /* @__PURE__ */ jsx2(
1327
+ "path",
1328
+ {
1329
+ d: "M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6",
1330
+ stroke: "currentColor",
1331
+ strokeLinecap: "round",
1332
+ strokeLinejoin: "round"
1333
+ }
1334
+ ),
1335
+ /* @__PURE__ */ jsx2(
1336
+ "path",
1337
+ {
1338
+ d: "M9 9L9 16",
1339
+ stroke: "currentColor",
1340
+ strokeLinecap: "round",
1341
+ strokeLinejoin: "round"
1342
+ }
1343
+ ),
1344
+ /* @__PURE__ */ jsx2(
1345
+ "path",
1346
+ {
1347
+ d: "M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16",
1348
+ stroke: "currentColor",
1349
+ strokeLinecap: "round",
1350
+ strokeLinejoin: "round"
1351
+ }
1352
+ )
1353
+ ]
1354
+ }
1355
+ );
1356
+ };
1357
+
1358
+ // src/icons/BigPlayIcon.tsx
1359
+ import { jsx as jsx3 } from "react/jsx-runtime";
1360
+ var BigPlayIcon = ({ size = 40, className = "" }) => {
1361
+ return /* @__PURE__ */ jsx3(
1362
+ "svg",
1363
+ {
1364
+ width: size,
1365
+ height: size,
1366
+ viewBox: "0 0 24 24",
1367
+ fill: "currentColor",
1368
+ xmlns: "http://www.w3.org/2000/svg",
1369
+ className,
1370
+ children: /* @__PURE__ */ jsx3(
1371
+ "path",
1372
+ {
1373
+ fillRule: "evenodd",
1374
+ d: "M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z",
1375
+ clipRule: "evenodd"
1376
+ }
1377
+ )
1378
+ }
1379
+ );
1380
+ };
1381
+
1382
+ // src/utils/renderIcon.ts
1383
+ import { renderToStaticMarkup } from "react-dom/server";
1384
+ import { createElement } from "react";
1385
+ var renderIcon = (Component, props = {}) => {
1386
+ return renderToStaticMarkup(createElement(Component, props));
1387
+ };
1388
+
1389
+ // src/hooks/useShakaUI.ts
265
1390
  var SkipBackButton = class {
266
- constructor(parent, controls, onSkipBack) {
1391
+ constructor(parent, controls, onSkipBack, iconSize = 24) {
267
1392
  this.parent = parent;
268
1393
  this.controls = controls;
269
1394
  this.eventManager = { listen: (element, event, handler) => {
@@ -271,14 +1396,7 @@ var SkipBackButton = class {
271
1396
  } };
272
1397
  this.button_ = document.createElement("button");
273
1398
  this.button_.className = "shaka-button motto-native-skip-button";
274
- this.button_.innerHTML = `
275
- <svg width="24px" stroke-width="2" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
276
- <path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
277
- <path d="M9 9L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
278
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
279
- <path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
280
- </svg>
281
- `;
1399
+ this.button_.innerHTML = renderIcon(SkipBackIcon, { size: iconSize });
282
1400
  this.button_.title = "Skip back 15 seconds";
283
1401
  this.button_.setAttribute("aria-label", "Skip back 15 seconds");
284
1402
  this.parent.appendChild(this.button_);
@@ -291,9 +1409,13 @@ var SkipBackButton = class {
291
1409
  }
292
1410
  });
293
1411
  }
1412
+ // Shaka UI will call `release` when the controls are destroyed.
1413
+ // Provide a no-op implementation to avoid TypeErrors.
1414
+ release() {
1415
+ }
294
1416
  };
295
1417
  var SkipForwardButton = class {
296
- constructor(parent, controls, onSkipForward) {
1418
+ constructor(parent, controls, onSkipForward, iconSize = 24) {
297
1419
  this.parent = parent;
298
1420
  this.controls = controls;
299
1421
  this.eventManager = { listen: (element, event, handler) => {
@@ -301,14 +1423,7 @@ var SkipForwardButton = class {
301
1423
  } };
302
1424
  this.button_ = document.createElement("button");
303
1425
  this.button_.className = "shaka-button motto-native-skip-button";
304
- this.button_.innerHTML = `
305
- <svg fill="none" height="24" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
306
- <path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
307
- <path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
308
- <path d="M9 9L9 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
309
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
310
- </svg>
311
- `;
1426
+ this.button_.innerHTML = renderIcon(SkipForwardIcon, { size: iconSize });
312
1427
  this.button_.title = "Skip forward 15 seconds";
313
1428
  this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
314
1429
  this.parent.appendChild(this.button_);
@@ -321,243 +1436,65 @@ var SkipForwardButton = class {
321
1436
  }
322
1437
  });
323
1438
  }
1439
+ release() {
1440
+ }
324
1441
  };
325
1442
  var SkipBackButtonFactory = class {
326
- constructor(onSkipBack) {
1443
+ constructor(onSkipBack, iconSize) {
327
1444
  this.onSkipBack = onSkipBack;
1445
+ this.iconSize = iconSize;
328
1446
  }
329
1447
  create(rootElement, controls) {
330
- return new SkipBackButton(rootElement, controls, this.onSkipBack);
1448
+ return new SkipBackButton(rootElement, controls, this.onSkipBack, this.iconSize);
331
1449
  }
332
1450
  };
333
1451
  var SkipForwardButtonFactory = class {
334
- constructor(onSkipForward) {
1452
+ constructor(onSkipForward, iconSize) {
335
1453
  this.onSkipForward = onSkipForward;
1454
+ this.iconSize = iconSize;
336
1455
  }
337
1456
  create(rootElement, controls) {
338
- return new SkipForwardButton(rootElement, controls, this.onSkipForward);
1457
+ return new SkipForwardButton(rootElement, controls, this.onSkipForward, this.iconSize);
339
1458
  }
340
1459
  };
341
- var MobilePlayButton = class {
342
- constructor(parent, controls) {
343
- this.parent = parent;
344
- this.controls = controls;
345
- this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
346
- if (!this.video) {
347
- console.error("MobilePlayButton: No video element found");
348
- return;
349
- }
350
- this.eventManager = { listen: (element, event, handler) => {
351
- element.addEventListener(event, handler);
352
- } };
353
- this.button_ = document.createElement("button");
354
- this.button_.className = "motto-mobile-play-button";
355
- this.updateIcon();
356
- this.parent.appendChild(this.button_);
357
- this.eventManager.listen(this.button_, "click", () => {
358
- if (this.video.paused) {
359
- this.video.play();
360
- } else {
361
- this.video.pause();
362
- }
363
- });
364
- this.eventManager.listen(this.video, "play", () => this.updateIcon());
365
- this.eventManager.listen(this.video, "pause", () => this.updateIcon());
366
- }
367
- updateIcon() {
368
- if (this.video.paused) {
369
- this.button_.innerHTML = `
370
- <svg xmlns="http://www.w3.org/2000/svg" stroke-width="2" viewBox="0 0 24 24" fill="currentColor">
371
- <path stroke-width="2" fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" />
372
- </svg>
373
- `;
374
- this.button_.setAttribute("aria-label", "Play");
375
- } else {
376
- this.button_.innerHTML = `
377
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
378
- <path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" />
379
- </svg>
380
- `;
381
- this.button_.setAttribute("aria-label", "Pause");
382
- }
383
- }
384
- };
385
- var MobileSkipBackButton = class {
386
- constructor(parent, controls, onSkipBack) {
387
- this.parent = parent;
388
- this.controls = controls;
389
- this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
390
- if (!this.video) {
391
- console.error("MobileSkipBackButton: No video element found");
392
- return;
393
- }
394
- this.eventManager = { listen: (element, event, handler) => {
395
- element.addEventListener(event, handler);
396
- } };
397
- this.button_ = document.createElement("button");
398
- this.button_.className = "motto-mobile-skip-button";
399
- this.button_.innerHTML = `
400
- <svg width="20px" stroke-width="2" height="20px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
401
- <path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
402
- <path d="M9 9L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
403
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
404
- <path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
405
- </svg>
406
- `;
407
- this.button_.setAttribute("aria-label", "Skip back 15 seconds");
408
- this.parent.appendChild(this.button_);
409
- this.eventManager.listen(this.button_, "click", () => {
410
- const newTime = Math.max(0, this.video.currentTime - 15);
411
- this.video.currentTime = newTime;
412
- onSkipBack?.(newTime);
413
- });
414
- }
415
- };
416
- var MobileSkipForwardButton = class {
417
- constructor(parent, controls, onSkipForward) {
418
- this.parent = parent;
419
- this.controls = controls;
420
- this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
421
- if (!this.video) {
422
- console.error("MobileSkipForwardButton: No video element found");
423
- return;
424
- }
425
- this.eventManager = { listen: (element, event, handler) => {
426
- element.addEventListener(event, handler);
427
- } };
428
- this.button_ = document.createElement("button");
429
- this.button_.className = "motto-mobile-skip-button";
430
- this.button_.innerHTML = `
431
- <svg fill="none" height="20" stroke-width="2" viewBox="0 0 24 24" width="20" xmlns="http://www.w3.org/2000/svg">
432
- <path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
433
- <path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
434
- <path d="M9 9L9 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
435
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
436
- </svg>
437
- `;
438
- this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
439
- this.parent.appendChild(this.button_);
440
- this.eventManager.listen(this.button_, "click", () => {
441
- const newTime = Math.min(this.video.duration || 0, this.video.currentTime + 15);
442
- this.video.currentTime = newTime;
443
- onSkipForward?.(newTime);
444
- });
445
- }
446
- };
447
- var MobileControlsContainer = class {
448
- constructor(parent, controls, onSkipBack, onSkipForward) {
449
- this.parent = parent;
450
- this.controls = controls;
451
- if (!parent) {
452
- console.error("MobileControlsContainer: No parent element provided");
453
- return;
454
- }
455
- this.container_ = document.createElement("div");
456
- this.container_.className = "motto-mobile-controls-overlay";
457
- const controlsGroup = document.createElement("div");
458
- controlsGroup.className = "motto-mobile-controls-group";
459
- new MobileSkipBackButton(controlsGroup, controls, onSkipBack);
460
- new MobilePlayButton(controlsGroup, controls);
461
- new MobileSkipForwardButton(controlsGroup, controls, onSkipForward);
462
- this.container_.appendChild(controlsGroup);
463
- this.parent.appendChild(this.container_);
464
- this.setupVisibilitySync();
465
- }
466
- setupVisibilitySync() {
467
- setTimeout(() => {
468
- this.syncVisibility();
469
- this.observer = new MutationObserver((mutations) => {
470
- mutations.forEach((mutation) => {
471
- if (mutation.type === "attributes" && mutation.attributeName === "class") {
472
- this.syncVisibility();
473
- }
474
- });
475
- });
476
- this.observer.observe(this.parent, {
477
- attributes: true,
478
- attributeFilter: ["class"]
479
- });
480
- const video = this.controls?.getVideo?.() || this.parent.querySelector("video");
481
- if (video) {
482
- video.addEventListener("play", () => {
483
- setTimeout(() => this.syncVisibility(), 50);
484
- });
485
- video.addEventListener("pause", () => {
486
- setTimeout(() => this.syncVisibility(), 50);
487
- });
488
- }
489
- }, 1e3);
490
- }
491
- syncVisibility() {
492
- const mainContainer = this.parent;
493
- const hasNoCursor = mainContainer.classList.contains("no-cursor");
494
- const video = this.controls?.getVideo?.() || this.parent.querySelector("video");
495
- const isVideoPaused = video ? video.paused : false;
496
- const isControlsVisible = !hasNoCursor || isVideoPaused;
497
- if (this.container_) {
498
- if (isControlsVisible) {
499
- this.container_.style.opacity = "1";
500
- this.container_.style.pointerEvents = "none";
501
- } else {
502
- this.container_.style.opacity = "0";
503
- this.container_.style.pointerEvents = "none";
504
- }
505
- }
506
- }
507
- isElementVisible(element) {
508
- const style = window.getComputedStyle(element);
509
- const hasHiddenClass = element.classList.contains("shaka-hidden") || element.classList.contains("hidden") || element.classList.contains("shaka-fade-out");
510
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && !element.hidden && !hasHiddenClass;
511
- }
512
- };
513
- var MobileControlsContainerFactory = class {
514
- constructor(onSkipBack, onSkipForward) {
515
- this.onSkipBack = onSkipBack;
516
- this.onSkipForward = onSkipForward;
517
- }
518
- create(rootElement, controls) {
519
- return new MobileControlsContainer(rootElement, controls, this.onSkipBack, this.onSkipForward);
520
- }
521
- };
522
- var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward) => {
1460
+ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale = "en") => {
523
1461
  const uiRef = useRef4(null);
524
1462
  const registeredElements = useRef4(/* @__PURE__ */ new Set());
525
1463
  const initializeUI = useCallback5(async () => {
526
1464
  if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
527
1465
  return null;
528
1466
  }
529
- const isMobile = window.innerWidth <= 767 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
530
1467
  if (!registeredElements.current.has("skip_back_button")) {
531
- ShakaUI.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack));
1468
+ ShakaUI.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack, iconSizes?.skipButtons));
532
1469
  registeredElements.current.add("skip_back_button");
533
1470
  }
534
1471
  if (!registeredElements.current.has("skip_forward_button")) {
535
- ShakaUI.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward));
1472
+ ShakaUI.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward, iconSizes?.skipButtons));
536
1473
  registeredElements.current.add("skip_forward_button");
537
1474
  }
538
- if (isMobile) {
539
- if (!registeredElements.current.has("mobile_controls_container")) {
540
- ShakaUI.Controls.registerElement("mobile_controls_container", new MobileControlsContainerFactory(onSkipBack, onSkipForward));
541
- registeredElements.current.add("mobile_controls_container");
542
- }
543
- }
544
1475
  const ui = new ShakaUI.Overlay(playerRef.current, containerRef.current, videoRef.current);
545
1476
  uiRef.current = ui;
546
- const controlPanelElements = isMobile ? [
547
- "mute",
548
- "time_and_duration",
549
- "spacer",
550
- "fullscreen",
551
- "overflow_menu"
552
- ] : [
553
- "skip_back_button",
554
- "play_pause",
555
- "skip_forward_button",
1477
+ if (locale !== "en") {
1478
+ try {
1479
+ ui.getControls().getLocalization().changeLocale([locale]);
1480
+ console.log(`Set locale to '${locale}'`);
1481
+ } catch (error) {
1482
+ console.warn(`Failed to set locale to '${locale}', falling back to 'en':`, error);
1483
+ }
1484
+ }
1485
+ const isMobile = window.innerWidth <= 767;
1486
+ const controlPanelElements = [
1487
+ ...isMobile ? [] : ["skip_back_button"],
1488
+ ...isMobile ? [] : ["play_pause"],
1489
+ ...isMobile ? [] : ["skip_forward_button"],
556
1490
  "mute",
557
- "volume",
1491
+ ...isMobile ? [] : ["volume"],
1492
+ // Only include volume on desktop
558
1493
  "time_and_duration",
559
1494
  "spacer",
560
1495
  "fullscreen",
1496
+ "cast",
1497
+ // Always show cast button
561
1498
  "overflow_menu"
562
1499
  ];
563
1500
  const uiConfig = {
@@ -570,35 +1507,58 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
570
1507
  // Progress/played portion (white)
571
1508
  },
572
1509
  controlPanelElements,
573
- ...chromecastConfig?.receiverApplicationId && {
574
- "castReceiverAppId": chromecastConfig.receiverApplicationId,
575
- "castAndroidReceiverCompatible": false
576
- }
1510
+ addBigPlayButton: isMobile,
1511
+ // For now, Chromecast via Shaka must use the Motto receiver that runs on the legacy cast SDK (2.0), because
1512
+ // Shaka does not support the newer Cast SDK (3.0+) in its native integration.
1513
+ castReceiverAppId: "EC900D4D",
1514
+ castAndroidReceiverCompatible: true,
1515
+ // Enable Android TV compatibility
1516
+ overflowMenuButtons: [
1517
+ "quality",
1518
+ "picture_in_picture",
1519
+ "playback_rate"
1520
+ ]
577
1521
  };
578
- if (chromecastConfig?.receiverApplicationId) {
579
- uiConfig.castReceiverAppId = chromecastConfig.receiverApplicationId;
580
- uiConfig.castAndroidReceiverCompatible = false;
581
- }
582
1522
  ui.configure(uiConfig);
583
1523
  if (isMobile) {
584
- setTimeout(() => {
585
- const container = containerRef.current;
586
- const video = videoRef.current;
587
- if (container && video) {
588
- new MobileControlsContainer(container, { getVideo: () => video }, onSkipBack, onSkipForward);
1524
+ const customizeBigPlayButton = () => {
1525
+ const bigPlayButton = containerRef.current?.querySelector(".shaka-big-play-button");
1526
+ if (bigPlayButton && !bigPlayButton.hasAttribute("data-customized")) {
1527
+ const buttonSize = iconSizes?.bigPlayButton || 40;
1528
+ bigPlayButton.innerHTML = renderIcon(BigPlayIcon, { size: buttonSize });
1529
+ bigPlayButton.setAttribute("data-customized", "true");
1530
+ const buttonElement = bigPlayButton;
1531
+ buttonElement.style.display = "flex";
1532
+ buttonElement.style.alignItems = "center";
1533
+ buttonElement.style.justifyContent = "center";
589
1534
  }
590
- }, 500);
1535
+ };
1536
+ setTimeout(customizeBigPlayButton, 100);
1537
+ const observer = new MutationObserver(() => {
1538
+ customizeBigPlayButton();
1539
+ });
1540
+ if (containerRef.current) {
1541
+ observer.observe(containerRef.current, {
1542
+ childList: true,
1543
+ subtree: true,
1544
+ attributes: false
1545
+ });
1546
+ }
591
1547
  }
592
1548
  return ui;
593
- }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward]);
594
- const destroyUI = useCallback5(() => {
595
- if (uiRef.current) {
1549
+ }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale]);
1550
+ const destroyUI = useCallback5(async () => {
1551
+ const uiInstance = uiRef.current;
1552
+ if (uiInstance) {
596
1553
  try {
597
- uiRef.current.destroy();
1554
+ await uiInstance.destroy();
598
1555
  } catch (error) {
599
1556
  console.error("Error destroying UI:", error);
1557
+ } finally {
1558
+ if (uiRef.current === uiInstance) {
1559
+ uiRef.current = null;
1560
+ }
600
1561
  }
601
- uiRef.current = null;
602
1562
  }
603
1563
  }, []);
604
1564
  return {
@@ -637,128 +1597,149 @@ var useEventHandlers = (videoRef, handlers) => {
637
1597
  };
638
1598
  };
639
1599
 
640
- // src/hooks/useLiveBadge.ts
641
- import { useEffect, useState, useRef as useRef5 } from "react";
642
- var useLiveBadge = (playerRef, options = {}) => {
643
- const [isLive, setIsLive] = useState(false);
644
- const [isVisible, setIsVisible] = useState(false);
645
- const intervalRef = useRef5(null);
646
- const { enabled = true, onLiveStateChange } = options;
647
- const checkLiveStatus = () => {
648
- if (!playerRef.current || !enabled) {
649
- return;
1600
+ // src/hooks/usePosterFallback.ts
1601
+ import { useEffect, useState as useState2 } from "react";
1602
+
1603
+ // src/hooks/useLiveIndicator.ts
1604
+ import { useEffect as useEffect2, useRef as useRef6 } from "react";
1605
+ var useLiveIndicator = (containerRef, playerRef, options = {}) => {
1606
+ const observerRef = useRef6(null);
1607
+ const intervalRef = useRef6(null);
1608
+ const lastStatusRef = useRef6(null);
1609
+ const {
1610
+ enabled = true,
1611
+ indicatorColor = "#ff0000",
1612
+ indicatorSize = 8,
1613
+ showPulseAnimation = true,
1614
+ liveThresholdSeconds = 15,
1615
+ onLiveStatusChange
1616
+ } = options;
1617
+ const getLiveStatus = (player) => {
1618
+ if (!player) {
1619
+ return { isLive: false, isNearEdge: false };
650
1620
  }
651
1621
  try {
652
- const player = playerRef.current;
653
- if (!player.getManifest || !player.getPresentationTimeline || typeof player.getPresentationTimeline !== "function") {
654
- return;
655
- }
656
- const manifest = player.getManifest();
657
- if (!manifest) {
658
- return;
1622
+ if (typeof player.isLive !== "function") {
1623
+ return { isLive: false, isNearEdge: false };
659
1624
  }
660
- const timeline = player.getPresentationTimeline();
661
- if (!timeline || typeof timeline.isLive !== "function") {
662
- return;
1625
+ const isLiveStream = player.isLive();
1626
+ if (!isLiveStream) return { isLive: false, isNearEdge: false };
1627
+ const videoElement = player.getMediaElement?.();
1628
+ if (!videoElement) return { isLive: true, isNearEdge: false };
1629
+ if (typeof player.seekRange !== "function") {
1630
+ return { isLive: true, isNearEdge: false };
663
1631
  }
664
- const liveStatus = timeline.isLive();
665
- if (liveStatus !== isLive) {
666
- setIsLive(liveStatus);
667
- setIsVisible(liveStatus);
668
- onLiveStateChange?.(liveStatus);
1632
+ const seekRange = player.seekRange();
1633
+ if (!seekRange || seekRange.end === void 0) {
1634
+ return { isLive: true, isNearEdge: false };
669
1635
  }
1636
+ const liveEdge = seekRange.end;
1637
+ const currentTime = videoElement.currentTime;
1638
+ const timeBehindLive = liveEdge - currentTime;
1639
+ return {
1640
+ isLive: true,
1641
+ isNearEdge: timeBehindLive <= liveThresholdSeconds,
1642
+ liveEdge
1643
+ };
670
1644
  } catch (error) {
671
- if (error instanceof Error && !error.message.includes("not a function")) {
672
- console.error("Error checking live status:", error);
673
- }
1645
+ console.error("Error checking live status:", error);
1646
+ return { isLive: false, isNearEdge: false };
674
1647
  }
675
1648
  };
676
- useEffect(() => {
677
- if (!enabled) {
678
- setIsLive(false);
679
- setIsVisible(false);
680
- return;
681
- }
682
- checkLiveStatus();
683
- intervalRef.current = setInterval(checkLiveStatus, 2e3);
684
- return () => {
685
- if (intervalRef.current) {
686
- clearInterval(intervalRef.current);
687
- intervalRef.current = null;
688
- }
689
- };
690
- }, [enabled, playerRef.current]);
691
- useEffect(() => {
692
- return () => {
693
- if (intervalRef.current) {
694
- clearInterval(intervalRef.current);
1649
+ const seekToLiveEdge = () => {
1650
+ const player = playerRef.current;
1651
+ if (!player) return;
1652
+ try {
1653
+ if (typeof player.seekRange !== "function") return;
1654
+ const seekRange = player.seekRange();
1655
+ if (!seekRange || seekRange.end === void 0) return;
1656
+ const liveEdge = seekRange.end;
1657
+ const videoElement = player.getMediaElement?.();
1658
+ if (videoElement) {
1659
+ videoElement.currentTime = liveEdge;
695
1660
  }
696
- };
697
- }, []);
698
- const hideBadge = () => setIsVisible(false);
699
- const showBadge = () => setIsVisible(true);
700
- return {
701
- isLive,
702
- isVisible,
703
- hideBadge,
704
- showBadge,
705
- checkLiveStatus
1661
+ } catch (error) {
1662
+ console.error("Error seeking to live edge:", error);
1663
+ }
706
1664
  };
707
- };
708
-
709
- // src/hooks/usePosterFallback.ts
710
- import { useEffect as useEffect2, useState as useState2 } from "react";
711
-
712
- // src/hooks/useLiveIndicator.ts
713
- import { useEffect as useEffect3, useRef as useRef7 } from "react";
714
- var useLiveIndicator = (containerRef, options = {}) => {
715
- const observerRef = useRef7(null);
716
- const {
717
- enabled = true,
718
- indicatorColor = "#ff0000",
719
- indicatorSize = 8,
720
- showPulseAnimation = true
721
- } = options;
722
- useEffect3(() => {
1665
+ useEffect2(() => {
723
1666
  if (!containerRef.current || !enabled) {
724
1667
  return;
725
1668
  }
726
- const addLiveIndicator = (currentTimeElement) => {
727
- if (currentTimeElement.querySelector(".live-indicator-dot")) {
1669
+ const updateLiveIndicator = (currentTimeElement, status) => {
1670
+ const parent = currentTimeElement.parentElement;
1671
+ if (!parent) return;
1672
+ const existingContainer = parent.querySelector(".live-indicator-container");
1673
+ const isCurrentlyNearEdge = existingContainer?.getAttribute("data-near-edge") === "true";
1674
+ if (existingContainer && status.isNearEdge === isCurrentlyNearEdge) {
728
1675
  return;
729
1676
  }
1677
+ if (existingContainer) {
1678
+ existingContainer.remove();
1679
+ }
1680
+ const container = document.createElement("span");
1681
+ container.className = "live-indicator-container";
1682
+ container.setAttribute("data-near-edge", status.isNearEdge.toString());
1683
+ container.style.cssText = `
1684
+ display: inline-flex;
1685
+ align-items: center;
1686
+ width: 80px;
1687
+ ${!status.isNearEdge ? "cursor: pointer;" : ""}
1688
+ `;
730
1689
  const indicator = document.createElement("span");
731
1690
  indicator.className = "live-indicator-dot";
732
1691
  indicator.style.cssText = `
733
1692
  display: inline-block;
734
1693
  width: ${indicatorSize}px;
735
1694
  height: ${indicatorSize}px;
736
- background-color: ${indicatorColor};
1695
+ background-color: ${status.isNearEdge ? indicatorColor : "#888888"};
737
1696
  border-radius: 50%;
738
1697
  margin-right: 6px;
739
- vertical-align: middle;
740
- ${showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
1698
+ ${status.isNearEdge && showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
741
1699
  `;
742
- currentTimeElement.insertBefore(indicator, currentTimeElement.firstChild);
1700
+ const liveText = document.createElement("span");
1701
+ liveText.className = "live-indicator-text";
1702
+ liveText.textContent = status.isNearEdge ? "LIVE" : "GO TO LIVE";
1703
+ container.appendChild(indicator);
1704
+ container.appendChild(liveText);
1705
+ if (!status.isNearEdge) {
1706
+ container.addEventListener("click", seekToLiveEdge);
1707
+ }
1708
+ if (status.isNearEdge) {
1709
+ parent.insertBefore(container, currentTimeElement);
1710
+ currentTimeElement.style.display = "none";
1711
+ } else {
1712
+ currentTimeElement.insertAdjacentElement("afterend", container);
1713
+ currentTimeElement.style.display = "";
1714
+ }
743
1715
  };
744
1716
  const removeLiveIndicator = (currentTimeElement) => {
745
- const indicator = currentTimeElement.querySelector(".live-indicator-dot");
746
- if (indicator) {
747
- indicator.remove();
1717
+ const parent = currentTimeElement.parentElement;
1718
+ if (!parent) return;
1719
+ const container = parent.querySelector(".live-indicator-container");
1720
+ if (container) {
1721
+ container.remove();
1722
+ currentTimeElement.style.display = "";
748
1723
  }
749
1724
  };
750
1725
  const checkForLiveContent = () => {
751
1726
  const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
1727
+ const status = getLiveStatus(playerRef.current);
1728
+ const lastStatus = lastStatusRef.current;
1729
+ if (onLiveStatusChange && (!lastStatus || lastStatus.isLive !== status.isLive || lastStatus.isNearEdge !== status.isNearEdge)) {
1730
+ onLiveStatusChange(status);
1731
+ lastStatusRef.current = { isLive: status.isLive, isNearEdge: status.isNearEdge };
1732
+ }
752
1733
  currentTimeElements?.forEach((element) => {
753
- const textContent = element.textContent?.trim() || "";
754
- if (textContent.toLowerCase().includes("live")) {
755
- addLiveIndicator(element);
1734
+ if (status.isLive) {
1735
+ updateLiveIndicator(element, status);
756
1736
  } else {
757
1737
  removeLiveIndicator(element);
758
1738
  }
759
1739
  });
760
1740
  };
761
1741
  checkForLiveContent();
1742
+ intervalRef.current = setInterval(checkForLiveContent, 1e3);
762
1743
  observerRef.current = new MutationObserver((mutations) => {
763
1744
  let shouldCheck = false;
764
1745
  mutations.forEach((mutation) => {
@@ -784,31 +1765,289 @@ var useLiveIndicator = (containerRef, options = {}) => {
784
1765
  characterData: true,
785
1766
  characterDataOldValue: true
786
1767
  });
787
- const intervalId = setInterval(checkForLiveContent, 1e3);
788
1768
  return () => {
789
1769
  if (observerRef.current) {
790
1770
  observerRef.current.disconnect();
791
1771
  }
792
- clearInterval(intervalId);
1772
+ if (intervalRef.current) {
1773
+ clearInterval(intervalRef.current);
1774
+ }
793
1775
  };
794
- }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
1776
+ }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation, liveThresholdSeconds]);
795
1777
  return {
796
- // Expose method to manually trigger check if needed
797
- checkForLiveContent: () => {
798
- const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
799
- currentTimeElements?.forEach((element) => {
800
- const textContent = element.textContent?.trim() || "";
801
- if (textContent.toLowerCase().includes("live")) {
1778
+ seekToLiveEdge,
1779
+ getLiveStatus: () => getLiveStatus(playerRef.current)
1780
+ };
1781
+ };
1782
+
1783
+ // src/hooks/useKeyboardControls.ts
1784
+ import { useCallback as useCallback7, useEffect as useEffect3 } from "react";
1785
+ var useKeyboardControls = (videoRef, options = {}) => {
1786
+ const { skipBack, skipForward, enabled = true } = options;
1787
+ const isDesktop = useCallback7(() => {
1788
+ return window.innerWidth > 767 && !/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1789
+ }, []);
1790
+ const handleKeydown = useCallback7((event) => {
1791
+ if (!enabled || !isDesktop() || !videoRef.current) return;
1792
+ const activeElement = document.activeElement;
1793
+ if (activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable)) {
1794
+ return;
1795
+ }
1796
+ switch (event.key) {
1797
+ case "ArrowLeft":
1798
+ event.preventDefault();
1799
+ skipBack?.();
1800
+ break;
1801
+ case "ArrowRight":
1802
+ event.preventDefault();
1803
+ skipForward?.();
1804
+ break;
1805
+ case " ":
1806
+ case "Space":
1807
+ event.preventDefault();
1808
+ if (videoRef.current.paused) {
1809
+ videoRef.current.play();
1810
+ } else {
1811
+ videoRef.current.pause();
802
1812
  }
1813
+ break;
1814
+ }
1815
+ }, [enabled, videoRef, skipBack, skipForward, isDesktop]);
1816
+ useEffect3(() => {
1817
+ if (!enabled || !isDesktop()) return;
1818
+ document.addEventListener("keydown", handleKeydown);
1819
+ return () => {
1820
+ document.removeEventListener("keydown", handleKeydown);
1821
+ };
1822
+ }, [handleKeydown, enabled, isDesktop]);
1823
+ return {
1824
+ isDesktop: isDesktop()
1825
+ };
1826
+ };
1827
+
1828
+ // src/hooks/useAdEvents.ts
1829
+ import { useCallback as useCallback8, useRef as useRef7 } from "react";
1830
+ var useAdEvents = (playerRef, handlers) => {
1831
+ const listenersRef = useRef7([]);
1832
+ const setupAdEventListeners = useCallback8(() => {
1833
+ const player = playerRef.current;
1834
+ if (!player) return;
1835
+ const adManager = player.getAdManager();
1836
+ if (!adManager) return;
1837
+ const onAdsManagerLoaded = (event) => {
1838
+ const adsManager = event.getAdsManager();
1839
+ const onAdStarted = () => {
1840
+ console.log("Ad started");
1841
+ handlers.onAdStart?.();
1842
+ };
1843
+ const onAdComplete = () => {
1844
+ console.log("Ad completed");
1845
+ handlers.onAdComplete?.();
1846
+ };
1847
+ const onAdError = (adErrorEvent) => {
1848
+ console.error("Ad error:", adErrorEvent.getError());
1849
+ handlers.onAdError?.(adErrorEvent.getError());
1850
+ };
1851
+ const onAdSkipped = () => {
1852
+ console.log("Ad skipped");
1853
+ handlers.onAdSkipped?.();
1854
+ };
1855
+ const onAdPaused = () => {
1856
+ console.log("Ad paused");
1857
+ handlers.onAdPaused?.();
1858
+ };
1859
+ const onAdResumed = () => {
1860
+ console.log("Ad resumed");
1861
+ handlers.onAdResumed?.();
1862
+ };
1863
+ const onAdProgress = (adProgressData) => {
1864
+ handlers.onAdProgress?.(adProgressData);
1865
+ };
1866
+ const onAllAdsCompleted = () => {
1867
+ console.log("All ads completed");
1868
+ handlers.onAllAdsCompleted?.();
1869
+ };
1870
+ const adEventListeners = [];
1871
+ if (window.google?.ima) {
1872
+ const AdEvent = window.google.ima.AdEvent.Type;
1873
+ const AdErrorEvent = window.google.ima.AdErrorEvent.Type;
1874
+ if (handlers.onAdStart) {
1875
+ adsManager.addEventListener(AdEvent.STARTED, onAdStarted);
1876
+ adEventListeners.push({ event: AdEvent.STARTED, listener: onAdStarted });
1877
+ }
1878
+ if (handlers.onAdComplete) {
1879
+ adsManager.addEventListener(AdEvent.COMPLETE, onAdComplete);
1880
+ adEventListeners.push({ event: AdEvent.COMPLETE, listener: onAdComplete });
1881
+ }
1882
+ if (handlers.onAdError) {
1883
+ adsManager.addEventListener(AdErrorEvent.AD_ERROR, onAdError);
1884
+ adEventListeners.push({ event: AdErrorEvent.AD_ERROR, listener: onAdError });
1885
+ }
1886
+ if (handlers.onAdSkipped) {
1887
+ adsManager.addEventListener(AdEvent.SKIPPED, onAdSkipped);
1888
+ adEventListeners.push({ event: AdEvent.SKIPPED, listener: onAdSkipped });
1889
+ }
1890
+ if (handlers.onAdPaused) {
1891
+ adsManager.addEventListener(AdEvent.PAUSED, onAdPaused);
1892
+ adEventListeners.push({ event: AdEvent.PAUSED, listener: onAdPaused });
1893
+ }
1894
+ if (handlers.onAdResumed) {
1895
+ adsManager.addEventListener(AdEvent.RESUMED, onAdResumed);
1896
+ adEventListeners.push({ event: AdEvent.RESUMED, listener: onAdResumed });
1897
+ }
1898
+ if (handlers.onAdProgress) {
1899
+ adsManager.addEventListener(AdEvent.AD_PROGRESS, onAdProgress);
1900
+ adEventListeners.push({ event: AdEvent.AD_PROGRESS, listener: onAdProgress });
1901
+ }
1902
+ if (handlers.onAllAdsCompleted) {
1903
+ adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, onAllAdsCompleted);
1904
+ adEventListeners.push({ event: AdEvent.ALL_ADS_COMPLETED, listener: onAllAdsCompleted });
1905
+ }
1906
+ listenersRef.current.push({
1907
+ adsManager,
1908
+ listeners: adEventListeners
1909
+ });
1910
+ }
1911
+ };
1912
+ try {
1913
+ player.addEventListener("ad-started", () => {
1914
+ console.log("Shaka ad-started event");
1915
+ handlers.onAdStart?.();
1916
+ });
1917
+ player.addEventListener("ad-complete", () => {
1918
+ console.log("Shaka ad-complete event");
1919
+ handlers.onAdComplete?.();
1920
+ });
1921
+ player.addEventListener("ad-skipped", () => {
1922
+ console.log("Shaka ad-skipped event");
1923
+ handlers.onAdSkipped?.();
1924
+ });
1925
+ player.addEventListener("ad-error", (event) => {
1926
+ console.error("Shaka ad-error event:", event);
1927
+ handlers.onAdError?.(event);
1928
+ });
1929
+ listenersRef.current.push({
1930
+ type: "shaka",
1931
+ player,
1932
+ events: ["ad-started", "ad-complete", "ad-skipped", "ad-error"]
803
1933
  });
1934
+ } catch (error) {
1935
+ console.warn("Error setting up ad event listeners:", error);
1936
+ }
1937
+ }, [playerRef, handlers]);
1938
+ const cleanupAdEventListeners = useCallback8(() => {
1939
+ try {
1940
+ listenersRef.current.forEach((listenerGroup) => {
1941
+ if (listenerGroup.type === "shaka" && listenerGroup.player) {
1942
+ listenerGroup.events.forEach((eventName) => {
1943
+ try {
1944
+ listenerGroup.player.removeEventListener(eventName, () => {
1945
+ });
1946
+ } catch (e) {
1947
+ console.warn(`Error removing ${eventName} listener:`, e);
1948
+ }
1949
+ });
1950
+ } else if (listenerGroup.adsManager && listenerGroup.listeners) {
1951
+ listenerGroup.listeners.forEach(({ event, listener }) => {
1952
+ try {
1953
+ listenerGroup.adsManager.removeEventListener(event, listener);
1954
+ } catch (e) {
1955
+ console.warn("Error removing ad listener:", e);
1956
+ }
1957
+ });
1958
+ }
1959
+ });
1960
+ listenersRef.current = [];
1961
+ } catch (error) {
1962
+ console.warn("Error cleaning up ad event listeners:", error);
804
1963
  }
1964
+ }, []);
1965
+ return {
1966
+ setupAdEventListeners,
1967
+ cleanupAdEventListeners
805
1968
  };
806
1969
  };
807
1970
 
1971
+ // src/Player.tsx
1972
+ import { twMerge as twMerge2 } from "tailwind-merge";
1973
+
1974
+ // src/utils/scriptLoader.ts
1975
+ var SCRIPT_CONFIGS = {
1976
+ ima: {
1977
+ src: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
1978
+ id: "ima-sdk",
1979
+ type: "text/javascript"
1980
+ },
1981
+ system73: {
1982
+ src: "//cdn.s73cloud.com/4/s73-sdk-shakaplayer.js",
1983
+ id: "system73-sdk",
1984
+ type: "application/javascript"
1985
+ }
1986
+ };
1987
+ function loadScript(config) {
1988
+ return new Promise((resolve, reject) => {
1989
+ if (document.getElementById(config.id)) {
1990
+ resolve();
1991
+ return;
1992
+ }
1993
+ const script = document.createElement("script");
1994
+ script.id = config.id;
1995
+ script.src = config.src;
1996
+ script.type = config.type || "text/javascript";
1997
+ script.async = true;
1998
+ script.onload = () => resolve();
1999
+ script.onerror = () => reject(new Error(`Failed to load script: ${config.src}`));
2000
+ document.head.appendChild(script);
2001
+ });
2002
+ }
2003
+ function getRequiredScriptLoaders(needsIma, needsSystem73) {
2004
+ const loaders = [];
2005
+ if (needsIma) {
2006
+ loaders.push(loadScript(SCRIPT_CONFIGS.ima));
2007
+ }
2008
+ if (needsSystem73) {
2009
+ loaders.push(loadScript(SCRIPT_CONFIGS.system73));
2010
+ }
2011
+ return loaders;
2012
+ }
2013
+ async function loadScripts(scriptLoaders) {
2014
+ if (scriptLoaders.length === 0) {
2015
+ return;
2016
+ }
2017
+ try {
2018
+ await Promise.all(scriptLoaders);
2019
+ } catch (error) {
2020
+ console.error("Error loading scripts:", error);
2021
+ throw error;
2022
+ }
2023
+ }
2024
+ function waitForGlobal(globalName, timeout = 5e3) {
2025
+ return new Promise((resolve, reject) => {
2026
+ const startTime = Date.now();
2027
+ function checkGlobal() {
2028
+ const global = window[globalName];
2029
+ if (global) {
2030
+ resolve(global);
2031
+ return;
2032
+ }
2033
+ if (Date.now() - startTime > timeout) {
2034
+ reject(new Error(`Timeout waiting for global: ${globalName}`));
2035
+ return;
2036
+ }
2037
+ setTimeout(checkGlobal, 100);
2038
+ }
2039
+ checkGlobal();
2040
+ });
2041
+ }
2042
+ async function waitForGlobals(globalNames, timeout = 5e3) {
2043
+ const promises = globalNames.map((name) => waitForGlobal(name, timeout));
2044
+ await Promise.all(promises);
2045
+ }
2046
+
808
2047
  // src/components/Loading.tsx
809
2048
  import { twMerge } from "tailwind-merge";
810
- import { jsx, jsxs } from "react/jsx-runtime";
811
- var Loading = ({ className }) => /* @__PURE__ */ jsxs(
2049
+ import { jsx as jsx4 } from "react/jsx-runtime";
2050
+ var Loading = ({ className }) => /* @__PURE__ */ jsx4(
812
2051
  "div",
813
2052
  {
814
2053
  className: twMerge(
@@ -816,17 +2055,36 @@ var Loading = ({ className }) => /* @__PURE__ */ jsxs(
816
2055
  className
817
2056
  ),
818
2057
  role: "status",
819
- children: [
820
- /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-white" }),
821
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading..." })
822
- ]
2058
+ children: /* @__PURE__ */ jsx4("div", { className: " flex justify-center items-center", children: /* @__PURE__ */ jsx4(
2059
+ "svg",
2060
+ {
2061
+ className: "shaka-spinner-svg animate-spin h-12 w-12",
2062
+ viewBox: "0 0 64 64",
2063
+ xmlns: "http://www.w3.org/2000/svg",
2064
+ children: /* @__PURE__ */ jsx4(
2065
+ "circle",
2066
+ {
2067
+ className: "shaka-spinner-path",
2068
+ cx: "32",
2069
+ cy: "32",
2070
+ r: "28",
2071
+ strokeWidth: "4",
2072
+ strokeLinecap: "round",
2073
+ stroke: "currentColor",
2074
+ fill: "none",
2075
+ strokeDasharray: "176",
2076
+ strokeDashoffset: "120"
2077
+ }
2078
+ )
2079
+ }
2080
+ ) })
823
2081
  }
824
2082
  );
825
2083
 
826
2084
  // src/components/ErrorScreen.tsx
827
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
828
- var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx2("div", { className: "w-full h-full md:rounded-2xl! aspect-video bg-black", children: /* @__PURE__ */ jsxs2("div", { className: "bg-[#151515] text-white w-full h-full flex justify-stretch items-center", children: [
829
- /* @__PURE__ */ jsx2(
2085
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2086
+ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx5("div", { className: "w-full h-full md:rounded-2xl! aspect-video bg-black flex", children: /* @__PURE__ */ jsxs3("div", { className: "bg-[#151515] text-white w-full h-full flex justify-center items-center", children: [
2087
+ /* @__PURE__ */ jsx5(
830
2088
  "svg",
831
2089
  {
832
2090
  className: "w-24 h-24 m-6",
@@ -836,7 +2094,7 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx2("div", { clas
836
2094
  style: { width: 96 },
837
2095
  viewBox: "0 0 24 24",
838
2096
  xmlns: "http://www.w3.org/2000/svg",
839
- children: /* @__PURE__ */ jsx2(
2097
+ children: /* @__PURE__ */ jsx5(
840
2098
  "path",
841
2099
  {
842
2100
  d: "M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z",
@@ -846,66 +2104,22 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx2("div", { clas
846
2104
  )
847
2105
  }
848
2106
  ),
849
- /* @__PURE__ */ jsxs2("div", { children: [
850
- /* @__PURE__ */ jsx2("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
851
- /* @__PURE__ */ jsx2("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
2107
+ /* @__PURE__ */ jsxs3("div", { children: [
2108
+ /* @__PURE__ */ jsx5("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
2109
+ /* @__PURE__ */ jsx5("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
852
2110
  ] })
853
2111
  ] }) });
854
2112
 
855
2113
  // src/components/Title.tsx
856
- import { jsx as jsx3 } from "react/jsx-runtime";
857
- var Title = ({ title }) => /* @__PURE__ */ jsx3("div", { className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4", children: /* @__PURE__ */ jsx3("h2", { className: "text-white text-xl font-semibold", children: title }) });
858
-
859
- // src/components/LiveBadge.tsx
860
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
861
- var LiveBadge = ({
862
- isVisible,
863
- position = "top-right",
864
- className = "",
865
- style = {},
866
- text = "LIVE"
867
- }) => {
868
- if (!isVisible) return null;
869
- const positionClasses = {
870
- "top-left": "top-4 left-4",
871
- "top-right": "top-4 right-4",
872
- "bottom-left": "bottom-4 left-4",
873
- "bottom-right": "bottom-4 right-4"
874
- };
875
- return /* @__PURE__ */ jsx4(
876
- "div",
877
- {
878
- className: `
879
- absolute z-50
880
- ${positionClasses[position]}
881
- bg-red-600 text-white
882
- px-2 py-1
883
- rounded-md
884
- text-xs font-bold
885
- uppercase tracking-wide
886
- shadow-lg
887
- animate-pulse
888
- pointer-events-none
889
- ${className}
890
- `,
891
- style,
892
- children: /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1", children: [
893
- /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 bg-white rounded-full animate-pulse" }),
894
- text
895
- ] })
896
- }
897
- );
898
- };
899
-
900
- // src/styles.css
901
- styleInject('/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wide: 0.025em;\n --tracking-widest: 0.1em;\n --radius-md: 0.375rem;\n --radius-2xl: 1rem;\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --aspect-video: 16 / 9;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-auto {\n pointer-events: auto;\n }\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-4 {\n top: calc(var(--spacing) * 4);\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .bottom-0 {\n bottom: calc(var(--spacing) * 0);\n }\n .bottom-4 {\n bottom: calc(var(--spacing) * 4);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .z-10 {\n z-index: 10;\n }\n .z-50 {\n z-index: 50;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .m-6 {\n margin: calc(var(--spacing) * 6);\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-3 {\n margin-top: calc(var(--spacing) * 3);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .aspect-video {\n aspect-ratio: var(--aspect-video);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-8 {\n height: calc(var(--spacing) * 8);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-8 {\n width: calc(var(--spacing) * 8);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-full {\n width: 100%;\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .auto-cols-max {\n grid-auto-columns: max-content;\n }\n .grid-flow-col {\n grid-auto-flow: column;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-stretch {\n justify-content: stretch;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-5 {\n gap: calc(var(--spacing) * 5);\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-white {\n border-color: var(--color-white);\n }\n .bg-\\[\\#151515\\] {\n background-color: #151515;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-gradient-to-t {\n --tw-gradient-position: to top in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black\\/70 {\n --tw-gradient-from: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-transparent {\n --tw-gradient-to: transparent;\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .bg-no-repeat {\n background-repeat: no-repeat;\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .font-mono {\n font-family: var(--font-mono);\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-5xl {\n font-size: var(--text-5xl);\n line-height: var(--tw-leading, var(--text-5xl--line-height));\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .text-\\[10px\\] {\n font-size: 10px;\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wide {\n --tw-tracking: var(--tracking-wide);\n letter-spacing: var(--tracking-wide);\n }\n .tracking-widest {\n --tw-tracking: var(--tracking-widest);\n letter-spacing: var(--tracking-widest);\n }\n .text-white {\n color: var(--color-white);\n }\n .uppercase {\n text-transform: uppercase;\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .md\\:rounded-2xl {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl);\n }\n }\n .md\\:rounded-2xl\\! {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl) !important;\n }\n }\n .md\\:text-base {\n @media (width >= 48rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n .md\\:text-sm {\n @media (width >= 48rem) {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n }\n .md\\:text-xl {\n @media (width >= 48rem) {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n }\n}\n@layer components {\n .motto-video-container {\n position: relative;\n width: 100%;\n min-height: 300px;\n }\n @supports (aspect-ratio: 16/9) {\n .motto-video-container {\n min-height: auto;\n }\n }\n .motto-video-responsive {\n position: absolute;\n top: calc(var(--spacing) * 0);\n left: calc(var(--spacing) * 0);\n height: 100%;\n width: 100%;\n }\n .motto-skip-button {\n position: absolute;\n top: calc(1/2 * 100%);\n z-index: 10;\n display: flex;\n height: calc(var(--spacing) * 16);\n width: calc(var(--spacing) * 16);\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n color: var(--color-white);\n opacity: 80%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 110%;\n --tw-scale-y: 110%;\n --tw-scale-z: 110%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n &:hover {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .motto-skip-button-back {\n left: calc(var(--spacing) * 5);\n }\n .motto-skip-button-forward {\n right: calc(var(--spacing) * 5);\n }\n .motto-mobile-controls-overlay {\n position: absolute;\n inset: calc(var(--spacing) * 0);\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 300ms;\n transition-duration: 300ms;\n pointer-events: none;\n }\n .motto-mobile-controls-group {\n display: flex;\n align-items: center;\n gap: calc(var(--spacing) * 8);\n opacity: 100%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: none;\n }\n .motto-mobile-play-button {\n display: flex;\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-play-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-play-button svg {\n height: calc(var(--spacing) * 7);\n width: calc(var(--spacing) * 7);\n }\n .motto-mobile-skip-button {\n display: flex;\n height: calc(var(--spacing) * 10);\n width: calc(var(--spacing) * 10);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-skip-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-skip-button svg {\n height: calc(var(--spacing) * 6);\n width: calc(var(--spacing) * 6);\n }\n}\n@media (min-width: 768px) {\n .motto-mobile-controls-overlay {\n display: none !important;\n }\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-button[title*="Skip back"],\n .shaka-controls-container .shaka-button[title*="Skip forward"],\n .shaka-controls-container .shaka-button[aria-label*="Skip back"],\n .shaka-controls-container .shaka-button[aria-label*="Skip forward"],\n .shaka-controls-container button[title*="Skip back"],\n .shaka-controls-container button[title*="Skip forward"],\n .shaka-controls-container button[aria-label*="Skip back"],\n .shaka-controls-container button[aria-label*="Skip forward"],\n .motto-native-skip-button:not(.motto-mobile-skip-button),\n .motto-skip-back-button:not(.motto-mobile-skip-button),\n .motto-skip-forward-button:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button),\n button[title*="Skip back"]:not(.motto-mobile-skip-button),\n button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button) {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n width: 0 !important;\n height: 0 !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n .motto-mobile-skip-button {\n display: flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n.shaka-seek-bar-container {\n height: 6px !important;\n width: 100% !important;\n margin: 8px 0 !important;\n border-radius: 4px !important;\n position: relative !important;\n border-top: none !important;\n border-bottom: none !important;\n box-shadow: none !important;\n}\n.shaka-seek-bar {\n height: 6px !important;\n width: 100% !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n background: transparent !important;\n cursor: pointer !important;\n border: none !important;\n outline: none !important;\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n border-radius: 4px !important;\n}\n.shaka-seek-bar::-webkit-slider-runnable-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-moz-range-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-webkit-slider-thumb {\n -webkit-appearance: none !important;\n appearance: none !important;\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.shaka-seek-bar::-moz-range-thumb {\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.motto-skip-back-button,\n.motto-skip-forward-button,\n.motto-native-skip-button {\n background: transparent !important;\n border: none !important;\n padding: 4px !important;\n margin: 0px !important;\n cursor: pointer !important;\n color: #ffffff !important;\n transition: all 0.2s ease !important;\n min-width: 32px !important;\n height: 32px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n border-radius: 4px !important;\n width: 25px;\n}\n.motto-skip-back-button:hover,\n.motto-skip-forward-button:hover,\n.motto-native-skip-button:hover {\n opacity: 0.8 !important;\n background: transparent !important;\n transform: scale(1.05) !important;\n}\n.motto-skip-back-button:active,\n.motto-skip-forward-button:active,\n.motto-native-skip-button:active {\n transform: scale(0.95) !important;\n}\n.motto-skip-back-button svg,\n.motto-skip-forward-button svg,\n.motto-native-skip-button svg {\n width: 24px !important;\n height: 24px !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-play-button,\n .shaka-controls-container .shaka-pause-button {\n display: none !important;\n }\n}\n.shaka-spinner-svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-spinner-path {\n stroke: white !important;\n fill: none !important;\n}\n.shaka-spinner-container {\n color: white !important;\n}\n.shaka-buffering-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner path {\n stroke: white !important;\n fill: none !important;\n}\n[data-shaka-player-container] .shaka-spinner,\n[data-shaka-player-container] .spinner {\n color: white !important;\n border-color: white !important;\n}\n.material-icons.shaka-spinner {\n color: white !important;\n}\n.shaka-controls-container .shaka-spinner,\n.shaka-video-container .shaka-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner svg,\n.shaka-video-container .shaka-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner path,\n.shaka-video-container .shaka-spinner path {\n stroke: white !important;\n}\n.motto-video-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n linear-gradient(\n 135deg,\n #1a1a1a 0%,\n #2d2d2d 100%);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: opacity 0.3s ease;\n}\n.motto-video-loading-overlay.hidden {\n opacity: 0;\n pointer-events: none;\n}\n.motto-video-loading-content {\n text-align: center;\n color: white;\n}\n.motto-video-loading-icon {\n width: 64px;\n height: 64px;\n margin-bottom: 16px;\n opacity: 0.7;\n}\n.motto-video-loading-text {\n font-size: 16px;\n font-weight: 500;\n margin-bottom: 8px;\n}\n.motto-video-loading-subtext {\n font-size: 14px;\n opacity: 0.7;\n}\n@keyframes pulse-live {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-gradient-position { syntax: "*"; inherits: false; }\n@property --tw-gradient-from { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-via { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-to { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-via-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-from-position { syntax: "<length-percentage>"; inherits: false; initial-value: 0%; }\n@property --tw-gradient-via-position { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }\n@property --tw-gradient-to-position { syntax: "<length-percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-tracking { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@property --tw-translate-x { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-y { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-z { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-duration { syntax: "*"; inherits: false; }\n@property --tw-scale-x { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-y { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-z { syntax: "*"; inherits: false; initial-value: 1; }\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
2114
+ import { jsx as jsx6 } from "react/jsx-runtime";
2115
+ var Title = ({ title }) => /* @__PURE__ */ jsx6("div", { className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4", children: /* @__PURE__ */ jsx6("h2", { className: "text-white text-xl font-semibold", children: title }) });
902
2116
 
903
2117
  // src/Player.tsx
904
- import { twMerge as twMerge2 } from "tailwind-merge";
905
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2118
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
906
2119
  var Player = forwardRef(
907
2120
  ({
908
2121
  src,
2122
+ managedMode = false,
909
2123
  autoPlay = false,
910
2124
  loop = false,
911
2125
  muted = false,
@@ -917,25 +2131,48 @@ var Player = forwardRef(
917
2131
  shakaConfig,
918
2132
  drmConfig,
919
2133
  muxConfig,
2134
+ system73Config,
920
2135
  imaConfig,
921
2136
  chromecastConfig,
922
2137
  qualityConfig,
923
2138
  seekbarConfig,
2139
+ iconSizes,
924
2140
  events,
2141
+ locale = "en",
925
2142
  containerClassName,
926
- ...props
2143
+ liveThresholdSeconds = 15,
2144
+ publicKey,
2145
+ auth,
2146
+ ...videoProps
927
2147
  }, ref) => {
928
2148
  const videoRef = useRef8(null);
929
2149
  const containerRef = useRef8(null);
930
- const adContainerRef = useRef8(null);
2150
+ const [isScriptsLoaded, setIsScriptsLoaded] = useState3(false);
2151
+ const [isInitialLoading, setIsInitialLoading] = useState3(true);
2152
+ const [bfResetKey, setBfResetKey] = useState3(0);
2153
+ const hasPlaylist = !!src && (typeof src === "string" || !!(src.url || src.drm?.widevine?.playlistUrl || src.drm?.playready?.playlistUrl || src.drm?.fairplay?.playlistUrl));
931
2154
  useImperativeHandle(ref, () => videoRef.current, []);
932
- const { playerRef, initializePlayer, destroyPlayer } = useShakePlayer({
2155
+ const { playerRef, initializePlayer, loadManifest, destroyPlayer, isRetrying } = useShakaPlayer({
933
2156
  src,
934
2157
  shakaConfig,
935
2158
  drmConfig,
936
2159
  onError: events?.onError,
937
- onPlayerReady: events?.onPlayerReady
2160
+ onPlayerReady: events?.onPlayerReady,
2161
+ muxConfig,
2162
+ onMuxReady: events?.onMuxReady,
2163
+ onMuxDataUpdate: events?.onMuxDataUpdate,
2164
+ publicKey,
2165
+ mottoToken: auth?.mottoToken,
2166
+ hasAds: !!imaConfig?.adTagUrl,
2167
+ hasSystem73: !!system73Config?.apiKey,
2168
+ apiToken: auth?.apiToken
938
2169
  });
2170
+ const {
2171
+ initializeMux,
2172
+ updateMuxData,
2173
+ handleMuxError,
2174
+ destroyMux
2175
+ } = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
939
2176
  const {
940
2177
  getAvailableQualities,
941
2178
  setQuality,
@@ -948,12 +2185,11 @@ var Player = forwardRef(
948
2185
  skipDuration,
949
2186
  shouldShowSkipControls
950
2187
  } = useSkipControls(videoRef, events?.onSkipBack, events?.onSkipForward);
951
- const {
952
- initializeMux,
953
- updateMuxData,
954
- handleMuxError,
955
- destroyMux
956
- } = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
2188
+ useKeyboardControls(videoRef, {
2189
+ skipBack,
2190
+ skipForward,
2191
+ enabled: true
2192
+ });
957
2193
  const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, {
958
2194
  onPlay: events?.onPlay,
959
2195
  onPause: events?.onPause,
@@ -969,109 +2205,230 @@ var Player = forwardRef(
969
2205
  chromecastConfig,
970
2206
  seekbarConfig,
971
2207
  events?.onSkipBack,
972
- events?.onSkipForward
2208
+ events?.onSkipForward,
2209
+ iconSizes,
2210
+ locale
973
2211
  );
974
- const { isLive, isVisible: isLiveBadgeVisible } = useLiveBadge(playerRef, {
975
- enabled: true,
976
- onLiveStateChange: (isLive2) => {
977
- events?.onLiveStateChange?.(isLive2);
978
- }
979
- });
980
- useLiveIndicator(containerRef, {
2212
+ const { getLiveStatus, seekToLiveEdge } = useLiveIndicator(containerRef, playerRef, {
981
2213
  enabled: true,
982
2214
  indicatorColor: "#ff0000",
983
2215
  indicatorSize: 8,
984
- showPulseAnimation: true
2216
+ showPulseAnimation: true,
2217
+ liveThresholdSeconds,
2218
+ onLiveStatusChange: events?.onLiveStatusChange
985
2219
  });
986
- const initializeAds = () => {
987
- if (!imaConfig || !playerRef.current || !videoRef.current) return;
988
- const adManager = playerRef.current.getAdManager();
989
- if (!adManager) return;
990
- adManager.addEventListener(shaka2.ads?.Utils?.AD_STARTED, () => {
991
- events?.onAdStart?.();
992
- });
993
- adManager.addEventListener(shaka2.ads?.Utils?.AD_COMPLETE, () => {
994
- events?.onAdComplete?.();
995
- });
996
- adManager.addEventListener(shaka2.ads?.Utils?.AD_ERROR, (event) => {
997
- events?.onAdError?.(event.detail);
998
- });
999
- if (imaConfig.adTagUrl) {
1000
- const adContainer = adContainerRef.current;
1001
- if (adContainer) {
1002
- adManager.initClientSide(adContainer, videoRef.current, imaConfig.adsRenderingSettings);
1003
- const adsRequest = {
1004
- adTagUrl: imaConfig.adTagUrl,
1005
- linearAdSlotWidth: imaConfig.linearAdSlotWidth || width || 640,
1006
- linearAdSlotHeight: imaConfig.linearAdSlotHeight || height || 360,
1007
- nonLinearAdSlotWidth: imaConfig.nonLinearAdSlotWidth || width || 640,
1008
- nonLinearAdSlotHeight: imaConfig.nonLinearAdSlotHeight || 150
1009
- };
1010
- adManager.requestClientSideAds(adsRequest);
1011
- }
2220
+ const { setupAdEventListeners, cleanupAdEventListeners } = useAdEvents(playerRef, {
2221
+ onAdStart: events?.onAdStart,
2222
+ onAdComplete: events?.onAdComplete,
2223
+ onAdError: events?.onAdError,
2224
+ onAdSkipped: events?.onAdSkipped,
2225
+ onAdPaused: events?.onAdPaused,
2226
+ onAdResumed: events?.onAdResumed,
2227
+ onAdProgress: events?.onAdProgress,
2228
+ onAllAdsCompleted: events?.onAllAdsCompleted
2229
+ });
2230
+ const initializeSystem73 = useCallback9((playerConfig) => {
2231
+ if (!system73Config?.apiKey || !window.S73ShakaPlayerWrapper) {
2232
+ return null;
1012
2233
  }
1013
- };
1014
- const initializeChromecast = () => {
1015
- if (!chromecastConfig?.enabled) {
2234
+ console.log("Initializing System73 SDK...");
2235
+ try {
2236
+ const s73Config = {
2237
+ apiKey: system73Config.apiKey,
2238
+ contentSteeringEndpoint: system73Config.contentSteeringEndpoint,
2239
+ channelId: system73Config.channelId
2240
+ };
2241
+ const wrapper = window.S73ShakaPlayerWrapper(s73Config, { shaka: shaka3 });
2242
+ wrapper.wrapPlayerConfig(playerConfig);
2243
+ console.log("System73 SDK initialized with config:", s73Config);
2244
+ return wrapper;
2245
+ } catch (error) {
2246
+ console.error("Error initializing System73 SDK:", error);
2247
+ return null;
2248
+ }
2249
+ }, [system73Config]);
2250
+ const initializeAds = useCallback9(async () => {
2251
+ if (!imaConfig?.adTagUrl || !playerRef.current || !videoRef.current || !uiRef.current) {
2252
+ return;
2253
+ }
2254
+ if (!window.google?.ima) {
2255
+ console.error("Google IMA SDK not available when trying to initialize ads");
1016
2256
  return;
1017
2257
  }
1018
2258
  try {
1019
- if (events?.onCastStateChange) {
1020
- setTimeout(() => events.onCastStateChange(false), 100);
2259
+ const player = playerRef.current;
2260
+ const video = videoRef.current;
2261
+ const ui = uiRef.current;
2262
+ const controls2 = ui.getControls();
2263
+ const container = controls2.getClientSideAdContainer();
2264
+ const adManager = player.getAdManager();
2265
+ if (!adManager) {
2266
+ console.error("Ad manager not available");
2267
+ return;
1021
2268
  }
2269
+ const google = window.google;
2270
+ let adsRenderingSettings = null;
2271
+ if (imaConfig.adsRenderingSettings) {
2272
+ adsRenderingSettings = imaConfig.adsRenderingSettings;
2273
+ } else if (autoPlay) {
2274
+ adsRenderingSettings = new google.ima.AdsRenderingSettings();
2275
+ adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
2276
+ }
2277
+ adManager.initClientSide(container, video, adsRenderingSettings);
2278
+ const adsRequest = new google.ima.AdsRequest();
2279
+ adsRequest.adTagUrl = imaConfig.adTagUrl;
2280
+ adManager.requestClientSideAds(adsRequest);
2281
+ setupAdEventListeners();
2282
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2283
+ await loadManifest();
1022
2284
  } catch (error) {
1023
- console.warn("Chromecast initialization failed:", error);
2285
+ console.error("Error initializing ads:", error);
1024
2286
  }
1025
- };
2287
+ }, [imaConfig, autoPlay, setupAdEventListeners, loadManifest]);
2288
+ useEffect4(() => {
2289
+ const loadRequiredScripts = async () => {
2290
+ try {
2291
+ const scriptLoaders = getRequiredScriptLoaders(!!imaConfig?.adTagUrl, !!system73Config?.apiKey);
2292
+ await loadScripts(scriptLoaders);
2293
+ const globalsToWait = [];
2294
+ if (imaConfig?.adTagUrl) {
2295
+ globalsToWait.push("google");
2296
+ }
2297
+ if (system73Config?.apiKey) {
2298
+ globalsToWait.push("S73ShakaPlayerWrapper");
2299
+ }
2300
+ if (globalsToWait.length > 0) {
2301
+ await waitForGlobals(globalsToWait);
2302
+ }
2303
+ setIsScriptsLoaded(true);
2304
+ } catch (error) {
2305
+ console.error("Error loading required scripts:", error);
2306
+ setIsScriptsLoaded(true);
2307
+ }
2308
+ };
2309
+ loadRequiredScripts();
2310
+ }, [imaConfig?.adTagUrl, system73Config?.apiKey]);
2311
+ useEffect4(() => {
2312
+ const onPageShow = (e) => {
2313
+ if (e && e.persisted) {
2314
+ setBfResetKey((k) => k + 1);
2315
+ }
2316
+ };
2317
+ window.addEventListener("pageshow", onPageShow);
2318
+ return () => window.removeEventListener("pageshow", onPageShow);
2319
+ }, []);
1026
2320
  useEffect4(() => {
1027
2321
  const video = videoRef.current;
1028
- if (!video) return;
2322
+ if (!video || !isScriptsLoaded) return;
1029
2323
  const initialize = async () => {
1030
2324
  try {
2325
+ console.log("\u{1F680} [Player] Starting initialization...");
2326
+ setIsInitialLoading(true);
2327
+ let system73Wrapper = null;
2328
+ if (system73Config?.apiKey && window.S73ShakaPlayerWrapper) {
2329
+ console.log("\u{1F4E6} [System73] Step 1: Initializing System73 wrapper with config");
2330
+ const playerConfig = { ...shakaConfig };
2331
+ system73Wrapper = initializeSystem73(playerConfig);
2332
+ if (system73Wrapper) {
2333
+ shakaConfig = playerConfig;
2334
+ console.log("\u2705 [System73] Step 1 complete: Wrapper created and config modified");
2335
+ }
2336
+ }
2337
+ console.log("\u{1F3AC} [Shaka] Step 2: Initializing Shaka Player (auto-load:", !system73Config?.apiKey && !imaConfig?.adTagUrl, ")");
1031
2338
  await initializePlayer(video);
2339
+ console.log("\u2705 [Shaka] Step 2 complete: Player initialized");
2340
+ if (system73Wrapper && playerRef.current) {
2341
+ console.log("\u{1F517} [System73] Step 3: Wrapping Shaka player with System73");
2342
+ system73Wrapper.wrapPlayer(playerRef.current);
2343
+ console.log("\u2705 [System73] Step 3 complete: Player wrapped");
2344
+ if (!imaConfig?.adTagUrl) {
2345
+ console.log("\u{1F4FA} [System73] Step 4: Loading manifest");
2346
+ await loadManifest();
2347
+ console.log("\u2705 [System73] Step 4 complete: Manifest loaded");
2348
+ } else {
2349
+ console.log("\u23ED\uFE0F [System73] Skipping manifest load - ads will handle it");
2350
+ }
2351
+ }
2352
+ console.log("\u{1F4CB} [Player] Setting up event listeners and quality tracking");
1032
2353
  setupEventListeners();
1033
2354
  const cleanupQuality = setupQualityTracking();
1034
2355
  configureQuality();
2356
+ console.log("\u{1F3A8} [UI] Initializing Shaka UI");
1035
2357
  await initializeUI();
1036
- initializeMux();
1037
- initializeAds();
1038
- initializeChromecast();
2358
+ console.log("\u2705 [UI] UI initialized");
2359
+ if (imaConfig?.adTagUrl && window.google?.ima) {
2360
+ console.log("\u{1F4E2} [Ads] Initializing ads (will load manifest after VAST fetch)");
2361
+ await initializeAds();
2362
+ console.log("\u2705 [Ads] Ads initialized and manifest loaded");
2363
+ }
2364
+ console.log("\u2728 [Player] Initialization complete!");
1039
2365
  } catch (error) {
1040
- console.error("Error during player initialization:", error);
2366
+ console.error("\u274C [Player] Error during initialization:", error);
1041
2367
  handleMuxError(error);
1042
2368
  }
1043
2369
  };
1044
2370
  initialize();
1045
2371
  return () => {
1046
2372
  cleanupEventListeners();
2373
+ cleanupAdEventListeners();
1047
2374
  destroyUI();
1048
2375
  destroyMux();
1049
2376
  destroyPlayer();
1050
2377
  };
1051
- }, [
1052
- src,
1053
- initializePlayer,
1054
- setupEventListeners,
1055
- setupQualityTracking,
1056
- configureQuality,
1057
- initializeUI,
1058
- initializeMux,
1059
- cleanupEventListeners,
1060
- destroyUI,
1061
- destroyMux,
1062
- destroyPlayer,
1063
- handleMuxError,
1064
- playerRef
1065
- ]);
2378
+ }, [managedMode ? hasPlaylist : src, isScriptsLoaded, bfResetKey, managedMode]);
2379
+ useEffect4(() => {
2380
+ const video = videoRef.current;
2381
+ if (!video) return;
2382
+ const onLoadStart = () => {
2383
+ setIsInitialLoading(true);
2384
+ };
2385
+ const onCanPlay = () => {
2386
+ setIsInitialLoading(false);
2387
+ };
2388
+ const onPlaying = () => {
2389
+ setIsInitialLoading(false);
2390
+ };
2391
+ video.addEventListener("loadstart", onLoadStart);
2392
+ video.addEventListener("canplay", onCanPlay);
2393
+ video.addEventListener("playing", onPlaying);
2394
+ return () => {
2395
+ video.removeEventListener("loadstart", onLoadStart);
2396
+ video.removeEventListener("canplay", onCanPlay);
2397
+ video.removeEventListener("playing", onPlaying);
2398
+ };
2399
+ }, []);
1066
2400
  useEffect4(() => {
1067
2401
  const video = videoRef.current;
1068
2402
  if (!video) return;
1069
2403
  video.autoplay = autoPlay;
1070
2404
  video.loop = loop;
1071
- video.muted = muted;
1072
2405
  video.controls = false;
1073
2406
  if (poster) video.poster = poster;
1074
- }, [autoPlay, loop, muted, poster]);
2407
+ }, [autoPlay, loop, muted, poster, imaConfig?.adTagUrl]);
2408
+ useEffect4(() => {
2409
+ const video = videoRef.current;
2410
+ if (!video) return;
2411
+ video.controls = false;
2412
+ video.setAttribute("controls", "false");
2413
+ video.removeAttribute("controls");
2414
+ const observer = new MutationObserver((mutations) => {
2415
+ mutations.forEach((mutation) => {
2416
+ if (mutation.type === "attributes" && mutation.attributeName === "controls") {
2417
+ if (video.hasAttribute("controls")) {
2418
+ video.removeAttribute("controls");
2419
+ video.controls = false;
2420
+ }
2421
+ }
2422
+ });
2423
+ });
2424
+ observer.observe(video, {
2425
+ attributes: true,
2426
+ attributeFilter: ["controls"]
2427
+ });
2428
+ return () => {
2429
+ observer.disconnect();
2430
+ };
2431
+ }, []);
1075
2432
  useImperativeHandle(ref, () => ({
1076
2433
  ...videoRef.current,
1077
2434
  // Custom methods for quality control
@@ -1082,27 +2439,30 @@ var Player = forwardRef(
1082
2439
  skipForward,
1083
2440
  // Mux methods
1084
2441
  updateMuxData,
2442
+ // Live status methods
2443
+ getLiveStatus,
2444
+ seekToLiveEdge,
1085
2445
  // Access to underlying instances
1086
2446
  getPlayer: () => playerRef.current,
1087
2447
  getMuxMonitor: () => null
1088
- }), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData]);
2448
+ }), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData, getLiveStatus, seekToLiveEdge]);
1089
2449
  const isResponsive = !width && !height;
1090
- const containerClasses = twMerge2(containerClassName, "motto-video-container");
2450
+ const containerClasses = twMerge2(containerClassName, "motto-video-container relative bg-[#111111] ");
1091
2451
  const containerStyle = isResponsive ? {
1092
2452
  aspectRatio: aspectRatio.toString()
1093
2453
  } : { width, height };
1094
- const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
2454
+ const videoClasses = isResponsive ? "motto-video-responsive w-full" : "w-full h-full ";
1095
2455
  const videoStyle = isResponsive ? {} : { width, height };
2456
+ const filteredVideoProps = { ...videoProps };
2457
+ delete filteredVideoProps.controls;
1096
2458
  return /* @__PURE__ */ jsxs4(
1097
2459
  "div",
1098
2460
  {
1099
2461
  ref: containerRef,
1100
2462
  className: containerClasses,
1101
2463
  style: containerStyle,
1102
- "data-shaka-player-container": true,
1103
- "data-shaka-player-cast-receiver-id": chromecastConfig?.receiverApplicationId,
1104
2464
  children: [
1105
- /* @__PURE__ */ jsx5(
2465
+ /* @__PURE__ */ jsx7(
1106
2466
  "video",
1107
2467
  {
1108
2468
  ref: videoRef,
@@ -1111,17 +2471,11 @@ var Player = forwardRef(
1111
2471
  height: isResponsive ? void 0 : height,
1112
2472
  style: videoStyle,
1113
2473
  controls: false,
1114
- ...props
2474
+ playsInline: true,
2475
+ ...filteredVideoProps
1115
2476
  }
1116
2477
  ),
1117
- /* @__PURE__ */ jsx5(LiveBadge, { isVisible: isLiveBadgeVisible }),
1118
- imaConfig && /* @__PURE__ */ jsx5(
1119
- "div",
1120
- {
1121
- ref: adContainerRef,
1122
- className: "absolute top-0 left-0 w-full h-full pointer-events-auto"
1123
- }
1124
- )
2478
+ isInitialLoading && /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 flex items-center justify-center z-20 pointer-events-none", children: /* @__PURE__ */ jsx7(Loading, { className: "bg-transparent" }) })
1125
2479
  ]
1126
2480
  }
1127
2481
  );
@@ -1135,11 +2489,11 @@ import { twMerge as twMerge3 } from "tailwind-merge";
1135
2489
  import { useQuery } from "@tanstack/react-query";
1136
2490
 
1137
2491
  // src/api/video.ts
1138
- var fetchVideoData = async (videoId, publicKey, mottoToken) => {
2492
+ var fetchVideoData = async (videoId, publicKey, mottoToken, adsEnabled = false, locale = "en") => {
1139
2493
  const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/GetVideo";
1140
2494
  const url = new URL(endpoint);
1141
2495
  url.searchParams.set("encoding", "json");
1142
- url.searchParams.set("message", JSON.stringify({ videoId }));
2496
+ url.searchParams.set("message", JSON.stringify({ videoId, enable_ads: adsEnabled, locale }));
1143
2497
  const response = await fetch(url, {
1144
2498
  method: "GET",
1145
2499
  headers: {
@@ -1153,14 +2507,14 @@ var fetchVideoData = async (videoId, publicKey, mottoToken) => {
1153
2507
  const data = await response.json();
1154
2508
  return data.video;
1155
2509
  };
1156
- async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0) {
2510
+ async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0, adsEnabled = true, locale = "en") {
1157
2511
  if (!videoIds || videoIds.length === 0) {
1158
2512
  return [];
1159
2513
  }
1160
2514
  const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/BatchGetVideos";
1161
2515
  const url = new URL(endpoint);
1162
2516
  url.searchParams.set("encoding", "json");
1163
- url.searchParams.set("message", JSON.stringify({ videoIds }));
2517
+ url.searchParams.set("message", JSON.stringify({ videoIds, enable_ads: adsEnabled, locale }));
1164
2518
  const response = await fetch(url.toString(), {
1165
2519
  method: "GET",
1166
2520
  headers: {
@@ -1271,7 +2625,7 @@ var getErrorType = (error, video) => {
1271
2625
  };
1272
2626
 
1273
2627
  // src/messages/useMessages.tsx
1274
- import { useState as useState3, useEffect as useEffect5 } from "react";
2628
+ import { useState as useState4, useEffect as useEffect5 } from "react";
1275
2629
 
1276
2630
  // src/messages/en.json
1277
2631
  var en_default = {
@@ -1573,8 +2927,8 @@ var getBrowserLanguage = () => {
1573
2927
  return availableLanguages[language] ? language : "en";
1574
2928
  };
1575
2929
  var useMessages = (locale) => {
1576
- const [language, setLanguage] = useState3("en");
1577
- const [translations, setTranslations] = useState3(availableLanguages.en);
2930
+ const [language, setLanguage] = useState4("en");
2931
+ const [translations, setTranslations] = useState4(availableLanguages.en);
1578
2932
  useEffect5(() => {
1579
2933
  const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
1580
2934
  ;
@@ -1601,11 +2955,10 @@ var useMessages = (locale) => {
1601
2955
  var useMessages_default = useMessages;
1602
2956
 
1603
2957
  // src/Video.tsx
1604
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2958
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1605
2959
  var Video = ({
1606
2960
  videoId,
1607
2961
  publicKey,
1608
- mottoToken,
1609
2962
  videoData: providedVideoData,
1610
2963
  refetchInterval = 0,
1611
2964
  playerName,
@@ -1613,7 +2966,10 @@ var Video = ({
1613
2966
  events,
1614
2967
  children,
1615
2968
  className,
2969
+ auth,
2970
+ settings,
1616
2971
  queryOptions = {},
2972
+ adsEnabled = false,
1617
2973
  ...props
1618
2974
  }) => {
1619
2975
  const {
@@ -1622,8 +2978,8 @@ var Video = ({
1622
2978
  error,
1623
2979
  refetch
1624
2980
  } = useQuery({
1625
- queryKey: ["video", videoId, publicKey, mottoToken],
1626
- queryFn: () => fetchVideoData(videoId, publicKey, mottoToken),
2981
+ queryKey: ["video", videoId, publicKey, auth?.mottoToken, adsEnabled, locale],
2982
+ queryFn: () => fetchVideoData(videoId, publicKey, auth?.mottoToken, adsEnabled, locale),
1627
2983
  enabled: !!videoId && !!publicKey && !providedVideoData,
1628
2984
  refetchInterval: refetchInterval > 0 ? refetchInterval : false,
1629
2985
  staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
@@ -1636,16 +2992,17 @@ var Video = ({
1636
2992
  const video = providedVideoData || data;
1637
2993
  const { t } = useMessages_default(locale);
1638
2994
  const activePlaylist = findHLSPlaylist(video);
1639
- const hlsUrl = activePlaylist?.url;
2995
+ const activePlaylistUrl = activePlaylist?.url ?? activePlaylist?.drm?.widevine?.playlistUrl ?? activePlaylist?.drm?.playready?.playlistUrl ?? activePlaylist?.drm?.fairplay?.playlistUrl;
2996
+ const activePlaylistHasUrl = !!activePlaylistUrl;
1640
2997
  useEffect6(() => {
1641
2998
  if (events?.onVideoData && video) {
1642
2999
  events.onVideoData(video);
1643
3000
  }
1644
3001
  }, [video, events]);
1645
3002
  if (isLoading || !providedVideoData && !video) {
1646
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx6("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ jsx6(Loading, {}) }) });
3003
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ jsx8(Loading, {}) }) });
1647
3004
  }
1648
- if (!isLoading && video && !hlsUrl && events?.onEmptyPlaylists) {
3005
+ if (!isLoading && video && !activePlaylistHasUrl && events?.onEmptyPlaylists) {
1649
3006
  events.onEmptyPlaylists();
1650
3007
  }
1651
3008
  if (error || video?.error) {
@@ -1656,8 +3013,8 @@ var Video = ({
1656
3013
  }
1657
3014
  const title = t(errorKey) || t("DEFAULT_ERROR");
1658
3015
  const description = t(`${errorKey}_DESCRIPTION`) || t("DEFAULT_ERROR_DESCRIPTION");
1659
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full", children: [
1660
- /* @__PURE__ */ jsx6(
3016
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full", children: [
3017
+ /* @__PURE__ */ jsx8(
1661
3018
  ErrorScreen,
1662
3019
  {
1663
3020
  title,
@@ -1667,31 +3024,35 @@ var Video = ({
1667
3024
  children
1668
3025
  ] }) });
1669
3026
  }
1670
- if (!hlsUrl) {
1671
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full bg-[#151515]", children: [
1672
- /* @__PURE__ */ jsx6(Title, { title: video?.name || "" }),
3027
+ if (!activePlaylist || !activePlaylistHasUrl) {
3028
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full bg-[#151515]", children: [
3029
+ /* @__PURE__ */ jsx8(Title, { title: video?.name || "" }),
1673
3030
  children
1674
3031
  ] }) });
1675
3032
  }
1676
- console.log("hlsUrl", hlsUrl);
1677
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx6("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx6(
3033
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx8(
1678
3034
  Player,
1679
3035
  {
1680
3036
  ...props,
1681
- src: hlsUrl,
3037
+ src: activePlaylist,
3038
+ managedMode: true,
1682
3039
  className: twMerge3("video-player-container", className),
1683
3040
  events,
3041
+ locale,
1684
3042
  containerClassName: "w-full h-full",
3043
+ publicKey,
3044
+ auth,
3045
+ ...adsEnabled && video?.ad?.adTagUrl ? { imaConfig: { adTagUrl: video?.ad?.adTagUrl } } : {},
1685
3046
  children
1686
3047
  }
1687
3048
  ) }) });
1688
3049
  };
1689
3050
 
1690
3051
  // src/Event.tsx
1691
- import { useCallback as useCallback7, useEffect as useEffect7, useState as useState4 } from "react";
3052
+ import { useCallback as useCallback10, useEffect as useEffect7, useState as useState5 } from "react";
1692
3053
  import { twMerge as twMerge4 } from "tailwind-merge";
1693
3054
  import { useQuery as useQuery2 } from "@tanstack/react-query";
1694
- import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3055
+ import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1695
3056
  var Event = ({
1696
3057
  publicKey,
1697
3058
  eventId,
@@ -1704,6 +3065,7 @@ var Event = ({
1704
3065
  settings,
1705
3066
  auth,
1706
3067
  queryOptions = {},
3068
+ adsEnabled = false,
1707
3069
  ...props
1708
3070
  }) => {
1709
3071
  const {
@@ -1721,16 +3083,16 @@ var Event = ({
1721
3083
  retry: queryOptions.retry ?? 3,
1722
3084
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1723
3085
  });
1724
- const [activePlaylist, setActivePlaylist] = useState4();
1725
- const [activeVideoId, setActiveVideoId] = useState4();
3086
+ const [activePlaylist, setActivePlaylist] = useState5();
3087
+ const [activeVideoId, setActiveVideoId] = useState5();
1726
3088
  const videoIds = eventData?.videoIds ?? [];
1727
3089
  const {
1728
3090
  data: videosData,
1729
3091
  isLoading: videosIsLoading,
1730
3092
  error: videosError
1731
3093
  } = useQuery2({
1732
- queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
1733
- queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
3094
+ queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
3095
+ queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
1734
3096
  enabled: !!publicKey && videoIds.length > 0,
1735
3097
  refetchInterval: activePlaylist === null ? 3e4 : false,
1736
3098
  staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
@@ -1738,7 +3100,7 @@ var Event = ({
1738
3100
  retry: queryOptions.retry ?? 3,
1739
3101
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1740
3102
  });
1741
- const [loadingApisState, setLoadingApisState] = useState4(true);
3103
+ const [loadingApisState, setLoadingApisState] = useState5(true);
1742
3104
  useEffect7(() => {
1743
3105
  if (videosData !== void 0) {
1744
3106
  setLoadingApisState(false);
@@ -1748,9 +3110,11 @@ var Event = ({
1748
3110
  if (videosWithPlaylists.length > 0) {
1749
3111
  let hlsPlaylistFound = false;
1750
3112
  for (const video of videosWithPlaylists) {
1751
- const hlsPlaylist = findHLSPlaylist(video);
1752
- if (hlsPlaylist?.url) {
1753
- setActivePlaylist(hlsPlaylist.url);
3113
+ const activePlaylist2 = findHLSPlaylist(video);
3114
+ const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
3115
+ const activePlaylistHasUrl = !!activePlaylistUrl;
3116
+ if (activePlaylist2 && activePlaylistHasUrl) {
3117
+ setActivePlaylist(activePlaylist2);
1754
3118
  setActiveVideoId(video.id);
1755
3119
  hlsPlaylistFound = true;
1756
3120
  break;
@@ -1784,12 +3148,17 @@ var Event = ({
1784
3148
  }
1785
3149
  }
1786
3150
  }, [activeVideoId, videosData, events]);
1787
- const [error, setError] = useState4(null);
1788
- const [loadingPlaylist, setLoadingPlaylist] = useState4(true);
3151
+ const [error, setError] = useState5(null);
3152
+ const [loadingPlaylist, setLoadingPlaylist] = useState5(true);
1789
3153
  const videosDataError = videosData?.some((video) => !!video.error);
1790
3154
  useEffect7(() => {
1791
- if (eventError || videosError || videosDataError) {
1792
- const errorObj = eventError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
3155
+ if (isEventLoading || videosIsLoading || loadingApisState) {
3156
+ return;
3157
+ }
3158
+ const hasPlayablePlaylist = Boolean(activePlaylist);
3159
+ if (eventError || videosError || videosDataError && !hasPlayablePlaylist) {
3160
+ const firstVideoError = videosData?.find((video) => !!video.error)?.error;
3161
+ const errorObj = eventError || videosError || firstVideoError && new Error(firstVideoError) || new Error("default");
1793
3162
  setError(errorObj);
1794
3163
  if (events?.onError) {
1795
3164
  events.onError(errorObj);
@@ -1797,7 +3166,17 @@ var Event = ({
1797
3166
  } else {
1798
3167
  setError(null);
1799
3168
  }
1800
- }, [eventError, videosError, videosDataError, videosData, events]);
3169
+ }, [
3170
+ eventError,
3171
+ videosError,
3172
+ videosDataError,
3173
+ videosData,
3174
+ events,
3175
+ activePlaylist,
3176
+ isEventLoading,
3177
+ videosIsLoading,
3178
+ loadingApisState
3179
+ ]);
1801
3180
  useEffect7(() => {
1802
3181
  const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
1803
3182
  const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
@@ -1808,7 +3187,7 @@ var Event = ({
1808
3187
  if (error) {
1809
3188
  const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
1810
3189
  const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
1811
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx7(
3190
+ return /* @__PURE__ */ jsx9("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx9("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx9(
1812
3191
  ErrorScreen,
1813
3192
  {
1814
3193
  title,
@@ -1820,22 +3199,28 @@ var Event = ({
1820
3199
  events.onEmptyPlaylists();
1821
3200
  }
1822
3201
  if (loadingPlaylist) {
1823
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ jsx7(Loading, {}) }) });
3202
+ return /* @__PURE__ */ jsx9("div", { className: twMerge4("", className), children: /* @__PURE__ */ jsx9("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ jsx9(Loading, {}) }) });
1824
3203
  }
1825
3204
  if (activePlaylist && activeVideoId && videosData) {
1826
3205
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
1827
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs6("div", { className: "relative w-full h-full", children: [
1828
- /* @__PURE__ */ jsx7(
3206
+ console.log("activeVideo?.ad?.adTagUrl", activeVideo?.ad?.adTagUrl);
3207
+ return /* @__PURE__ */ jsxs6("div", { className: twMerge4("", className), children: [
3208
+ /* @__PURE__ */ jsx9("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx9(
1829
3209
  Player,
1830
3210
  {
1831
3211
  ...props,
1832
3212
  src: activePlaylist,
1833
- className: twMerge4(className, "peer"),
3213
+ managedMode: true,
3214
+ className: twMerge4(className, "peer aspect-video"),
1834
3215
  events,
1835
- containerClassName: "w-full h-full"
3216
+ locale,
3217
+ containerClassName: "w-full h-full",
3218
+ publicKey,
3219
+ auth,
3220
+ ...adsEnabled && activeVideo ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
1836
3221
  }
1837
- ),
1838
- !hideTitle && eventData && /* @__PURE__ */ jsx7(
3222
+ ) }),
3223
+ !hideTitle && eventData && /* @__PURE__ */ jsx9(
1839
3224
  TitleAndDescription,
1840
3225
  {
1841
3226
  title: eventData.title,
@@ -1844,10 +3229,10 @@ var Event = ({
1844
3229
  locale
1845
3230
  }
1846
3231
  )
1847
- ] }) });
3232
+ ] });
1848
3233
  }
1849
3234
  if (eventData) {
1850
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx7(
3235
+ return /* @__PURE__ */ jsx9("div", { className: twMerge4("", className), children: /* @__PURE__ */ jsx9("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx9(
1851
3236
  PreEvent,
1852
3237
  {
1853
3238
  event: eventData,
@@ -1869,7 +3254,7 @@ function PreEvent({
1869
3254
  }) {
1870
3255
  const date = new Date(event.startTime);
1871
3256
  const now = /* @__PURE__ */ new Date();
1872
- const [remainingTime, setRemainingTime] = useState4(
3257
+ const [remainingTime, setRemainingTime] = useState5(
1873
3258
  date.getTime() - now.getTime()
1874
3259
  );
1875
3260
  const shouldBeStarted = remainingTime < 0;
@@ -1884,29 +3269,28 @@ function PreEvent({
1884
3269
  }, 1e3);
1885
3270
  return () => clearInterval(interval);
1886
3271
  }, [date, remainingTime]);
1887
- const renderCountdown = useCallback7(() => {
3272
+ const renderCountdown = useCallback10(() => {
1888
3273
  if (shouldBeStarted) {
1889
- return /* @__PURE__ */ jsx7("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
3274
+ return /* @__PURE__ */ jsx9("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
1890
3275
  }
1891
3276
  const seconds = Math.floor(remainingTime / 1e3) % 60;
1892
3277
  const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
1893
3278
  const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
1894
3279
  const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
1895
- return /* @__PURE__ */ jsxs6("div", { className: "grid grid-flow-col gap-5 text-center auto-cols-max", children: [
3280
+ return /* @__PURE__ */ jsxs6("div", { className: "grid grid-flow-col gap-1 md:gap-5 text-center auto-cols-max", children: [
1896
3281
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1897
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3282
+ /* @__PURE__ */ jsx9("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1898
3283
  "span",
1899
3284
  {
1900
- style: { "--value": days },
1901
3285
  "aria-live": "polite",
1902
3286
  "aria-label": days.toString(),
1903
- children: days?.toString()?.padStart(2, "0")
3287
+ children: days.toString()
1904
3288
  }
1905
3289
  ) }),
1906
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("DAYS") })
3290
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
1907
3291
  ] }),
1908
3292
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1909
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3293
+ /* @__PURE__ */ jsx9("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1910
3294
  "span",
1911
3295
  {
1912
3296
  style: { "--value": hours },
@@ -1915,10 +3299,10 @@ function PreEvent({
1915
3299
  children: hours?.toString()?.padStart(2, "0")
1916
3300
  }
1917
3301
  ) }),
1918
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("HOURS") })
3302
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
1919
3303
  ] }),
1920
3304
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1921
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3305
+ /* @__PURE__ */ jsx9("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1922
3306
  "span",
1923
3307
  {
1924
3308
  style: { "--value": minutes },
@@ -1927,10 +3311,10 @@ function PreEvent({
1927
3311
  children: minutes?.toString()?.padStart(2, "0")
1928
3312
  }
1929
3313
  ) }),
1930
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("MINUTES") })
3314
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
1931
3315
  ] }),
1932
3316
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1933
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3317
+ /* @__PURE__ */ jsx9("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1934
3318
  "span",
1935
3319
  {
1936
3320
  style: { "--value": seconds },
@@ -1939,12 +3323,12 @@ function PreEvent({
1939
3323
  children: seconds?.toString()?.padStart(2, "0")
1940
3324
  }
1941
3325
  ) }),
1942
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("SECONDS") })
3326
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
1943
3327
  ] })
1944
3328
  ] });
1945
3329
  }, [remainingTime, shouldBeStarted, t]);
1946
- return /* @__PURE__ */ jsx7(Fragment, { children: event?.posterUrl ? /* @__PURE__ */ jsxs6(Fragment, { children: [
1947
- /* @__PURE__ */ jsx7(
3330
+ return /* @__PURE__ */ jsx9(Fragment, { children: event?.posterUrl ? /* @__PURE__ */ jsxs6(Fragment, { children: [
3331
+ /* @__PURE__ */ jsx9(
1948
3332
  "div",
1949
3333
  {
1950
3334
  className: "relative overflow-hidden bg-base-200 aspect-video text-base-content w-full h-full flex justify-center items-center flex-col bg-no-repeat bg-cover md:rounded-2xl",
@@ -1953,10 +3337,10 @@ function PreEvent({
1953
3337
  backgroundRepeat: "no-repeat",
1954
3338
  backgroundSize: "cover"
1955
3339
  },
1956
- children: /* @__PURE__ */ jsx7("div", { className: "relative z-10", children: renderCountdown() })
3340
+ children: /* @__PURE__ */ jsx9("div", { className: "relative z-10", children: renderCountdown() })
1957
3341
  }
1958
3342
  ),
1959
- !hideTitle && /* @__PURE__ */ jsx7(
3343
+ !hideTitle && /* @__PURE__ */ jsx9(
1960
3344
  TitleAndDescription,
1961
3345
  {
1962
3346
  title: event.title,
@@ -1966,17 +3350,17 @@ function PreEvent({
1966
3350
  }
1967
3351
  )
1968
3352
  ] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
1969
- /* @__PURE__ */ jsx7(
3353
+ /* @__PURE__ */ jsx9(
1970
3354
  "div",
1971
3355
  {
1972
3356
  className: "relative overflow-hidden md:rounded-2xl bg-base-200 aspect-video text-base-content flex flex-col justify-center items-center w-full h-full bg-cover bg-center bg-no-repeat",
1973
3357
  style: {
1974
3358
  backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
1975
3359
  },
1976
- children: /* @__PURE__ */ jsx7("div", { className: "relative z-10", children: renderCountdown() })
3360
+ children: /* @__PURE__ */ jsx9("div", { className: "relative z-10", children: renderCountdown() })
1977
3361
  }
1978
3362
  ),
1979
- !hideTitle && /* @__PURE__ */ jsx7(
3363
+ !hideTitle && /* @__PURE__ */ jsx9(
1980
3364
  TitleAndDescription,
1981
3365
  {
1982
3366
  title: event.title,
@@ -1995,8 +3379,8 @@ var TitleAndDescription = ({
1995
3379
  className
1996
3380
  }) => {
1997
3381
  return /* @__PURE__ */ jsxs6("div", { className: twMerge4("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
1998
- /* @__PURE__ */ jsx7("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
1999
- startTime ? /* @__PURE__ */ jsxs6("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
3382
+ /* @__PURE__ */ jsx9("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
3383
+ startTime ? /* @__PURE__ */ jsxs6("div", { className: "text-xs md:text-base text-base-content/70 m-event-start-time", children: [
2000
3384
  new Date(startTime || "").toLocaleDateString(locale || "default", {
2001
3385
  month: "long",
2002
3386
  year: "numeric",
@@ -2009,15 +3393,15 @@ var TitleAndDescription = ({
2009
3393
  minute: "2-digit"
2010
3394
  })
2011
3395
  ] }) : null,
2012
- description && /* @__PURE__ */ jsx7("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
3396
+ description && /* @__PURE__ */ jsx9("div", { className: "text-xs md:text-xs text-base-content/60 uppercase", children: description })
2013
3397
  ] });
2014
3398
  };
2015
3399
 
2016
3400
  // src/CreativeWork.tsx
2017
- import { useEffect as useEffect8, useState as useState5 } from "react";
3401
+ import { useEffect as useEffect8, useState as useState6 } from "react";
2018
3402
  import { twMerge as twMerge5 } from "tailwind-merge";
2019
3403
  import { useQuery as useQuery3 } from "@tanstack/react-query";
2020
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3404
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2021
3405
  var CreativeWork = ({
2022
3406
  publicKey,
2023
3407
  creativeWorkId,
@@ -2030,6 +3414,7 @@ var CreativeWork = ({
2030
3414
  settings,
2031
3415
  auth,
2032
3416
  queryOptions = {},
3417
+ adsEnabled = false,
2033
3418
  ...props
2034
3419
  }) => {
2035
3420
  const {
@@ -2047,17 +3432,17 @@ var CreativeWork = ({
2047
3432
  retry: queryOptions.retry ?? 3,
2048
3433
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2049
3434
  });
2050
- const [activePlaylist, setActivePlaylist] = useState5();
2051
- const [activeVideoId, setActiveVideoId] = useState5();
2052
- const [showCountDown, setShowCountDown] = useState5(false);
3435
+ const [activePlaylist, setActivePlaylist] = useState6();
3436
+ const [activeVideoId, setActiveVideoId] = useState6();
3437
+ const [showCountDown, setShowCountDown] = useState6(false);
2053
3438
  const videoIds = creativeWorkData?.videoIds ?? [];
2054
3439
  const {
2055
3440
  data: videosData,
2056
3441
  isLoading: videosIsLoading,
2057
3442
  error: videosError
2058
3443
  } = useQuery3({
2059
- queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
2060
- queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
3444
+ queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
3445
+ queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
2061
3446
  enabled: !!publicKey && videoIds.length > 0,
2062
3447
  refetchInterval: activePlaylist === null ? 3e4 : false,
2063
3448
  staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
@@ -2065,7 +3450,7 @@ var CreativeWork = ({
2065
3450
  retry: queryOptions.retry ?? 3,
2066
3451
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2067
3452
  });
2068
- const [loadingApisState, setLoadingApisState] = useState5(true);
3453
+ const [loadingApisState, setLoadingApisState] = useState6(true);
2069
3454
  useEffect8(() => {
2070
3455
  if (videosData !== void 0) {
2071
3456
  setLoadingApisState(false);
@@ -2075,9 +3460,11 @@ var CreativeWork = ({
2075
3460
  if (videosWithPlaylists.length > 0) {
2076
3461
  let hlsPlaylistFound = false;
2077
3462
  for (const video of videosWithPlaylists) {
2078
- const hlsPlaylist = findHLSPlaylist(video);
2079
- if (hlsPlaylist?.url) {
2080
- setActivePlaylist(hlsPlaylist.url);
3463
+ const activePlaylist2 = findHLSPlaylist(video);
3464
+ const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
3465
+ const activePlaylistHasUrl = !!activePlaylistUrl;
3466
+ if (activePlaylist2 && activePlaylistHasUrl) {
3467
+ setActivePlaylist(activePlaylist2);
2081
3468
  setActiveVideoId(video.id);
2082
3469
  hlsPlaylistFound = true;
2083
3470
  break;
@@ -2114,7 +3501,7 @@ var CreativeWork = ({
2114
3501
  }
2115
3502
  }
2116
3503
  }, [activeVideoId, videosData, events]);
2117
- const [error, setError] = useState5(null);
3504
+ const [error, setError] = useState6(null);
2118
3505
  const videosDataError = videosData?.some((video) => !!video.error);
2119
3506
  useEffect8(() => {
2120
3507
  if (creativeWorkError || videosError || videosDataError) {
@@ -2130,7 +3517,7 @@ var CreativeWork = ({
2130
3517
  if (error) {
2131
3518
  const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
2132
3519
  const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
2133
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx8(
3520
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx10(
2134
3521
  ErrorScreen,
2135
3522
  {
2136
3523
  title,
@@ -2138,7 +3525,7 @@ var CreativeWork = ({
2138
3525
  }
2139
3526
  ) }) });
2140
3527
  }
2141
- const [loadingPlaylist, setLoadingPlaylist] = useState5(true);
3528
+ const [loadingPlaylist, setLoadingPlaylist] = useState6(true);
2142
3529
  useEffect8(() => {
2143
3530
  const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
2144
3531
  const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
@@ -2160,10 +3547,10 @@ var CreativeWork = ({
2160
3547
  events
2161
3548
  ]);
2162
3549
  if (isCreativeWorkLoading || videosIsLoading || loadingApisState) {
2163
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx8(Loading, {}) }) });
3550
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ jsx10(Loading, {}) }) });
2164
3551
  }
2165
3552
  if (showCountDown && creativeWorkData) {
2166
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full bg-base-200 text-base-content flex justify-center items-center flex-col", children: /* @__PURE__ */ jsx8(
3553
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full h-full bg-base-200 text-base-content flex justify-center items-center flex-col", children: /* @__PURE__ */ jsx10(
2167
3554
  PreCreativeWork,
2168
3555
  {
2169
3556
  creativeWork: creativeWorkData,
@@ -2176,20 +3563,25 @@ var CreativeWork = ({
2176
3563
  }
2177
3564
  if (activeVideoId && activePlaylist && !loadingPlaylist) {
2178
3565
  const activeVideo = videosData?.find((video) => video.id === activeVideoId);
2179
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs7("div", { className: "relative w-full h-full", children: [
2180
- /* @__PURE__ */ jsx8(
3566
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsxs7("div", { className: "relative w-full h-full", children: [
3567
+ /* @__PURE__ */ jsx10(
2181
3568
  Player,
2182
3569
  {
2183
3570
  ...props,
2184
- className: twMerge5(className, "peer"),
3571
+ className: twMerge5(className, "peer aspect-video"),
3572
+ managedMode: true,
2185
3573
  events: {
2186
3574
  ...events
2187
3575
  },
2188
3576
  src: activePlaylist,
2189
- containerClassName: "w-full h-full"
3577
+ locale,
3578
+ containerClassName: "w-full h-full",
3579
+ publicKey,
3580
+ auth,
3581
+ ...adsEnabled && activeVideo?.ad?.adTagUrl ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
2190
3582
  }
2191
3583
  ),
2192
- !hideTitle && /* @__PURE__ */ jsx8(
3584
+ !hideTitle && /* @__PURE__ */ jsx10(
2193
3585
  TitleAndDescription2,
2194
3586
  {
2195
3587
  title: creativeWorkData?.title || "",
@@ -2202,7 +3594,7 @@ var CreativeWork = ({
2202
3594
  ] }) });
2203
3595
  }
2204
3596
  if (loadingPlaylist) {
2205
- return /* @__PURE__ */ jsx8(Loading, {});
3597
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ jsx10(Loading, {}) }) });
2206
3598
  }
2207
3599
  return null;
2208
3600
  };
@@ -2215,7 +3607,7 @@ function PreCreativeWork({
2215
3607
  }) {
2216
3608
  const date = new Date(creativeWork.releaseTime);
2217
3609
  const now = /* @__PURE__ */ new Date();
2218
- const [remainingTime, setRemainingTime] = useState5(
3610
+ const [remainingTime, setRemainingTime] = useState6(
2219
3611
  date.getTime() - now.getTime()
2220
3612
  );
2221
3613
  const shouldBeStarted = remainingTime < 0;
@@ -2234,27 +3626,26 @@ function PreCreativeWork({
2234
3626
  }, [date, remainingTime]);
2235
3627
  const renderCountdown = () => {
2236
3628
  if (shouldBeStarted) {
2237
- return /* @__PURE__ */ jsx8("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
3629
+ return /* @__PURE__ */ jsx10("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
2238
3630
  }
2239
3631
  const seconds = Math.floor(remainingTime / 1e3) % 60;
2240
3632
  const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
2241
3633
  const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
2242
3634
  const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
2243
- return /* @__PURE__ */ jsxs7("div", { className: "grid grid-flow-col gap-5 text-center auto-cols-max", children: [
3635
+ return /* @__PURE__ */ jsxs7("div", { className: "grid grid-flow-col md:gap-5 gap-1 text-center auto-cols-max", children: [
2244
3636
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2245
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3637
+ /* @__PURE__ */ jsx10("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2246
3638
  "span",
2247
3639
  {
2248
- style: { "--value": days },
2249
3640
  "aria-live": "polite",
2250
3641
  "aria-label": days.toString(),
2251
- children: days?.toString()?.padStart(2, "0")
3642
+ children: days.toString()
2252
3643
  }
2253
3644
  ) }),
2254
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("DAYS") })
3645
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
2255
3646
  ] }),
2256
3647
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2257
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3648
+ /* @__PURE__ */ jsx10("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2258
3649
  "span",
2259
3650
  {
2260
3651
  style: { "--value": hours },
@@ -2263,10 +3654,10 @@ function PreCreativeWork({
2263
3654
  children: hours?.toString()?.padStart(2, "0")
2264
3655
  }
2265
3656
  ) }),
2266
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("HOURS") })
3657
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
2267
3658
  ] }),
2268
3659
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2269
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3660
+ /* @__PURE__ */ jsx10("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2270
3661
  "span",
2271
3662
  {
2272
3663
  style: { "--value": minutes },
@@ -2275,10 +3666,10 @@ function PreCreativeWork({
2275
3666
  children: minutes?.toString()?.padStart(2, "0")
2276
3667
  }
2277
3668
  ) }),
2278
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("MINUTES") })
3669
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
2279
3670
  ] }),
2280
3671
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2281
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3672
+ /* @__PURE__ */ jsx10("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2282
3673
  "span",
2283
3674
  {
2284
3675
  style: { "--value": seconds },
@@ -2287,7 +3678,7 @@ function PreCreativeWork({
2287
3678
  children: seconds?.toString()?.padStart(2, "0")
2288
3679
  }
2289
3680
  ) }),
2290
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("SECONDS") })
3681
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
2291
3682
  ] })
2292
3683
  ] });
2293
3684
  };
@@ -2300,12 +3691,12 @@ function PreCreativeWork({
2300
3691
  backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
2301
3692
  },
2302
3693
  children: [
2303
- backgroundImageUrl && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
2304
- /* @__PURE__ */ jsx8("div", { className: "relative z-10", children: renderCountdown() })
3694
+ backgroundImageUrl && /* @__PURE__ */ jsx10("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
3695
+ /* @__PURE__ */ jsx10("div", { className: "relative z-10", children: renderCountdown() })
2305
3696
  ]
2306
3697
  }
2307
3698
  ),
2308
- !hideTitle && /* @__PURE__ */ jsx8(
3699
+ !hideTitle && /* @__PURE__ */ jsx10(
2309
3700
  TitleAndDescription2,
2310
3701
  {
2311
3702
  title: creativeWork.title,
@@ -2324,7 +3715,7 @@ var TitleAndDescription2 = ({
2324
3715
  className
2325
3716
  }) => {
2326
3717
  return /* @__PURE__ */ jsxs7("div", { className: twMerge5("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
2327
- /* @__PURE__ */ jsx8("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
3718
+ /* @__PURE__ */ jsx10("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
2328
3719
  releaseTime ? /* @__PURE__ */ jsxs7("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
2329
3720
  new Date(releaseTime || "").toLocaleDateString(locale || "default", {
2330
3721
  month: "long",
@@ -2338,13 +3729,13 @@ var TitleAndDescription2 = ({
2338
3729
  minute: "2-digit"
2339
3730
  })
2340
3731
  ] }) : null,
2341
- description && /* @__PURE__ */ jsx8("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
3732
+ description && /* @__PURE__ */ jsx10("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
2342
3733
  ] });
2343
3734
  };
2344
3735
 
2345
3736
  // src/QueryProvider.tsx
2346
3737
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2347
- import { jsx as jsx9 } from "react/jsx-runtime";
3738
+ import { jsx as jsx11 } from "react/jsx-runtime";
2348
3739
  var queryClient = new QueryClient({
2349
3740
  defaultOptions: {
2350
3741
  queries: {
@@ -2358,13 +3749,16 @@ var queryClient = new QueryClient({
2358
3749
  }
2359
3750
  });
2360
3751
  var QueryProvider = ({ children }) => {
2361
- return /* @__PURE__ */ jsx9(QueryClientProvider, { client: queryClient, children });
3752
+ return /* @__PURE__ */ jsx11(QueryClientProvider, { client: queryClient, children });
2362
3753
  };
2363
3754
  export {
3755
+ BigPlayIcon,
2364
3756
  CreativeWork,
2365
3757
  Event,
2366
3758
  Player,
2367
3759
  QueryProvider,
3760
+ SkipBackIcon,
3761
+ SkipForwardIcon,
2368
3762
  Video,
2369
3763
  queryClient
2370
3764
  };