eb-player 2.0.8 → 2.0.10
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/build/ebplayer.bundle.js +86 -24
- package/dist/build/ebplayer.bundle.js.map +1 -1
- package/dist/build/types/eb-player.d.ts.map +1 -1
- package/dist/build/types/engines/cdn-token-manager.d.ts +1 -0
- package/dist/build/types/engines/cdn-token-manager.d.ts.map +1 -1
- package/dist/build/types/engines/hls.d.ts.map +1 -1
- package/dist/build/types/engines/snapshot/hls.d.ts +10 -0
- package/dist/build/types/engines/snapshot/hls.d.ts.map +1 -1
- package/dist/dev/default.js +445 -98
- package/dist/dev/default.js.map +1 -1
- package/dist/dev/easybroadcast.js +125 -49
- package/dist/dev/easybroadcast.js.map +1 -1
- package/dist/dev/equipe.js +424 -83
- package/dist/dev/equipe.js.map +1 -1
- package/dist/players/equipe/EB_lequipe-preprod.js +6 -6
- package/package.json +1 -1
package/dist/dev/default.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
var EBPlayerBundle = (function (exports) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
var __EB_PLAYER_VERSION__ = "2.0.9";
|
|
5
|
+
|
|
4
6
|
function styleInject(css, ref) {
|
|
5
7
|
if ( ref === void 0 ) ref = {};
|
|
6
8
|
var insertAt = ref.insertAt;
|
|
@@ -28,13 +30,16 @@ var EBPlayerBundle = (function (exports) {
|
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
var css_248z$
|
|
33
|
+
var css_248z$7 = "/**\n * eb-player base CSS\n *\n * CSS custom property defaults are provided as fallbacks in var() calls\n * rather than declared on .eb-player. This allows lifecycle.ts to set\n * overrides on the parent container element and have them inherit into\n * .eb-player without being blocked by a competing declaration.\n *\n * Theme overrides use the .eb-player[data-theme=\"...\"] selector pattern (see theme-*.css).\n * Runtime overrides use style.setProperty() via PlayerController.mount() for backward\n * compatibility with the primaryColor / skinColors consumer API.\n *\n * CSS scoping: The .eb-player prefix ensures no style bleed between two co-hosted instances.\n */\n\n.eb-player {\n /* Base styles — all var() calls include hardcoded fallbacks */\n position: relative;\n overflow: hidden;\n font-family: var(--eb-font-family, Arial, sans-serif);\n font-size: var(--eb-font-size-base, 14px);\n color: var(--eb-color-text, #ffffff);\n box-sizing: border-box;\n}\n\n/* Ensure all descendants use border-box sizing */\n.eb-player *,\n.eb-player *::before,\n.eb-player *::after {\n box-sizing: inherit;\n}\n\n/* BEM block scaffold */\n.eb-player__container {\n position: relative;\n width: 100%;\n height: 100%;\n background-color: var(--eb-color-background, rgba(0, 0, 0, 0.8));\n}\n\n.eb-player__video {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n";
|
|
34
|
+
styleInject(css_248z$7);
|
|
35
|
+
|
|
36
|
+
var css_248z$6 = "/**\n * Forja theme overrides\n *\n * Applied when the container has [data-theme=\"forja\"].\n * Uses higher specificity than base.css .eb-player selector.\n */\n\n[data-theme=\"forja\"] .eb-player {\n --eb-color-primary: #FC013B;\n}\n";
|
|
32
37
|
styleInject(css_248z$6);
|
|
33
38
|
|
|
34
|
-
var css_248z$5 = "/**\n * Forja theme overrides\n *\n * Applied when the container has [data-theme=\"forja\"].\n * Uses higher specificity than base.css .eb-player selector.\n */\n\n[data-theme=\"forja\"] .eb-player {\n --eb-color-primary: #E63946;\n}\n";
|
|
39
|
+
var css_248z$5 = "/**\n * L'Equipe theme — v2 layout with L'Equipe red (#d61e00) accent\n *\n * Applied when the container has [data-theme=\"lequipe\"].\n * Dark UI with red accent, Inter font, rounded container,\n * backdrop-blur panels, expandable volume, single-row bottom bar,\n * gradient overlays, centered frosted-glass transport circles,\n * and refined slide/fade animations.\n */\n\n/* ============================================================\n Google Fonts (Inter 300-700)\n ============================================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');\n\n/* ============================================================\n Root vars & container\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player {\n --eb-color-primary: #d61e00;\n --eb-color-progress: #d61e00;\n --eb-color-background: rgba(10, 10, 20, 0.85);\n --eb-accent: #d61e00;\n --eb-color-text: #fff;\n --eb-font-family: 'Inter', -apple-system, sans-serif;\n --eb-font-size-base: 14px;\n --eb-radius-control: 8px;\n --eb-duration-transition: 200ms;\n font-family: 'Inter', -apple-system, sans-serif;\n border-radius: 0;\n box-shadow: none;\n color: #fff;\n}\n\n/* ============================================================\n Icons: bolder stroke weight to match filled-style target\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-icon {\n stroke-width: 2.5;\n}\n\n/* Fullscreen: fill viewport, drop card styling */\n[data-theme=\"lequipe\"] .eb-player:fullscreen,\n[data-theme=\"lequipe\"] .eb-player:-webkit-full-screen {\n border-radius: 0;\n box-shadow: none;\n}\n\n/* ============================================================\n Gradients (top & bottom)\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-top-bar {\n background: linear-gradient(to bottom, rgba(0,0,0,.72), transparent);\n height: 110px;\n padding: 14px 16px;\n gap: 6px;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-bottom-bar__gradient {\n height: 150px;\n background: linear-gradient(to top, rgba(0,0,0,.9), transparent);\n}\n\n/* ============================================================\n Top bar: slide-in from above\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player.eb-controls-visible .eb-top-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"lequipe\"] .eb-player.eb-controls-hidden .eb-top-bar {\n opacity: 0;\n transform: translateY(-6px);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-top-bar__actions {\n gap: 6px;\n}\n\n/* Logo */\n[data-theme=\"lequipe\"] .eb-player .eb-top-bar__logo {\n max-height: 32px;\n max-width: 120px;\n opacity: .85;\n}\n\n/* ============================================================\n Bottom bar: slide-up animation + spacing\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-bottom-bar__controls-row {\n padding: 0 14px 12px;\n gap: 8px;\n}\n\n[data-theme=\"lequipe\"] .eb-player.eb-controls-visible .eb-bottom-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"lequipe\"] .eb-player.eb-controls-hidden .eb-bottom-bar {\n opacity: 0;\n transform: translateY(8px);\n transition: opacity .3s, transform .3s;\n}\n\n/* ============================================================\n Middle bar: glassmorphism transport circles\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar {\n gap: 28px;\n}\n\n[data-theme=\"lequipe\"] .eb-player.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity .3s;\n}\n\n[data-theme=\"lequipe\"] .eb-player.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity .3s;\n}\n\n/* Central play/pause — large frosted circle */\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__play-btn {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255,255,255,.15);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 2px solid rgba(255,255,255,.25);\n color: #fff;\n padding: 0;\n transition: background .15s, transform .25s, opacity .25s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__play-btn:hover {\n background: rgba(255,255,255,.25);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__play-btn:active {\n transform: scale(.92);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n width: 32px;\n height: 32px;\n stroke-width: 2.5;\n}\n\n/* Seek buttons — smaller frosted circles */\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__seek-btn {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(255,255,255,.15);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 2px solid rgba(255,255,255,.25);\n color: #fff;\n gap: 1px;\n padding: 0;\n transition: background .15s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,.25);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-seek-circle {\n width: 24px;\n height: 24px;\n color: rgba(255,255,255,.85);\n fill: currentColor;\n stroke: none;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-seek-label {\n font-size: .75em;\n font-weight: 700;\n color: rgba(255,255,255,.9);\n line-height: 1;\n}\n\n/* ============================================================\n Buttons: rounded, soft color, scale on press\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn),\n[data-theme=\"lequipe\"] .eb-player .eb-play-pause,\n[data-theme=\"lequipe\"] .eb-player .eb-fullscreen,\n[data-theme=\"lequipe\"] .eb-player .eb-pip,\n[data-theme=\"lequipe\"] .eb-player .eb-cast,\n[data-theme=\"lequipe\"] .eb-player .eb-volume-mute,\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync {\n color: rgba(255,255,255,.82);\n border-radius: 8px;\n width: 38px;\n height: 38px;\n transition: background .15s, color .15s, transform .1s;\n flex-shrink: 0;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn):hover,\n[data-theme=\"lequipe\"] .eb-player .eb-play-pause:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-fullscreen:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-pip:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-cast:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-volume-mute:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync:hover {\n background: rgba(255,255,255,.12);\n color: #fff;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn):active,\n[data-theme=\"lequipe\"] .eb-player .eb-play-pause:active,\n[data-theme=\"lequipe\"] .eb-player .eb-fullscreen:active,\n[data-theme=\"lequipe\"] .eb-player .eb-pip:active,\n[data-theme=\"lequipe\"] .eb-player .eb-cast:active,\n[data-theme=\"lequipe\"] .eb-player .eb-volume-mute:active,\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync:active {\n transform: scale(.88);\n}\n\n/* Icon size inside buttons (not middle bar transport) */\n[data-theme=\"lequipe\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn) .eb-icon,\n[data-theme=\"lequipe\"] .eb-player .eb-play-pause .eb-icon,\n[data-theme=\"lequipe\"] .eb-player .eb-fullscreen .eb-icon,\n[data-theme=\"lequipe\"] .eb-player .eb-pip .eb-icon,\n[data-theme=\"lequipe\"] .eb-player .eb-cast .eb-icon,\n[data-theme=\"lequipe\"] .eb-player .eb-volume-mute .eb-icon {\n width: 22px;\n height: 22px;\n}\n\n/* Top bar icons slightly larger */\n[data-theme=\"lequipe\"] .eb-player .eb-top-bar .eb-icon {\n width: 24px;\n height: 24px;\n}\n\n/* Play/pause icons should be filled (solid), not stroke outlines */\n[data-theme=\"lequipe\"] .eb-player .eb-play-pause .eb-icon,\n[data-theme=\"lequipe\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n fill: currentColor;\n stroke: none;\n}\n\n/* Volume icon: fill the speaker body, keep stroke for sound waves */\n[data-theme=\"lequipe\"] .eb-player .eb-volume-mute .eb-icon path:first-child {\n fill: currentColor;\n}\n\n/* Cast button active state */\n[data-theme=\"lequipe\"] .eb-player .eb-cast-active {\n color: #1eb6d4 !important;\n background: rgba(30, 182, 212, .15) !important;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-cast-active .eb-icon {\n filter: drop-shadow(0 0 4px rgba(30, 182, 212, .6));\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-track {\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar:hover .eb-seekbar-track {\n height: 5px;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-buffered {\n background: rgba(255,255,255,.28);\n border-radius: 3px;\n transition: height .15s;\n}\n\n/* Solid red fill */\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-progress {\n background: #d61e00;\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-thumb {\n width: 14px;\n height: 14px;\n right: -7px;\n background: #fff;\n box-shadow: 0 0 0 3px rgba(214,30,0,.45);\n}\n\n/* ============================================================\n Seekbar tooltip & preview\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-tooltip {\n bottom: 28px;\n background: rgba(0,0,0,.88);\n border: 1px solid rgba(255,255,255,.12);\n border-radius: 7px;\n font-size: 11px;\n font-weight: 500;\n padding: 0;\n overflow: hidden;\n box-shadow: 0 4px 16px rgba(0,0,0,.5);\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-preview {\n width: 160px;\n height: 90px;\n background: #111;\n border: none;\n border-radius: 0;\n margin: 0;\n}\n\n/* ============================================================\n Chapter markers\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-chapter-marker {\n width: 2px;\n height: 7px;\n background: rgba(0,0,0,.45);\n border-radius: 1px;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* ============================================================\n Volume: expandable slider, white fill\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-volume-control {\n flex-direction: row;\n gap: 0;\n margin-right: 0;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-volume-track {\n width: 0;\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n overflow: hidden;\n transition: width .25s ease, margin .25s ease;\n margin: 0;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-volume-control:hover .eb-volume-track,\n[data-theme=\"lequipe\"] .eb-player .eb-volume-control:focus-within .eb-volume-track {\n width: 66px;\n margin: 0 6px 0 2px;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-volume-fill {\n background: var(--eb-color-primary, #d61e00);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-volume-thumb {\n width: 11px;\n height: 11px;\n background: #fff;\n box-shadow: 0 0 0 2px rgba(255,255,255,.35);\n transform: translate(-50%, -50%) scale(0);\n transition: transform .15s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-volume-control:hover .eb-volume-thumb {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-time-display {\n font-size: 13px;\n color: rgba(255,255,255,.85);\n font-weight: 500;\n letter-spacing: .02em;\n}\n\n/* ============================================================\n Live badge — text badge with blinking dot (not icon)\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync {\n width: auto;\n height: auto;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: .08em;\n text-transform: uppercase;\n gap: 5px;\n}\n\n/* Hide icon, show dot + label */\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync__icon {\n display: none;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync__dot {\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #fff;\n flex-shrink: 0;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync__label {\n display: block;\n}\n\n/* Synced state — red background with blinking dot */\n[data-theme=\"lequipe\"] .eb-player .eb-live-synced {\n background: rgba(214,30,0,.9);\n color: #fff;\n box-shadow: 0 2px 8px rgba(214,30,0,.4);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-live-synced .eb-live-sync__dot {\n animation: eb-lequipe-blink 1.2s ease infinite;\n}\n\n/* Delayed / not-at-live-edge */\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync:not(.eb-live-synced) {\n background: rgba(60,60,80,.75);\n color: rgba(255,255,255,.7);\n box-shadow: none;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync:not(.eb-live-synced) .eb-live-sync__dot {\n background: rgba(255,255,255,.5);\n animation: none;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-live-sync:not(.eb-live-synced):hover {\n background: rgba(214,30,0,.7);\n color: #fff;\n}\n\n@keyframes eb-lequipe-blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: .15; }\n}\n\n/* ============================================================\n Settings panel: glassmorphism dropdown\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-panel {\n background: rgba(30,30,45,.6);\n backdrop-filter: blur(24px) saturate(160%);\n -webkit-backdrop-filter: blur(24px) saturate(160%);\n border-radius: 14px;\n width: min(340px, 80vw);\n max-height: 60vh;\n overflow-y: auto;\n overflow-x: hidden;\n box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.08);\n}\n\n/* Small viewports: compact rows */\n@media (max-height: 400px) {\n [data-theme=\"lequipe\"] .eb-player .eb-settings-category { padding: 12px 14px; font-size: 13px; gap: 10px; }\n [data-theme=\"lequipe\"] .eb-player .eb-settings-item { padding: 11px 14px; font-size: 13px; }\n [data-theme=\"lequipe\"] .eb-player .eb-settings-header { padding: 10px 14px; }\n [data-theme=\"lequipe\"] .eb-player .eb-settings-panel { min-width: 220px; border-radius: 10px; }\n [data-theme=\"lequipe\"] .eb-player .eb-settings-back { width: 30px; height: 30px; }\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-menu {\n padding: 0;\n}\n\n/* Root menu category rows — icon | label | value | chevron */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px 20px;\n font-size: 14px;\n color: rgba(255,255,255,.95);\n border-bottom: 1px solid rgba(255,255,255,.06);\n transition: background .12s;\n width: 100%;\n border: none;\n background: none;\n cursor: pointer;\n text-align: left;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category:last-child {\n border-bottom: none;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category:hover {\n background: rgba(255,255,255,.05);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category__icon {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: rgba(255,255,255,.6);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category__icon .eb-icon {\n width: 22px;\n height: 22px;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category__label {\n flex: 1;\n font-weight: 400;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category__value {\n color: rgba(255,255,255,.45);\n font-size: 13px;\n font-weight: 400;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category__chevron {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: rgba(255,255,255,.3);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category__chevron .eb-icon {\n width: 16px;\n height: 16px;\n}\n\n/* Sub-menu header — circular back button + title */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 18px;\n border-bottom: 1px solid rgba(255,255,255,.08);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-header__title {\n font-size: 15px;\n font-weight: 600;\n color: #fff;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-back {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: rgba(255,255,255,.12);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: background .15s;\n flex-shrink: 0;\n color: #fff;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-back:hover {\n background: rgba(255,255,255,.2);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-back .eb-icon {\n width: 18px;\n height: 18px;\n}\n\n/* Sub-menu items */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n font-size: 14px;\n color: rgba(255,255,255,.7);\n border-bottom: 1px solid rgba(255,255,255,.06);\n transition: background .12s;\n width: 100%;\n border-left: none;\n border-right: none;\n border-top: none;\n background: none;\n cursor: pointer;\n text-align: left;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item:last-child {\n border-bottom: none;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item:hover {\n background: rgba(255,255,255,.05);\n}\n\n/* Selected item text — brighter */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item--selected {\n color: #fff;\n font-weight: 500;\n}\n\n/* Active selection dot (filled accent) */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item--selected::after {\n content: '';\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--eb-accent, #d61e00);\n flex-shrink: 0;\n}\n\n/* Non-selected items: hollow dot */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item:not(.eb-settings-item--selected)::after {\n content: '';\n width: 12px;\n height: 12px;\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,.2);\n flex-shrink: 0;\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-loading .eb-icon {\n width: 52px;\n height: 52px;\n color: rgba(255,255,255,.7);\n filter: drop-shadow(0 1px 6px rgba(0,0,0,.5));\n animation: eb-spin .75s linear infinite;\n}\n\n/* ============================================================\n Error overlay\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-error {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-error-message {\n font-weight: 400;\n letter-spacing: .01em;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-error-retry {\n border-radius: 8px;\n background: rgba(255,255,255,.1);\n border-color: rgba(255,255,255,.15);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-error-retry:hover {\n background: rgba(255,255,255,.18);\n}\n\n/* ============================================================\n Toast (keyboard hints, status messages)\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-toast {\n background: rgba(0,0,0,.72);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border-radius: 10px;\n font-size: 13px;\n padding: 8px 16px;\n}\n\n/* ============================================================\n Info & socials overlays\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-info-overlay,\n[data-theme=\"lequipe\"] .eb-player .eb-socials-overlay {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-info-close,\n[data-theme=\"lequipe\"] .eb-player .eb-socials-close {\n border-radius: 8px;\n background: rgba(255,255,255,.07);\n border-color: rgba(255,255,255,.08);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-info-close:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-socials-close:hover {\n background: rgba(255,255,255,.13);\n color: #fff;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-socials-link {\n background: rgba(255,255,255,.07);\n border: 1px solid rgba(255,255,255,.08);\n border-radius: 8px;\n transition: background .2s, color .2s, border-color .2s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-socials-link:hover {\n background: rgba(214,30,0,.15);\n border-color: rgba(214,30,0,.35);\n color: #ff8a75;\n}\n\n/* ============================================================\n Poster\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-poster {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n\n/* ============================================================\n Radio overlay\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-radio-overlay {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-radio-bar {\n background: rgba(214,30,0,.8);\n}\n\n/* ============================================================\n Chapter skip button\n ============================================================ */\n[data-theme=\"lequipe\"] .eb-player .eb-chapter-skip {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid rgba(255,255,255,.15);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n transition: background .15s;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-chapter-skip:hover {\n background: rgba(255,255,255,.12);\n}\n";
|
|
35
40
|
styleInject(css_248z$5);
|
|
36
41
|
|
|
37
|
-
var css_248z$4 = "/**\n * Modern theme overrides\n *\n * Applied when the container has [data-theme=\"modern\"].\n * Glassmorphism-inspired design with purple accent, Inter font,\n * rounded corners, backdrop blur, and smooth transitions.\n *\n * Reference: player-reference.html\n */\n\n/* ============================================================\n Google Fonts (Inter 300-600)\n ============================================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap');\n\n/* ============================================================\n Icons: override stroke-based defaults for filled Material icons\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-icon {\n fill: currentColor;\n stroke: none;\n stroke-width: 0;\n}\n\n/* ============================================================\n Root vars & container\n ============================================================ */\n[data-theme=\"modern\"] .eb-player {\n --eb-color-primary: #7c3aed;\n --eb-color-progress: #7c3aed;\n --eb-color-background: rgba(10, 10, 20, 0.85);\n --eb-accent: #1a73e8;\n --eb-font-family: 'Inter', sans-serif;\n font-family: 'Inter', sans-serif;\n border-radius: 14px;\n box-shadow: 0 40px 80px rgba(0,0,0,.8), 0 0 0 1px rgba(255,255,255,.06);\n}\n\n/* ============================================================\n Gradients\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-top-bar {\n background: linear-gradient(to bottom, rgba(0,0,0,.72), transparent);\n height: 110px;\n padding: 14px 16px;\n gap: 6px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__gradient {\n height: 150px;\n background: linear-gradient(to top, rgba(0,0,0,.9), transparent);\n}\n\n/* ============================================================\n Top bar: slide-in animation\n ============================================================ */\n[data-theme=\"modern\"] .eb-player.eb-controls-visible .eb-top-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-hidden .eb-top-bar {\n opacity: 0;\n transform: translateY(-6px);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-top-bar__actions {\n gap: 6px;\n}\n\n/* ============================================================\n Bottom bar: slide-up animation + spacing\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__controls-row {\n padding: 0 14px 12px;\n gap: 8px;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-visible .eb-bottom-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-hidden .eb-bottom-bar {\n opacity: 0;\n transform: translateY(8px);\n transition: opacity .3s, transform .3s;\n}\n\n/* ============================================================\n Middle bar: glassmorphism circles + wider gap\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-middle-bar {\n gap: 28px;\n}\n\n/* Controls slide with bottom bar */\n[data-theme=\"modern\"] .eb-player.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity .3s;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity .3s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__play-btn {\n width: 72px;\n height: 72px;\n background: rgba(255,255,255,.18);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n border: 2px solid rgba(255,255,255,.28);\n transition: background .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__play-btn:hover {\n background: rgba(255,255,255,.28);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n width: 30px;\n height: 30px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__seek-btn {\n width: 52px;\n height: 52px;\n border-radius: 50%;\n background: rgba(255,255,255,.14);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n border: 1.5px solid rgba(255,255,255,.22);\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 1px;\n transition: background .15s;\n padding: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,.24);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seek-circle {\n width: 18px;\n height: 18px;\n /* Reference uses filled skip arrows instead of the stroke circle */\n fill: white;\n stroke: none;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seek-label {\n font-size: .58em;\n font-weight: 700;\n color: rgba(255,255,255,.9);\n line-height: 1;\n}\n\n/* ============================================================\n Buttons: rounded, softer color, scale on active\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-button,\n[data-theme=\"modern\"] .eb-player .eb-play-pause,\n[data-theme=\"modern\"] .eb-player .eb-fullscreen,\n[data-theme=\"modern\"] .eb-player .eb-pip,\n[data-theme=\"modern\"] .eb-player .eb-cast,\n[data-theme=\"modern\"] .eb-player .eb-volume-mute,\n[data-theme=\"modern\"] .eb-player .eb-live-sync {\n color: rgba(255,255,255,.82);\n border-radius: 8px;\n width: 38px;\n height: 38px;\n transition: background .15s, color .15s, transform .1s;\n flex-shrink: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-button:hover,\n[data-theme=\"modern\"] .eb-player .eb-play-pause:hover,\n[data-theme=\"modern\"] .eb-player .eb-fullscreen:hover,\n[data-theme=\"modern\"] .eb-player .eb-pip:hover,\n[data-theme=\"modern\"] .eb-player .eb-cast:hover,\n[data-theme=\"modern\"] .eb-player .eb-volume-mute:hover,\n[data-theme=\"modern\"] .eb-player .eb-live-sync:hover {\n background: rgba(255,255,255,.12);\n color: #fff;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-button:active,\n[data-theme=\"modern\"] .eb-player .eb-play-pause:active,\n[data-theme=\"modern\"] .eb-player .eb-fullscreen:active,\n[data-theme=\"modern\"] .eb-player .eb-pip:active,\n[data-theme=\"modern\"] .eb-player .eb-cast:active,\n[data-theme=\"modern\"] .eb-player .eb-volume-mute:active,\n[data-theme=\"modern\"] .eb-player .eb-live-sync:active {\n transform: scale(.88);\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-seekbar-track {\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar:hover .eb-seekbar-track {\n height: 5px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-buffered {\n background: rgba(255,255,255,.28);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-progress {\n background: linear-gradient(90deg, #a78bfa, #7c3aed);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-thumb {\n width: 14px;\n height: 14px;\n right: -7px;\n background: #fff;\n box-shadow: 0 0 0 3px rgba(124,58,237,.45);\n}\n\n/* ============================================================\n Seekbar tooltip & preview\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-seekbar-tooltip {\n bottom: 24px;\n background: rgba(0,0,0,.82);\n border-radius: 5px;\n font-size: 11px;\n padding: 3px 7px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-preview {\n width: 128px;\n height: 72px;\n background: #111;\n border: 2px solid rgba(255,255,255,.16);\n border-radius: 6px;\n}\n\n/* ============================================================\n Chapter markers\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-chapter-marker {\n width: 2px;\n height: 7px;\n background: rgba(0,0,0,.45);\n border-radius: 1px;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* ============================================================\n Volume: expandable slider, white fill\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-volume-control {\n flex-direction: row;\n gap: 0;\n margin-right: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-track {\n width: 0;\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n overflow: hidden;\n transition: width .25s ease, margin .25s ease;\n margin: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-control:hover .eb-volume-track,\n[data-theme=\"modern\"] .eb-player .eb-volume-control:focus-within .eb-volume-track {\n width: 66px;\n margin: 0 6px 0 2px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-fill {\n background: #fff;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-thumb {\n width: 11px;\n height: 11px;\n background: #fff;\n box-shadow: 0 0 0 2px rgba(255,255,255,.35);\n transform: translate(-50%, -50%) scale(0);\n transition: transform .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-control:hover .eb-volume-thumb {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-time-display {\n font-size: 12px;\n color: rgba(255,255,255,.6);\n letter-spacing: .02em;\n}\n\n/* ============================================================\n Live badge\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-live-sync {\n width: auto;\n height: auto;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-live-synced {\n background: rgba(220,38,38,.9);\n color: #fff;\n box-shadow: 0 2px 8px rgba(220,38,38,.4);\n}\n\n/* ============================================================\n Settings panel: glassmorphism + refined layout\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-settings-panel {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(18px) saturate(160%);\n -webkit-backdrop-filter: blur(18px) saturate(160%);\n border-radius: 12px;\n min-width: 280px;\n box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.1);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-menu {\n padding: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-category,\n[data-theme=\"modern\"] .eb-player .eb-settings-item,\n[data-theme=\"modern\"] .eb-player .eb-settings-back {\n padding: 15px 20px;\n font-size: 13px;\n color: rgba(255,255,255,.9);\n border-bottom: 1px solid rgba(255,255,255,.06);\n transition: background .12s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-category:last-child,\n[data-theme=\"modern\"] .eb-player .eb-settings-item:last-child {\n border-bottom: none;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-category:hover,\n[data-theme=\"modern\"] .eb-player .eb-settings-item:hover,\n[data-theme=\"modern\"] .eb-player .eb-settings-back:hover {\n background: rgba(255,255,255,.05);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-item--selected {\n color: #fff;\n font-weight: 500;\n}\n\n/* Active selection dot */\n[data-theme=\"modern\"] .eb-player .eb-settings-item--selected::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #1a73e8;\n box-shadow: 0 0 0 3px rgba(26,115,232,.25);\n flex-shrink: 0;\n}\n\n/* Non-selected items: hollow dot */\n[data-theme=\"modern\"] .eb-player .eb-settings-item:not(.eb-settings-item--selected)::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,.2);\n flex-shrink: 0;\n}\n\n/* Sub-panel back button */\n[data-theme=\"modern\"] .eb-player .eb-settings-back {\n gap: 14px;\n font-weight: 600;\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-loading .eb-icon {\n color: rgba(255,255,255,.7);\n}\n\n/* ============================================================\n Error overlay\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-error {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-error-retry {\n border-radius: 8px;\n background: rgba(255,255,255,.1);\n border-color: rgba(255,255,255,.15);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-error-retry:hover {\n background: rgba(255,255,255,.18);\n}\n\n/* ============================================================\n Toast\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-toast {\n background: rgba(0,0,0,.72);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border-radius: 10px;\n font-size: 13px;\n}\n\n/* ============================================================\n Info & socials overlays\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-info-overlay,\n[data-theme=\"modern\"] .eb-player .eb-socials-overlay {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-info-close,\n[data-theme=\"modern\"] .eb-player .eb-socials-close {\n border-radius: 8px;\n background: rgba(255,255,255,.07);\n border-color: rgba(255,255,255,.08);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-info-close:hover,\n[data-theme=\"modern\"] .eb-player .eb-socials-close:hover {\n background: rgba(255,255,255,.13);\n color: #fff;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-socials-link {\n background: rgba(255,255,255,.07);\n border: 1px solid rgba(255,255,255,.08);\n border-radius: 8px;\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-socials-link:hover {\n background: rgba(167,139,250,.15);\n border-color: rgba(167,139,250,.35);\n color: #c4b5fd;\n}\n\n/* ============================================================\n Bottom bar: two-row layout (seekbar above, buttons below)\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__controls-row {\n flex-wrap: wrap;\n}\n\n/* Seekbar fills full width as its own row */\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__seekbar-zone {\n flex: none;\n width: 100%;\n order: -1;\n margin-bottom: -6px;\n}\n\n/* Time display sits before seekbar visually (after live badge) */\n[data-theme=\"modern\"] .eb-player .eb-slot-time {\n order: -1;\n margin-left: auto;\n}\n\n/* Live sync badge before time */\n[data-theme=\"modern\"] .eb-player .eb-slot-live-sync {\n order: -2;\n}\n\n/* Move settings + pip to right end of control row */\n[data-theme=\"modern\"] .eb-player .eb-slot-settings {\n margin-left: auto;\n}\n\n/* ============================================================\n Poster\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-poster {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n";
|
|
42
|
+
var css_248z$4 = "/**\n * Modern theme overrides\n *\n * Applied when the container has [data-theme=\"modern\"].\n * Glassmorphism-inspired design with purple accent, Inter font,\n * rounded corners, backdrop blur, and smooth transitions.\n *\n * Reference: player-reference.html\n */\n\n/* ============================================================\n Google Fonts (Inter 300-600)\n ============================================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap');\n\n/* ============================================================\n Icons: override stroke-based defaults for filled Material icons\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-icon {\n fill: currentColor;\n stroke: none;\n stroke-width: 0;\n}\n\n/* ============================================================\n Root vars & container\n ============================================================ */\n[data-theme=\"modern\"] .eb-player {\n --eb-color-primary: #7c3aed;\n --eb-color-progress: #7c3aed;\n --eb-color-background: rgba(10, 10, 20, 0.85);\n --eb-accent: #1a73e8;\n --eb-font-family: 'Inter', sans-serif;\n font-family: 'Inter', sans-serif;\n border-radius: 14px;\n box-shadow: 0 40px 80px rgba(0,0,0,.8), 0 0 0 1px rgba(255,255,255,.06);\n}\n\n/* ============================================================\n Gradients\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-top-bar {\n background: linear-gradient(to bottom, rgba(0,0,0,.72), transparent);\n height: 110px;\n padding: 14px 16px;\n gap: 6px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__gradient {\n height: 150px;\n background: linear-gradient(to top, rgba(0,0,0,.9), transparent);\n}\n\n/* ============================================================\n Top bar: slide-in animation\n ============================================================ */\n[data-theme=\"modern\"] .eb-player.eb-controls-visible .eb-top-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-hidden .eb-top-bar {\n opacity: 0;\n transform: translateY(-6px);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-top-bar__actions {\n gap: 6px;\n}\n\n/* ============================================================\n Bottom bar: slide-up animation + spacing\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__controls-row {\n padding: 0 14px 12px;\n gap: 8px;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-visible .eb-bottom-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-hidden .eb-bottom-bar {\n opacity: 0;\n transform: translateY(8px);\n transition: opacity .3s, transform .3s;\n}\n\n/* ============================================================\n Middle bar: glassmorphism circles + wider gap\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-middle-bar {\n gap: 28px;\n}\n\n/* Controls slide with bottom bar */\n[data-theme=\"modern\"] .eb-player.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity .3s;\n}\n\n[data-theme=\"modern\"] .eb-player.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity .3s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__play-btn {\n width: 72px;\n height: 72px;\n background: rgba(255,255,255,.18);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n border: 2px solid rgba(255,255,255,.28);\n transition: background .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__play-btn:hover {\n background: rgba(255,255,255,.28);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n width: 30px;\n height: 30px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__seek-btn {\n width: 52px;\n height: 52px;\n border-radius: 50%;\n background: rgba(255,255,255,.14);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n border: 1.5px solid rgba(255,255,255,.22);\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 1px;\n transition: background .15s;\n padding: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,.24);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seek-circle {\n width: 18px;\n height: 18px;\n /* Reference uses filled skip arrows instead of the stroke circle */\n fill: white;\n stroke: none;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seek-label {\n font-size: .58em;\n font-weight: 700;\n color: rgba(255,255,255,.9);\n line-height: 1;\n}\n\n/* ============================================================\n Buttons: rounded, softer color, scale on active\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-button,\n[data-theme=\"modern\"] .eb-player .eb-play-pause,\n[data-theme=\"modern\"] .eb-player .eb-fullscreen,\n[data-theme=\"modern\"] .eb-player .eb-pip,\n[data-theme=\"modern\"] .eb-player .eb-cast,\n[data-theme=\"modern\"] .eb-player .eb-volume-mute,\n[data-theme=\"modern\"] .eb-player .eb-live-sync {\n color: rgba(255,255,255,.82);\n border-radius: 8px;\n width: 38px;\n height: 38px;\n transition: background .15s, color .15s, transform .1s;\n flex-shrink: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-button:hover,\n[data-theme=\"modern\"] .eb-player .eb-play-pause:hover,\n[data-theme=\"modern\"] .eb-player .eb-fullscreen:hover,\n[data-theme=\"modern\"] .eb-player .eb-pip:hover,\n[data-theme=\"modern\"] .eb-player .eb-cast:hover,\n[data-theme=\"modern\"] .eb-player .eb-volume-mute:hover,\n[data-theme=\"modern\"] .eb-player .eb-live-sync:hover {\n background: rgba(255,255,255,.12);\n color: #fff;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-button:active,\n[data-theme=\"modern\"] .eb-player .eb-play-pause:active,\n[data-theme=\"modern\"] .eb-player .eb-fullscreen:active,\n[data-theme=\"modern\"] .eb-player .eb-pip:active,\n[data-theme=\"modern\"] .eb-player .eb-cast:active,\n[data-theme=\"modern\"] .eb-player .eb-volume-mute:active,\n[data-theme=\"modern\"] .eb-player .eb-live-sync:active {\n transform: scale(.88);\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-seekbar-track {\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar:hover .eb-seekbar-track {\n height: 5px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-buffered {\n background: rgba(255,255,255,.28);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-progress {\n background: linear-gradient(90deg, #a78bfa, #7c3aed);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-thumb {\n width: 14px;\n height: 14px;\n right: -7px;\n background: #fff;\n box-shadow: 0 0 0 3px rgba(124,58,237,.45);\n}\n\n/* ============================================================\n Seekbar tooltip & preview\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-seekbar-tooltip {\n bottom: 24px;\n background: rgba(0,0,0,.82);\n border-radius: 5px;\n font-size: 11px;\n padding: 3px 7px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-seekbar-preview {\n width: 128px;\n height: 72px;\n background: #111;\n border: 2px solid rgba(255,255,255,.16);\n border-radius: 6px;\n}\n\n/* ============================================================\n Chapter markers\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-chapter-marker {\n width: 2px;\n height: 7px;\n background: rgba(0,0,0,.45);\n border-radius: 1px;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* ============================================================\n Volume: expandable slider, white fill\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-volume-control {\n flex-direction: row;\n gap: 0;\n margin-right: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-track {\n width: 0;\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n overflow: hidden;\n transition: width .25s ease, margin .25s ease;\n margin: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-control:hover .eb-volume-track,\n[data-theme=\"modern\"] .eb-player .eb-volume-control:focus-within .eb-volume-track {\n width: 66px;\n margin: 0 6px 0 2px;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-fill {\n background: var(--eb-color-primary, #7c3aed);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-thumb {\n width: 11px;\n height: 11px;\n background: #fff;\n box-shadow: 0 0 0 2px rgba(255,255,255,.35);\n transform: translate(-50%, -50%) scale(0);\n transition: transform .15s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-volume-control:hover .eb-volume-thumb {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-time-display {\n font-size: 12px;\n color: rgba(255,255,255,.6);\n letter-spacing: .02em;\n}\n\n/* ============================================================\n Live badge\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-live-sync {\n width: auto;\n height: auto;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-live-synced {\n background: rgba(220,38,38,.9);\n color: #fff;\n box-shadow: 0 2px 8px rgba(220,38,38,.4);\n}\n\n/* ============================================================\n Settings panel: glassmorphism + refined layout\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-settings-panel {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(18px) saturate(160%);\n -webkit-backdrop-filter: blur(18px) saturate(160%);\n border-radius: 12px;\n min-width: 280px;\n box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.1);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-menu {\n padding: 0;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-category,\n[data-theme=\"modern\"] .eb-player .eb-settings-item,\n[data-theme=\"modern\"] .eb-player .eb-settings-back {\n padding: 15px 20px;\n font-size: 13px;\n color: rgba(255,255,255,.9);\n border-bottom: 1px solid rgba(255,255,255,.06);\n transition: background .12s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-category:last-child,\n[data-theme=\"modern\"] .eb-player .eb-settings-item:last-child {\n border-bottom: none;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-category:hover,\n[data-theme=\"modern\"] .eb-player .eb-settings-item:hover,\n[data-theme=\"modern\"] .eb-player .eb-settings-back:hover {\n background: rgba(255,255,255,.05);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-settings-item--selected {\n color: #fff;\n font-weight: 500;\n}\n\n/* Active selection dot */\n[data-theme=\"modern\"] .eb-player .eb-settings-item--selected::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #1a73e8;\n box-shadow: 0 0 0 3px rgba(26,115,232,.25);\n flex-shrink: 0;\n}\n\n/* Non-selected items: hollow dot */\n[data-theme=\"modern\"] .eb-player .eb-settings-item:not(.eb-settings-item--selected)::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,.2);\n flex-shrink: 0;\n}\n\n/* Sub-panel back button */\n[data-theme=\"modern\"] .eb-player .eb-settings-back {\n gap: 14px;\n font-weight: 600;\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-loading .eb-icon {\n color: rgba(255,255,255,.7);\n}\n\n/* ============================================================\n Error overlay\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-error {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-error-retry {\n border-radius: 8px;\n background: rgba(255,255,255,.1);\n border-color: rgba(255,255,255,.15);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-error-retry:hover {\n background: rgba(255,255,255,.18);\n}\n\n/* ============================================================\n Toast\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-toast {\n background: rgba(0,0,0,.72);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border-radius: 10px;\n font-size: 13px;\n}\n\n/* ============================================================\n Info & socials overlays\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-info-overlay,\n[data-theme=\"modern\"] .eb-player .eb-socials-overlay {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"modern\"] .eb-player .eb-info-close,\n[data-theme=\"modern\"] .eb-player .eb-socials-close {\n border-radius: 8px;\n background: rgba(255,255,255,.07);\n border-color: rgba(255,255,255,.08);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-info-close:hover,\n[data-theme=\"modern\"] .eb-player .eb-socials-close:hover {\n background: rgba(255,255,255,.13);\n color: #fff;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-socials-link {\n background: rgba(255,255,255,.07);\n border: 1px solid rgba(255,255,255,.08);\n border-radius: 8px;\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"modern\"] .eb-player .eb-socials-link:hover {\n background: rgba(167,139,250,.15);\n border-color: rgba(167,139,250,.35);\n color: #c4b5fd;\n}\n\n/* ============================================================\n Bottom bar: two-row layout (seekbar above, buttons below)\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__controls-row {\n flex-wrap: wrap;\n}\n\n/* Seekbar fills full width as its own row */\n[data-theme=\"modern\"] .eb-player .eb-bottom-bar__seekbar-zone {\n flex: none;\n width: 100%;\n order: -1;\n margin-bottom: -6px;\n}\n\n/* Time display sits before seekbar visually (after live badge) */\n[data-theme=\"modern\"] .eb-player .eb-slot-time {\n order: -1;\n margin-left: auto;\n}\n\n/* Live sync badge before time */\n[data-theme=\"modern\"] .eb-player .eb-slot-live-sync {\n order: -2;\n}\n\n/* Move settings + pip to right end of control row */\n[data-theme=\"modern\"] .eb-player .eb-slot-settings {\n margin-left: auto;\n}\n\n/* ============================================================\n Poster\n ============================================================ */\n[data-theme=\"modern\"] .eb-player .eb-poster {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n";
|
|
38
43
|
styleInject(css_248z$4);
|
|
39
44
|
|
|
40
45
|
var css_248z$3 = "/**\n * Radio theme overrides\n *\n * Applied when the container has [data-theme=\"radio\"].\n * Uses higher specificity than base.css .eb-player selector.\n */\n\n[data-theme=\"radio\"] .eb-player {\n --eb-color-primary: #F4A261;\n --eb-color-background: rgba(20, 20, 30, 0.95);\n}\n";
|
|
@@ -43,10 +48,10 @@ var EBPlayerBundle = (function (exports) {
|
|
|
43
48
|
var css_248z$2 = "/**\n * SNRT theme overrides\n *\n * Applied when the container has [data-theme=\"snrt\"].\n * Uses higher specificity than base.css .eb-player selector.\n */\n\n[data-theme=\"snrt\"] .eb-player {\n --eb-color-primary: #006633;\n --eb-color-background: rgba(0, 0, 0, 0.9);\n}\n";
|
|
44
49
|
styleInject(css_248z$2);
|
|
45
50
|
|
|
46
|
-
var css_248z$1 = "/**\n * V2 theme — based on snrtlive.ma (Aloula) player styling\n *\n * Applied when the container has [data-theme=\"v2\"].\n * Dark UI with orange accent (#ff841f), Inter font, rounded container,\n * backdrop-blur panels, expandable volume, two-row bottom bar\n * (seekbar on top, buttons below), gradient overlays, centered\n * frosted-glass transport circles, and refined slide/fade animations.\n */\n\n/* ============================================================\n Google Fonts (Inter 300-700)\n ============================================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');\n\n/* ============================================================\n Root vars & container\n ============================================================ */\n[data-theme=\"v2\"] .eb-player {\n --eb-color-primary: #ff841f;\n --eb-color-progress: #ff841f;\n --eb-color-background: rgba(10, 10, 20, 0.85);\n --eb-accent: #ff841f;\n --eb-color-text: #fff;\n --eb-font-family: 'Inter', -apple-system, sans-serif;\n --eb-font-size-base: 14px;\n --eb-radius-control: 8px;\n --eb-duration-transition: 200ms;\n font-family: 'Inter', -apple-system, sans-serif;\n border-radius: 14px;\n box-shadow: 0 40px 80px rgba(0,0,0,.8), 0 0 0 1px rgba(255,255,255,.06);\n color: #fff;\n}\n\n/* ============================================================\n Icons: bolder stroke weight to match filled-style target\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-icon {\n stroke-width: 2.5;\n}\n\n/* Fullscreen: fill viewport, drop card styling */\n[data-theme=\"v2\"] .eb-player:fullscreen,\n[data-theme=\"v2\"] .eb-player:-webkit-full-screen {\n border-radius: 0;\n box-shadow: none;\n}\n\n/* ============================================================\n Gradients (top & bottom)\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-top-bar {\n background: linear-gradient(to bottom, rgba(0,0,0,.72), transparent);\n height: 110px;\n padding: 14px 16px;\n gap: 6px;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-bottom-bar__gradient {\n height: 150px;\n background: linear-gradient(to top, rgba(0,0,0,.9), transparent);\n}\n\n/* ============================================================\n Top bar: slide-in from above\n ============================================================ */\n[data-theme=\"v2\"] .eb-player.eb-controls-visible .eb-top-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-hidden .eb-top-bar {\n opacity: 0;\n transform: translateY(-6px);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-top-bar__actions {\n gap: 6px;\n}\n\n/* Logo */\n[data-theme=\"v2\"] .eb-player .eb-top-bar__logo {\n max-height: 32px;\n max-width: 120px;\n opacity: .85;\n}\n\n/* ============================================================\n Bottom bar: slide-up animation + spacing\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-bottom-bar__controls-row {\n padding: 0 14px 12px;\n gap: 8px;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-visible .eb-bottom-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-hidden .eb-bottom-bar {\n opacity: 0;\n transform: translateY(8px);\n transition: opacity .3s, transform .3s;\n}\n\n/* ============================================================\n Bottom bar: single-row layout\n play | live | time | ——seekbar—— | settings | volume | fullscreen\n PiP / Cast are in the top bar (via THEME_LAYOUTS.v2 in config.ts)\n ============================================================ */\n\n/* ============================================================\n Middle bar: glassmorphism transport circles\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-middle-bar {\n gap: 28px;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity .3s;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity .3s;\n}\n\n/* Central play/pause — large frosted circle */\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255,255,255,.15);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 2px solid rgba(255,255,255,.25);\n color: #fff;\n padding: 0;\n transition: background .15s, transform .25s, opacity .25s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn:hover {\n background: rgba(255,255,255,.25);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn:active {\n transform: scale(.92);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n width: 32px;\n height: 32px;\n stroke-width: 2.5;\n}\n\n/* Seek buttons — smaller frosted circles, same style as play button */\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__seek-btn {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(255,255,255,.15);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 2px solid rgba(255,255,255,.25);\n color: #fff;\n gap: 1px;\n padding: 0;\n transition: background .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,.25);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seek-circle {\n width: 24px;\n height: 24px;\n color: rgba(255,255,255,.85);\n fill: currentColor;\n stroke: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seek-label {\n font-size: .75em;\n font-weight: 700;\n color: rgba(255,255,255,.9);\n line-height: 1;\n}\n\n/* ============================================================\n Buttons: rounded, soft color, scale on press\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn),\n[data-theme=\"v2\"] .eb-player .eb-play-pause,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen,\n[data-theme=\"v2\"] .eb-player .eb-pip,\n[data-theme=\"v2\"] .eb-player .eb-cast,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute,\n[data-theme=\"v2\"] .eb-player .eb-live-sync {\n color: rgba(255,255,255,.82);\n border-radius: 8px;\n width: 38px;\n height: 38px;\n transition: background .15s, color .15s, transform .1s;\n flex-shrink: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn):hover,\n[data-theme=\"v2\"] .eb-player .eb-play-pause:hover,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen:hover,\n[data-theme=\"v2\"] .eb-player .eb-pip:hover,\n[data-theme=\"v2\"] .eb-player .eb-cast:hover,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute:hover,\n[data-theme=\"v2\"] .eb-player .eb-live-sync:hover {\n background: rgba(255,255,255,.12);\n color: #fff;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn):active,\n[data-theme=\"v2\"] .eb-player .eb-play-pause:active,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen:active,\n[data-theme=\"v2\"] .eb-player .eb-pip:active,\n[data-theme=\"v2\"] .eb-player .eb-cast:active,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute:active,\n[data-theme=\"v2\"] .eb-player .eb-live-sync:active {\n transform: scale(.88);\n}\n\n/* Icon size inside buttons (not middle bar transport) */\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn) .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-play-pause .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-pip .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-cast .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute .eb-icon {\n width: 22px;\n height: 22px;\n}\n\n/* Top bar icons slightly larger */\n[data-theme=\"v2\"] .eb-player .eb-top-bar .eb-icon {\n width: 24px;\n height: 24px;\n}\n\n/* Play/pause icons should be filled (solid), not stroke outlines */\n[data-theme=\"v2\"] .eb-player .eb-play-pause .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n fill: currentColor;\n stroke: none;\n}\n\n/* Volume icon: fill the speaker body, keep stroke for sound waves */\n[data-theme=\"v2\"] .eb-player .eb-volume-mute .eb-icon path:first-child {\n fill: currentColor;\n}\n\n/* Cast button active state — cyan */\n[data-theme=\"v2\"] .eb-player .eb-cast-active {\n color: #1eb6d4 !important;\n background: rgba(30, 182, 212, .15) !important;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-cast-active .eb-icon {\n filter: drop-shadow(0 0 4px rgba(30, 182, 212, .6));\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-seekbar-track {\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar:hover .eb-seekbar-track {\n height: 5px;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar-buffered {\n background: rgba(255,255,255,.28);\n border-radius: 3px;\n transition: height .15s;\n}\n\n/* Orange gradient fill */\n[data-theme=\"v2\"] .eb-player .eb-seekbar-progress {\n background: linear-gradient(90deg, #ff841f, color-mix(in srgb, #ff841f 70%, #fff));\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar-thumb {\n width: 14px;\n height: 14px;\n right: -7px;\n background: #fff;\n box-shadow: 0 0 0 3px rgba(255,132,31,.45);\n}\n\n/* ============================================================\n Seekbar tooltip & preview\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-seekbar-tooltip {\n bottom: 28px;\n background: rgba(0,0,0,.88);\n border: 1px solid rgba(255,255,255,.12);\n border-radius: 7px;\n font-size: 11px;\n font-weight: 500;\n padding: 0;\n overflow: hidden;\n box-shadow: 0 4px 16px rgba(0,0,0,.5);\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar-preview {\n width: 160px;\n height: 90px;\n background: #111;\n border: none;\n border-radius: 0;\n margin: 0;\n}\n\n/* ============================================================\n Chapter markers\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-chapter-marker {\n width: 2px;\n height: 7px;\n background: rgba(0,0,0,.45);\n border-radius: 1px;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* ============================================================\n Volume: expandable slider, white fill\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-volume-control {\n flex-direction: row;\n gap: 0;\n margin-right: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-track {\n width: 0;\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n overflow: hidden;\n transition: width .25s ease, margin .25s ease;\n margin: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-control:hover .eb-volume-track,\n[data-theme=\"v2\"] .eb-player .eb-volume-control:focus-within .eb-volume-track {\n width: 66px;\n margin: 0 6px 0 2px;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-fill {\n background: #fff;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-thumb {\n width: 11px;\n height: 11px;\n background: #fff;\n box-shadow: 0 0 0 2px rgba(255,255,255,.35);\n transform: translate(-50%, -50%) scale(0);\n transition: transform .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-control:hover .eb-volume-thumb {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-time-display {\n font-size: 13px;\n color: rgba(255,255,255,.85);\n font-weight: 500;\n letter-spacing: .02em;\n}\n\n/* ============================================================\n Live badge — text badge with blinking dot (not icon)\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-live-sync {\n width: auto;\n height: auto;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: .08em;\n text-transform: uppercase;\n gap: 5px;\n}\n\n/* Hide icon, show dot + label */\n[data-theme=\"v2\"] .eb-player .eb-live-sync__icon {\n display: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync__dot {\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #fff;\n flex-shrink: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync__label {\n display: block;\n}\n\n/* Synced state — red background with blinking dot */\n[data-theme=\"v2\"] .eb-player .eb-live-synced {\n background: rgba(220,38,38,.9);\n color: #fff;\n box-shadow: 0 2px 8px rgba(220,38,38,.4);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-synced .eb-live-sync__dot {\n animation: eb-v2-blink 1.2s ease infinite;\n}\n\n/* Delayed / not-at-live-edge */\n[data-theme=\"v2\"] .eb-player .eb-live-sync:not(.eb-live-synced) {\n background: rgba(60,60,80,.75);\n color: rgba(255,255,255,.7);\n box-shadow: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync:not(.eb-live-synced) .eb-live-sync__dot {\n background: rgba(255,255,255,.5);\n animation: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync:not(.eb-live-synced):hover {\n background: rgba(220,38,38,.7);\n color: #fff;\n}\n\n@keyframes eb-v2-blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: .15; }\n}\n\n/* ============================================================\n Settings panel: glassmorphism dropdown\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-settings-panel {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(18px) saturate(160%);\n -webkit-backdrop-filter: blur(18px) saturate(160%);\n border-radius: 12px;\n min-width: 300px;\n box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.1);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-menu {\n padding: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-category,\n[data-theme=\"v2\"] .eb-player .eb-settings-item,\n[data-theme=\"v2\"] .eb-player .eb-settings-back {\n padding: 15px 20px;\n font-size: 13px;\n color: rgba(255,255,255,.9);\n border-bottom: 1px solid rgba(255,255,255,.06);\n transition: background .12s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-category:last-child,\n[data-theme=\"v2\"] .eb-player .eb-settings-item:last-child {\n border-bottom: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-category:hover,\n[data-theme=\"v2\"] .eb-player .eb-settings-item:hover,\n[data-theme=\"v2\"] .eb-player .eb-settings-back:hover {\n background: rgba(255,255,255,.05);\n}\n\n/* Selected item text */\n[data-theme=\"v2\"] .eb-player .eb-settings-item--selected {\n color: #fff;\n font-weight: 500;\n}\n\n/* Active selection dot (filled orange) */\n[data-theme=\"v2\"] .eb-player .eb-settings-item--selected::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--eb-accent, #ff841f);\n box-shadow: 0 0 0 3px rgba(255,132,31,.25);\n flex-shrink: 0;\n}\n\n/* Non-selected items: hollow dot */\n[data-theme=\"v2\"] .eb-player .eb-settings-item:not(.eb-settings-item--selected)::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,.2);\n flex-shrink: 0;\n}\n\n/* Back button */\n[data-theme=\"v2\"] .eb-player .eb-settings-back {\n gap: 14px;\n font-weight: 600;\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-loading .eb-icon {\n width: 52px;\n height: 52px;\n color: rgba(255,255,255,.7);\n filter: drop-shadow(0 1px 6px rgba(0,0,0,.5));\n animation: eb-spin .75s linear infinite;\n}\n\n/* ============================================================\n Error overlay\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-error {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-error-message {\n font-weight: 400;\n letter-spacing: .01em;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-error-retry {\n border-radius: 8px;\n background: rgba(255,255,255,.1);\n border-color: rgba(255,255,255,.15);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-error-retry:hover {\n background: rgba(255,255,255,.18);\n}\n\n/* ============================================================\n Toast (keyboard hints, status messages)\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-toast {\n background: rgba(0,0,0,.72);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border-radius: 10px;\n font-size: 13px;\n padding: 8px 16px;\n}\n\n/* ============================================================\n Info & socials overlays\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-info-overlay,\n[data-theme=\"v2\"] .eb-player .eb-socials-overlay {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-info-close,\n[data-theme=\"v2\"] .eb-player .eb-socials-close {\n border-radius: 8px;\n background: rgba(255,255,255,.07);\n border-color: rgba(255,255,255,.08);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-info-close:hover,\n[data-theme=\"v2\"] .eb-player .eb-socials-close:hover {\n background: rgba(255,255,255,.13);\n color: #fff;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-socials-link {\n background: rgba(255,255,255,.07);\n border: 1px solid rgba(255,255,255,.08);\n border-radius: 8px;\n transition: background .2s, color .2s, border-color .2s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-socials-link:hover {\n background: rgba(255,132,31,.15);\n border-color: rgba(255,132,31,.35);\n color: #ffb980;\n}\n\n/* ============================================================\n Poster\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-poster {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n\n/* ============================================================\n Radio overlay\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-radio-overlay {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-radio-bar {\n background: rgba(255,132,31,.8);\n}\n\n/* ============================================================\n Chapter skip button\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-chapter-skip {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid rgba(255,255,255,.15);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n transition: background .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-chapter-skip:hover {\n background: rgba(255,255,255,.12);\n}\n";
|
|
51
|
+
var css_248z$1 = "/**\n * V2 theme — based on snrtlive.ma (Aloula) player styling\n *\n * Applied when the container has [data-theme=\"v2\"].\n * Dark UI with orange accent (#ff841f), Inter font, rounded container,\n * backdrop-blur panels, expandable volume, two-row bottom bar\n * (seekbar on top, buttons below), gradient overlays, centered\n * frosted-glass transport circles, and refined slide/fade animations.\n */\n\n/* ============================================================\n Google Fonts (Inter 300-700)\n ============================================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');\n\n/* ============================================================\n Root vars & container\n ============================================================ */\n[data-theme=\"v2\"] .eb-player {\n --eb-color-primary: #ff841f;\n --eb-color-progress: #ff841f;\n --eb-color-background: rgba(10, 10, 20, 0.85);\n --eb-accent: #ff841f;\n --eb-color-text: #fff;\n --eb-font-family: 'Inter', -apple-system, sans-serif;\n --eb-font-size-base: 14px;\n --eb-radius-control: 8px;\n --eb-duration-transition: 200ms;\n font-family: 'Inter', -apple-system, sans-serif;\n border-radius: 14px;\n box-shadow: 0 40px 80px rgba(0,0,0,.8), 0 0 0 1px rgba(255,255,255,.06);\n color: #fff;\n}\n\n/* ============================================================\n Icons: bolder stroke weight to match filled-style target\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-icon {\n stroke-width: 2.5;\n}\n\n/* Fullscreen: fill viewport, drop card styling */\n[data-theme=\"v2\"] .eb-player:fullscreen,\n[data-theme=\"v2\"] .eb-player:-webkit-full-screen {\n border-radius: 0;\n box-shadow: none;\n}\n\n/* ============================================================\n Gradients (top & bottom)\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-top-bar {\n background: linear-gradient(to bottom, rgba(0,0,0,.72), transparent);\n height: 110px;\n padding: 14px 16px;\n gap: 6px;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-bottom-bar__gradient {\n height: 150px;\n background: linear-gradient(to top, rgba(0,0,0,.9), transparent);\n}\n\n/* ============================================================\n Top bar: slide-in from above\n ============================================================ */\n[data-theme=\"v2\"] .eb-player.eb-controls-visible .eb-top-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-hidden .eb-top-bar {\n opacity: 0;\n transform: translateY(-6px);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-top-bar__actions {\n gap: 6px;\n}\n\n/* Logo */\n[data-theme=\"v2\"] .eb-player .eb-top-bar__logo {\n max-height: 32px;\n max-width: 120px;\n opacity: .85;\n}\n\n/* ============================================================\n Bottom bar: slide-up animation + spacing\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-bottom-bar__controls-row {\n padding: 0 14px 12px;\n gap: 8px;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-visible .eb-bottom-bar {\n opacity: 1;\n transform: translateY(0);\n transition: opacity .3s, transform .3s;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-hidden .eb-bottom-bar {\n opacity: 0;\n transform: translateY(8px);\n transition: opacity .3s, transform .3s;\n}\n\n/* ============================================================\n Bottom bar: single-row layout\n play | live | time | ——seekbar—— | settings | volume | fullscreen\n PiP / Cast are in the top bar (via THEME_LAYOUTS.v2 in config.ts)\n ============================================================ */\n\n/* ============================================================\n Middle bar: glassmorphism transport circles\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-middle-bar {\n gap: 28px;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity .3s;\n}\n\n[data-theme=\"v2\"] .eb-player.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity .3s;\n}\n\n/* Central play/pause — large frosted circle */\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255,255,255,.15);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 2px solid rgba(255,255,255,.25);\n color: #fff;\n padding: 0;\n transition: background .15s, transform .25s, opacity .25s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn:hover {\n background: rgba(255,255,255,.25);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn:active {\n transform: scale(.92);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n width: 32px;\n height: 32px;\n stroke-width: 2.5;\n}\n\n/* Seek buttons — smaller frosted circles, same style as play button */\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__seek-btn {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(255,255,255,.15);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 2px solid rgba(255,255,255,.25);\n color: #fff;\n gap: 1px;\n padding: 0;\n transition: background .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,.25);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seek-circle {\n width: 24px;\n height: 24px;\n color: rgba(255,255,255,.85);\n fill: currentColor;\n stroke: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seek-label {\n font-size: .75em;\n font-weight: 700;\n color: rgba(255,255,255,.9);\n line-height: 1;\n}\n\n/* ============================================================\n Buttons: rounded, soft color, scale on press\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn),\n[data-theme=\"v2\"] .eb-player .eb-play-pause,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen,\n[data-theme=\"v2\"] .eb-player .eb-pip,\n[data-theme=\"v2\"] .eb-player .eb-cast,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute,\n[data-theme=\"v2\"] .eb-player .eb-live-sync {\n color: rgba(255,255,255,.82);\n border-radius: 8px;\n width: 38px;\n height: 38px;\n transition: background .15s, color .15s, transform .1s;\n flex-shrink: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn):hover,\n[data-theme=\"v2\"] .eb-player .eb-play-pause:hover,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen:hover,\n[data-theme=\"v2\"] .eb-player .eb-pip:hover,\n[data-theme=\"v2\"] .eb-player .eb-cast:hover,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute:hover,\n[data-theme=\"v2\"] .eb-player .eb-live-sync:hover {\n background: rgba(255,255,255,.12);\n color: #fff;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn):active,\n[data-theme=\"v2\"] .eb-player .eb-play-pause:active,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen:active,\n[data-theme=\"v2\"] .eb-player .eb-pip:active,\n[data-theme=\"v2\"] .eb-player .eb-cast:active,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute:active,\n[data-theme=\"v2\"] .eb-player .eb-live-sync:active {\n transform: scale(.88);\n}\n\n/* Icon size inside buttons (not middle bar transport) */\n[data-theme=\"v2\"] .eb-player .eb-button:not(.eb-middle-bar__seek-btn):not(.eb-middle-bar__play-btn) .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-play-pause .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-fullscreen .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-pip .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-cast .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-volume-mute .eb-icon {\n width: 22px;\n height: 22px;\n}\n\n/* Top bar icons slightly larger */\n[data-theme=\"v2\"] .eb-player .eb-top-bar .eb-icon {\n width: 24px;\n height: 24px;\n}\n\n/* Play/pause icons should be filled (solid), not stroke outlines */\n[data-theme=\"v2\"] .eb-player .eb-play-pause .eb-icon,\n[data-theme=\"v2\"] .eb-player .eb-middle-bar__play-btn .eb-icon {\n fill: currentColor;\n stroke: none;\n}\n\n/* Volume icon: fill the speaker body, keep stroke for sound waves */\n[data-theme=\"v2\"] .eb-player .eb-volume-mute .eb-icon path:first-child {\n fill: currentColor;\n}\n\n/* Cast button active state — cyan */\n[data-theme=\"v2\"] .eb-player .eb-cast-active {\n color: #1eb6d4 !important;\n background: rgba(30, 182, 212, .15) !important;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-cast-active .eb-icon {\n filter: drop-shadow(0 0 4px rgba(30, 182, 212, .6));\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-seekbar-track {\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar:hover .eb-seekbar-track {\n height: 5px;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar-buffered {\n background: rgba(255,255,255,.28);\n border-radius: 3px;\n transition: height .15s;\n}\n\n/* Orange gradient fill */\n[data-theme=\"v2\"] .eb-player .eb-seekbar-progress {\n background: linear-gradient(90deg, #ff841f, color-mix(in srgb, #ff841f 70%, #fff));\n border-radius: 3px;\n transition: height .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar-thumb {\n width: 14px;\n height: 14px;\n right: -7px;\n background: #fff;\n box-shadow: 0 0 0 3px rgba(255,132,31,.45);\n}\n\n/* ============================================================\n Seekbar tooltip & preview\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-seekbar-tooltip {\n bottom: 28px;\n background: rgba(0,0,0,.88);\n border: 1px solid rgba(255,255,255,.12);\n border-radius: 7px;\n font-size: 11px;\n font-weight: 500;\n padding: 0;\n overflow: hidden;\n box-shadow: 0 4px 16px rgba(0,0,0,.5);\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-seekbar-preview {\n width: 160px;\n height: 90px;\n background: #111;\n border: none;\n border-radius: 0;\n margin: 0;\n}\n\n/* ============================================================\n Chapter markers\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-chapter-marker {\n width: 2px;\n height: 7px;\n background: rgba(0,0,0,.45);\n border-radius: 1px;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* ============================================================\n Volume: expandable slider, white fill\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-volume-control {\n flex-direction: row;\n gap: 0;\n margin-right: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-track {\n width: 0;\n height: 3px;\n background: rgba(255,255,255,.22);\n border-radius: 3px;\n overflow: hidden;\n transition: width .25s ease, margin .25s ease;\n margin: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-control:hover .eb-volume-track,\n[data-theme=\"v2\"] .eb-player .eb-volume-control:focus-within .eb-volume-track {\n width: 66px;\n margin: 0 6px 0 2px;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-fill {\n background: var(--eb-color-primary, #ff841f);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-thumb {\n width: 11px;\n height: 11px;\n background: #fff;\n box-shadow: 0 0 0 2px rgba(255,255,255,.35);\n transform: translate(-50%, -50%) scale(0);\n transition: transform .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-volume-control:hover .eb-volume-thumb {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-time-display {\n font-size: 13px;\n color: rgba(255,255,255,.85);\n font-weight: 500;\n letter-spacing: .02em;\n}\n\n/* ============================================================\n Live badge — text badge with blinking dot (not icon)\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-live-sync {\n width: auto;\n height: auto;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: .08em;\n text-transform: uppercase;\n gap: 5px;\n}\n\n/* Hide icon, show dot + label */\n[data-theme=\"v2\"] .eb-player .eb-live-sync__icon {\n display: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync__dot {\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #fff;\n flex-shrink: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync__label {\n display: block;\n}\n\n/* Synced state — red background with blinking dot */\n[data-theme=\"v2\"] .eb-player .eb-live-synced {\n background: rgba(220,38,38,.9);\n color: #fff;\n box-shadow: 0 2px 8px rgba(220,38,38,.4);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-synced .eb-live-sync__dot {\n animation: eb-v2-blink 1.2s ease infinite;\n}\n\n/* Delayed / not-at-live-edge */\n[data-theme=\"v2\"] .eb-player .eb-live-sync:not(.eb-live-synced) {\n background: rgba(60,60,80,.75);\n color: rgba(255,255,255,.7);\n box-shadow: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync:not(.eb-live-synced) .eb-live-sync__dot {\n background: rgba(255,255,255,.5);\n animation: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-live-sync:not(.eb-live-synced):hover {\n background: rgba(220,38,38,.7);\n color: #fff;\n}\n\n@keyframes eb-v2-blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: .15; }\n}\n\n/* ============================================================\n Settings panel: glassmorphism dropdown\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-settings-panel {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(18px) saturate(160%);\n -webkit-backdrop-filter: blur(18px) saturate(160%);\n border-radius: 12px;\n min-width: 300px;\n box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.1);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-menu {\n padding: 0;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-category,\n[data-theme=\"v2\"] .eb-player .eb-settings-item,\n[data-theme=\"v2\"] .eb-player .eb-settings-back {\n padding: 15px 20px;\n font-size: 13px;\n color: rgba(255,255,255,.9);\n border-bottom: 1px solid rgba(255,255,255,.06);\n transition: background .12s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-category:last-child,\n[data-theme=\"v2\"] .eb-player .eb-settings-item:last-child {\n border-bottom: none;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-settings-category:hover,\n[data-theme=\"v2\"] .eb-player .eb-settings-item:hover,\n[data-theme=\"v2\"] .eb-player .eb-settings-back:hover {\n background: rgba(255,255,255,.05);\n}\n\n/* Selected item text */\n[data-theme=\"v2\"] .eb-player .eb-settings-item--selected {\n color: #fff;\n font-weight: 500;\n}\n\n/* Active selection dot (filled orange) */\n[data-theme=\"v2\"] .eb-player .eb-settings-item--selected::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--eb-accent, #ff841f);\n box-shadow: 0 0 0 3px rgba(255,132,31,.25);\n flex-shrink: 0;\n}\n\n/* Non-selected items: hollow dot */\n[data-theme=\"v2\"] .eb-player .eb-settings-item:not(.eb-settings-item--selected)::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,.2);\n flex-shrink: 0;\n}\n\n/* Back button */\n[data-theme=\"v2\"] .eb-player .eb-settings-back {\n gap: 14px;\n font-weight: 600;\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-loading .eb-icon {\n width: 52px;\n height: 52px;\n color: rgba(255,255,255,.7);\n filter: drop-shadow(0 1px 6px rgba(0,0,0,.5));\n animation: eb-spin .75s linear infinite;\n}\n\n/* ============================================================\n Error overlay\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-error {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-error-message {\n font-weight: 400;\n letter-spacing: .01em;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-error-retry {\n border-radius: 8px;\n background: rgba(255,255,255,.1);\n border-color: rgba(255,255,255,.15);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-error-retry:hover {\n background: rgba(255,255,255,.18);\n}\n\n/* ============================================================\n Toast (keyboard hints, status messages)\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-toast {\n background: rgba(0,0,0,.72);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border-radius: 10px;\n font-size: 13px;\n padding: 8px 16px;\n}\n\n/* ============================================================\n Info & socials overlays\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-info-overlay,\n[data-theme=\"v2\"] .eb-player .eb-socials-overlay {\n background: rgba(10,10,20,.85);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-info-close,\n[data-theme=\"v2\"] .eb-player .eb-socials-close {\n border-radius: 8px;\n background: rgba(255,255,255,.07);\n border-color: rgba(255,255,255,.08);\n transition: background .2s, color .2s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-info-close:hover,\n[data-theme=\"v2\"] .eb-player .eb-socials-close:hover {\n background: rgba(255,255,255,.13);\n color: #fff;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-socials-link {\n background: rgba(255,255,255,.07);\n border: 1px solid rgba(255,255,255,.08);\n border-radius: 8px;\n transition: background .2s, color .2s, border-color .2s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-socials-link:hover {\n background: rgba(255,132,31,.15);\n border-color: rgba(255,132,31,.35);\n color: #ffb980;\n}\n\n/* ============================================================\n Poster\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-poster {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n\n/* ============================================================\n Radio overlay\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-radio-overlay {\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\n}\n\n[data-theme=\"v2\"] .eb-player .eb-radio-bar {\n background: rgba(255,132,31,.8);\n}\n\n/* ============================================================\n Chapter skip button\n ============================================================ */\n[data-theme=\"v2\"] .eb-player .eb-chapter-skip {\n background: rgba(10,10,20,.55);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid rgba(255,255,255,.15);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n transition: background .15s;\n}\n\n[data-theme=\"v2\"] .eb-player .eb-chapter-skip:hover {\n background: rgba(255,255,255,.12);\n}\n";
|
|
47
52
|
styleInject(css_248z$1);
|
|
48
53
|
|
|
49
|
-
var css_248z = "/* eb-player skin CSS — BEM-prefixed structural styles */\n/* All class names use the eb- prefix to avoid collisions with consumer CSS */\n\n/* ============================================================\n Root container\n ============================================================ */\n.eb-player {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n font-family: sans-serif;\n background: #000;\n color: #fff;\n box-sizing: border-box;\n user-select: none;\n}\n\n/* Video element fills the container */\n.eb-player video.eb-video {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: block;\n object-fit: contain;\n z-index: 1;\n}\n\n/* ============================================================\n Overlay zone (poster, radio, loading, error, socials, info)\n ============================================================ */\n.eb-overlay-zone {\n position: absolute;\n inset: 0;\n pointer-events: none;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n}\n\n/* Poster image */\n.eb-poster {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: contain;\n pointer-events: none;\n background: #000;\n padding: 15%;\n box-sizing: border-box;\n}\n\n/* Ads container (for IMA SDK) */\n.eb-ads-container {\n position: absolute;\n inset: 0;\n z-index: 20;\n pointer-events: none;\n}\n\n/* ============================================================\n Top bar\n ============================================================ */\n.eb-top-bar {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.6), transparent);\n z-index: 30;\n pointer-events: auto;\n}\n\n.eb-top-bar__logo {\n height: 28px;\n width: auto;\n display: block;\n}\n\n.eb-top-bar__logo-link {\n display: inline-flex;\n text-decoration: none;\n}\n\n.eb-top-bar__actions {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n}\n\n/* ============================================================\n Bottom bar\n ============================================================ */\n.eb-bottom-bar {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n flex-direction: column;\n z-index: 30;\n pointer-events: auto;\n}\n\n.eb-bottom-bar__gradient {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 100px;\n background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);\n pointer-events: none;\n z-index: -1;\n}\n\n.eb-bottom-bar__controls-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 4px;\n padding: 4px 8px 8px;\n}\n\n.eb-bottom-bar__seekbar-zone {\n flex: 1;\n min-width: 0;\n}\n\n/* ============================================================\n Middle bar\n ============================================================ */\n.eb-middle-bar {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n z-index: 25;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.eb-middle-bar__play-btn {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.eb-middle-bar__seek-btn {\n flex-direction: column;\n gap: 2px;\n background: none;\n padding: 4px;\n}\n\n.eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,0.1);\n border-radius: 8px;\n}\n\n.eb-seek-circle {\n width: 32px;\n height: 32px;\n display: block;\n pointer-events: none;\n fill: currentColor;\n}\n\n.eb-seek-label {\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n opacity: 0.85;\n}\n\n/* ============================================================\n Extension zones\n ============================================================ */\n.eb-extension-top-extra,\n.eb-extension-bottom-extra,\n.eb-extension-overlay,\n.eb-extension-controls-extra {\n position: absolute;\n pointer-events: none;\n z-index: 35;\n}\n\n.eb-extension-top-extra > *,\n.eb-extension-bottom-extra > *,\n.eb-extension-overlay > *,\n.eb-extension-controls-extra > * {\n pointer-events: auto;\n}\n\n.eb-extension-top-extra {\n top: 0;\n left: 0;\n right: 0;\n}\n\n.eb-extension-bottom-extra {\n bottom: 0;\n left: 0;\n right: 0;\n}\n\n.eb-extension-overlay {\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.eb-extension-controls-extra {\n bottom: 0;\n right: 0;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px 8px;\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n.eb-time-display {\n font-size: 13px;\n line-height: 1;\n white-space: nowrap;\n padding: 0 4px;\n color: #fff;\n font-variant-numeric: tabular-nums;\n}\n\n/* ============================================================\n Volume control\n ============================================================ */\n.eb-volume-control {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-right: 8px;\n}\n\n.eb-volume-track {\n position: relative;\n width: 60px;\n height: 4px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n cursor: pointer;\n}\n\n.eb-volume-fill {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--eb-color-volume, var(--eb-color-primary, #fff));\n border-radius: 2px;\n pointer-events: none;\n}\n\n.eb-volume-thumb {\n position: absolute;\n top: 50%;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--eb-color-volume, var(--eb-color-primary, #fff));\n transform: translate(-50%, -50%);\n pointer-events: none;\n}\n\n/* ============================================================\n Settings panel\n ============================================================ */\n.eb-settings-wrapper {\n position: relative;\n}\n\n.eb-settings-panel {\n position: absolute;\n background: rgba(0, 0, 0, 0.85);\n border-radius: 6px;\n min-width: 180px;\n overflow: hidden;\n font-size: 13px;\n z-index: 40;\n}\n\n/* Vertical direction: up (default) or down */\n.eb-settings-panel--up {\n bottom: calc(100% + 8px);\n}\n\n.eb-settings-panel--down {\n top: calc(100% + 8px);\n}\n\n/* Horizontal alignment: right (default) or left */\n.eb-settings-panel--right {\n right: 0;\n}\n\n.eb-settings-panel--left {\n left: 0;\n}\n\n.eb-settings-menu {\n list-style: none;\n margin: 0;\n padding: 4px 0;\n}\n\n.eb-settings-category,\n.eb-settings-item,\n.eb-settings-back {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: none;\n color: #fff;\n cursor: pointer;\n font-size: 13px;\n text-align: left;\n}\n\n.eb-settings-category:hover,\n.eb-settings-item:hover,\n.eb-settings-back:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n\n.eb-settings-item--selected {\n color: var(--eb-accent, #e53935);\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n.eb-seekbar {\n position: relative;\n width: 100%;\n padding: 8px 0;\n cursor: pointer;\n}\n\n.eb-seekbar-disabled {\n pointer-events: none;\n opacity: 0.4;\n}\n\n.eb-seekbar-track {\n position: relative;\n height: 4px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n}\n\n.eb-seekbar-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.4);\n border-radius: 2px;\n pointer-events: none;\n}\n\n.eb-seekbar-progress {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--eb-color-progress, var(--eb-color-primary, #e53935));\n border-radius: 2px;\n pointer-events: none;\n}\n\n.eb-seekbar-thumb {\n position: absolute;\n right: -6px;\n top: 50%;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--eb-color-progress, var(--eb-color-primary, #e53935));\n transform: translateY(-50%) scale(0);\n transition: transform 0.15s;\n pointer-events: none;\n}\n\n.eb-seekbar:hover .eb-seekbar-thumb {\n transform: translateY(-50%) scale(1);\n}\n\n.eb-seekbar:hover .eb-seekbar-track {\n height: 6px;\n}\n\n.eb-seekbar-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n font-size: 12px;\n padding: 4px 8px;\n border-radius: 3px;\n white-space: nowrap;\n pointer-events: none;\n text-align: center;\n}\n\n.eb-seekbar-preview {\n width: 120px;\n height: auto;\n display: block;\n margin-bottom: 4px;\n}\n\n.eb-chapter-marker {\n position: absolute;\n top: 0;\n width: 3px;\n height: 100%;\n background: rgba(255, 255, 255, 0.6);\n transform: translateX(-50%);\n pointer-events: none;\n}\n\n.eb-chapter-marker.eb-chapter-active {\n background: #fff;\n}\n\n.eb-chapter-skip {\n position: absolute;\n right: 0;\n bottom: calc(100% + 4px);\n background: rgba(0, 0, 0, 0.7);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.4);\n border-radius: 4px;\n padding: 6px 16px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.eb-chapter-skip:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n\n.eb-epg-segment {\n position: absolute;\n top: 0;\n height: 100%;\n border-right: 1px solid rgba(255, 255, 255, 0.3);\n pointer-events: none;\n}\n\n.eb-epg-segment.eb-epg-current {\n background: rgba(255, 255, 255, 0.1);\n}\n\n/* ============================================================\n Icons\n ============================================================ */\n.eb-icon {\n width: 20px;\n height: 20px;\n fill: none;\n stroke: currentColor;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n display: block;\n pointer-events: none;\n flex-shrink: 0;\n}\n\n/* ============================================================\n Buttons (base style)\n ============================================================ */\n.eb-button,\n.eb-play-pause,\n.eb-fullscreen,\n.eb-pip,\n.eb-cast,\n.eb-volume-mute,\n.eb-live-sync {\n cursor: pointer;\n background: none;\n border: none;\n padding: 6px;\n color: var(--eb-color-icon, inherit);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background 0.15s;\n -webkit-tap-highlight-color: transparent;\n}\n\n.eb-button:hover,\n.eb-play-pause:hover,\n.eb-fullscreen:hover,\n.eb-pip:hover,\n.eb-cast:hover,\n.eb-volume-mute:hover,\n.eb-live-sync:hover {\n background: rgba(255,255,255,0.15);\n}\n\n.eb-button:active,\n.eb-play-pause:active,\n.eb-fullscreen:active,\n.eb-pip:active,\n.eb-cast:active,\n.eb-volume-mute:active,\n.eb-live-sync:active {\n background: rgba(255,255,255,0.25);\n}\n\n/* ============================================================\n Radio overlay\n ============================================================ */\n.eb-radio-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #000;\n z-index: 15;\n}\n\n.eb-radio-bars {\n display: flex;\n align-items: flex-end;\n gap: 4px;\n height: 40px;\n}\n\n.eb-radio-bar {\n display: block;\n width: 6px;\n background: #fff;\n border-radius: 3px;\n animation: eb-radio-bar-bounce 0.8s ease-in-out infinite;\n}\n\n.eb-radio-bar:nth-child(1) { animation-delay: 0s; height: 20px; }\n.eb-radio-bar:nth-child(2) { animation-delay: 0.1s; height: 32px; }\n.eb-radio-bar:nth-child(3) { animation-delay: 0.2s; height: 40px; }\n.eb-radio-bar:nth-child(4) { animation-delay: 0.3s; height: 28px; }\n.eb-radio-bar:nth-child(5) { animation-delay: 0.4s; height: 16px; }\n\n@keyframes eb-radio-bar-bounce {\n 0%, 100% { transform: scaleY(0.4); opacity: 0.7; }\n 50% { transform: scaleY(1); opacity: 1; }\n}\n\n/* Volume mute button — base styles shared via .eb-button group above */\n\n/* ============================================================\n Live sync button\n ============================================================ */\n.eb-live-sync[hidden] {\n display: none;\n}\n\n.eb-live-synced {\n color: var(--eb-accent, #e53935);\n}\n\n/* Default theme: show icon only, hide text badge elements */\n.eb-live-sync__dot,\n.eb-live-sync__label {\n display: none;\n}\n\n/* ============================================================\n Overlay panels (error, info, socials — mounted in .eb-player)\n ============================================================ */\n.eb-error-slot,\n.eb-info-slot,\n.eb-socials-slot {\n position: absolute;\n inset: 0;\n z-index: 50;\n pointer-events: none;\n}\n\n.eb-toast-slot {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 50;\n pointer-events: none;\n}\n\n.eb-toast {\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n padding: 8px 20px;\n border-radius: 4px;\n font-size: 13px;\n white-space: nowrap;\n pointer-events: auto;\n}\n\n.eb-error,\n.eb-info-overlay,\n.eb-socials-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.75);\n color: #fff;\n z-index: 50;\n pointer-events: auto;\n padding: 24px;\n text-align: center;\n}\n\n.eb-error[hidden],\n.eb-info-overlay[hidden],\n.eb-socials-overlay[hidden] {\n display: none;\n}\n\n.eb-error-message {\n font-size: 16px;\n margin: 0 0 16px;\n}\n\n.eb-error-retry {\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n padding: 8px 24px;\n font-size: 14px;\n cursor: pointer;\n}\n\n.eb-error-retry:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n.eb-info-content {\n font-size: 14px;\n line-height: 1.5;\n max-width: 400px;\n margin-bottom: 16px;\n}\n\n.eb-info-close,\n.eb-socials-close {\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n padding: 8px 24px;\n font-size: 14px;\n cursor: pointer;\n}\n\n.eb-info-close:hover,\n.eb-socials-close:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n.eb-socials-links {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n justify-content: center;\n margin-bottom: 16px;\n}\n\n.eb-socials-link {\n color: #fff;\n text-decoration: none;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n padding: 8px 16px;\n font-size: 14px;\n text-transform: capitalize;\n}\n\n.eb-socials-link:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n.eb-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #fff;\n pointer-events: none;\n}\n\n.eb-loading[hidden] {\n display: none;\n}\n\n.eb-loading .eb-icon {\n width: 40px;\n height: 40px;\n animation: eb-spin 1s linear infinite;\n}\n\n.eb-loading-text {\n font-size: 14px;\n}\n\n@keyframes eb-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* ============================================================\n Controls visibility\n ============================================================ */\n.eb-controls-visible .eb-top-bar,\n.eb-controls-visible .eb-bottom-bar,\n.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity 0.3s;\n}\n\n.eb-controls-hidden .eb-top-bar,\n.eb-controls-hidden .eb-bottom-bar,\n.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity 0.3s;\n pointer-events: none;\n}\n\n/* ============================================================\n iOS native controls fallback\n ============================================================ */\n.eb-ios-native .eb-top-bar,\n.eb-ios-native .eb-bottom-bar,\n.eb-ios-native .eb-middle-bar,\n.eb-ios-native .eb-overlay-zone,\n.eb-ios-native .eb-error-slot,\n.eb-ios-native .eb-info-slot,\n.eb-ios-native .eb-socials-slot,\n.eb-ios-native .eb-toast-slot {\n display: none;\n}\n\n/* ============================================================\n RTL support\n ============================================================ */\n[dir=\"rtl\"] .eb-bottom-bar__controls-row {\n flex-direction: row-reverse;\n}\n\n[dir=\"rtl\"] .eb-top-bar {\n flex-direction: row-reverse;\n}\n\n/* ============================================================\n Responsive: ensure container fills parent\n ============================================================ */\n.eb-player,\n.eb-player video {\n max-width: 100%;\n max-height: 100%;\n}\n";
|
|
54
|
+
var css_248z = "/* eb-player skin CSS — BEM-prefixed structural styles */\n/* All class names use the eb- prefix to avoid collisions with consumer CSS */\n\n/* ============================================================\n Root container\n ============================================================ */\n.eb-player {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n font-family: sans-serif;\n background: #000;\n color: #fff;\n box-sizing: border-box;\n user-select: none;\n}\n\n/* Video element fills the container.\n filter: brightness(1) is visually identical to no filter but forces Chrome to\n composite the video through the GPU filter pipeline instead of using a hardware\n overlay plane. Without this, DRM-protected video (Widevine) renders on a separate\n hardware overlay that sits above ALL HTML layers — making seekbar snapshot preview\n and other overlay elements invisible behind the main video. */\n.eb-player video.eb-video {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: block;\n object-fit: contain;\n z-index: 1;\n filter: brightness(1);\n}\n\n/* ============================================================\n Overlay zone (poster, radio, loading, error, socials, info)\n ============================================================ */\n.eb-overlay-zone {\n position: absolute;\n inset: 0;\n pointer-events: none;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n}\n\n/* Poster image */\n.eb-poster {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: contain;\n pointer-events: none;\n background: #000;\n padding: 15%;\n box-sizing: border-box;\n}\n\n/* Ads container (for IMA SDK) */\n.eb-ads-container {\n position: absolute;\n inset: 0;\n z-index: 20;\n pointer-events: none;\n}\n\n/* ============================================================\n Top bar\n ============================================================ */\n.eb-top-bar {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.6), transparent);\n z-index: 30;\n pointer-events: auto;\n}\n\n.eb-top-bar__logo {\n height: 28px;\n width: auto;\n display: block;\n}\n\n.eb-top-bar__logo-link {\n display: inline-flex;\n text-decoration: none;\n}\n\n.eb-top-bar__actions {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n}\n\n/* ============================================================\n Bottom bar\n ============================================================ */\n.eb-bottom-bar {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n flex-direction: column;\n z-index: 30;\n pointer-events: auto;\n}\n\n.eb-bottom-bar__gradient {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 100px;\n background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);\n pointer-events: none;\n z-index: -1;\n}\n\n.eb-bottom-bar__controls-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 4px;\n padding: 4px 8px 8px;\n}\n\n.eb-bottom-bar__seekbar-zone {\n flex: 1;\n min-width: 0;\n}\n\n/* ============================================================\n Middle bar\n ============================================================ */\n.eb-middle-bar {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n z-index: 25;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.eb-middle-bar__play-btn {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.eb-middle-bar__seek-btn {\n flex-direction: column;\n gap: 2px;\n background: none;\n padding: 4px;\n}\n\n.eb-middle-bar__seek-btn:hover {\n background: rgba(255,255,255,0.1);\n border-radius: 8px;\n}\n\n.eb-seek-circle {\n width: 32px;\n height: 32px;\n display: block;\n pointer-events: none;\n fill: currentColor;\n}\n\n.eb-seek-label {\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n opacity: 0.85;\n}\n\n/* ============================================================\n Extension zones\n ============================================================ */\n.eb-extension-top-extra,\n.eb-extension-bottom-extra,\n.eb-extension-overlay,\n.eb-extension-controls-extra {\n position: absolute;\n pointer-events: none;\n z-index: 35;\n}\n\n.eb-extension-top-extra > *,\n.eb-extension-bottom-extra > *,\n.eb-extension-overlay > *,\n.eb-extension-controls-extra > * {\n pointer-events: auto;\n}\n\n.eb-extension-top-extra {\n top: 0;\n left: 0;\n right: 0;\n}\n\n.eb-extension-bottom-extra {\n bottom: 0;\n left: 0;\n right: 0;\n}\n\n.eb-extension-overlay {\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.eb-extension-controls-extra {\n bottom: 0;\n right: 0;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px 8px;\n}\n\n/* ============================================================\n Time display\n ============================================================ */\n.eb-time-display {\n font-size: 13px;\n line-height: 1;\n white-space: nowrap;\n padding: 0 4px;\n color: #fff;\n font-variant-numeric: tabular-nums;\n}\n\n/* ============================================================\n Volume control\n ============================================================ */\n.eb-volume-control {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-right: 8px;\n}\n\n.eb-volume-track {\n position: relative;\n width: 60px;\n height: 4px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n cursor: pointer;\n}\n\n.eb-volume-fill {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--eb-color-volume, var(--eb-color-primary, #fff));\n border-radius: 2px;\n pointer-events: none;\n}\n\n.eb-volume-thumb {\n position: absolute;\n top: 50%;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--eb-color-volume, var(--eb-color-primary, #fff));\n transform: translate(-50%, -50%);\n pointer-events: none;\n}\n\n/* ============================================================\n Settings panel\n ============================================================ */\n.eb-settings-wrapper {\n position: relative;\n}\n\n.eb-settings-panel {\n position: absolute;\n background: rgba(0, 0, 0, 0.85);\n border-radius: 6px;\n min-width: 160px;\n max-width: 220px;\n overflow: hidden;\n font-size: 12px;\n z-index: 40;\n}\n\n/* Vertical direction: up (default) or down */\n.eb-settings-panel--up {\n bottom: calc(100% + 8px);\n}\n\n.eb-settings-panel--down {\n top: calc(100% + 8px);\n}\n\n/* Horizontal alignment: right (default) or left */\n.eb-settings-panel--right {\n right: 0;\n}\n\n.eb-settings-panel--left {\n left: 0;\n}\n\n.eb-settings-menu {\n list-style: none;\n margin: 0;\n padding: 4px 0;\n}\n\n.eb-settings-submenu {\n max-height: 200px;\n overflow-y: auto;\n}\n\n.eb-settings-submenu::-webkit-scrollbar {\n width: 4px;\n}\n\n.eb-settings-submenu::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n}\n\n.eb-settings-header {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 12px;\n}\n\n.eb-settings-category,\n.eb-settings-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 5px 12px;\n border: none;\n background: none;\n color: #fff;\n cursor: pointer;\n font-size: 12px;\n text-align: left;\n}\n\n.eb-settings-back {\n display: flex;\n align-items: center;\n border: none;\n background: none;\n color: #fff;\n cursor: pointer;\n padding: 0;\n}\n\n.eb-settings-category:hover,\n.eb-settings-item:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n\n.eb-settings-item--selected {\n color: var(--eb-accent, var(--eb-color-primary, #e53935));\n}\n\n/* ============================================================\n Seekbar\n ============================================================ */\n.eb-seekbar {\n position: relative;\n width: 100%;\n padding: 8px 0;\n cursor: pointer;\n}\n\n.eb-seekbar-disabled {\n pointer-events: none;\n opacity: 0.4;\n}\n\n.eb-seekbar-track {\n position: relative;\n height: 4px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n}\n\n.eb-seekbar-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.4);\n border-radius: 2px;\n pointer-events: none;\n}\n\n.eb-seekbar-progress {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--eb-color-progress, var(--eb-color-primary, #e53935));\n border-radius: 2px;\n pointer-events: none;\n}\n\n.eb-seekbar-thumb {\n position: absolute;\n right: -6px;\n top: 50%;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--eb-color-progress, var(--eb-color-primary, #e53935));\n transform: translateY(-50%) scale(0);\n transition: transform 0.15s;\n pointer-events: none;\n}\n\n.eb-seekbar:hover .eb-seekbar-thumb {\n transform: translateY(-50%) scale(1);\n}\n\n.eb-seekbar:hover .eb-seekbar-track {\n height: 6px;\n}\n\n.eb-seekbar-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n font-size: 12px;\n padding: 4px 8px;\n border-radius: 3px;\n white-space: nowrap;\n pointer-events: none;\n text-align: center;\n z-index: 50;\n overflow: hidden;\n}\n\n.eb-seekbar-preview {\n position: static !important;\n width: 120px;\n height: 68px;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n display: block !important;\n object-fit: contain;\n background: #000;\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n inset: auto !important;\n transform: none !important;\n z-index: auto !important;\n}\n\n.eb-chapter-marker {\n position: absolute;\n top: 0;\n width: 3px;\n height: 100%;\n background: rgba(255, 255, 255, 0.6);\n transform: translateX(-50%);\n pointer-events: none;\n}\n\n.eb-chapter-marker.eb-chapter-active {\n background: #fff;\n}\n\n.eb-chapter-skip {\n position: absolute;\n right: 0;\n bottom: calc(100% + 4px);\n background: rgba(0, 0, 0, 0.7);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.4);\n border-radius: 4px;\n padding: 6px 16px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.eb-chapter-skip:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n\n.eb-epg-segment {\n position: absolute;\n top: 0;\n height: 100%;\n border-right: 1px solid rgba(255, 255, 255, 0.3);\n pointer-events: none;\n}\n\n.eb-epg-segment.eb-epg-current {\n background: rgba(255, 255, 255, 0.1);\n}\n\n/* ============================================================\n Icons\n ============================================================ */\n.eb-icon {\n width: 20px;\n height: 20px;\n fill: none;\n stroke: currentColor;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n display: block;\n pointer-events: none;\n flex-shrink: 0;\n}\n\n/* ============================================================\n Buttons (base style)\n ============================================================ */\n.eb-button,\n.eb-play-pause,\n.eb-fullscreen,\n.eb-pip,\n.eb-cast,\n.eb-volume-mute,\n.eb-live-sync {\n cursor: pointer;\n background: none;\n border: none;\n padding: 6px;\n color: var(--eb-color-icon, inherit);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background 0.15s;\n -webkit-tap-highlight-color: transparent;\n}\n\n.eb-button:hover,\n.eb-play-pause:hover,\n.eb-fullscreen:hover,\n.eb-pip:hover,\n.eb-cast:hover,\n.eb-volume-mute:hover,\n.eb-live-sync:hover {\n background: rgba(255,255,255,0.15);\n}\n\n.eb-button:active,\n.eb-play-pause:active,\n.eb-fullscreen:active,\n.eb-pip:active,\n.eb-cast:active,\n.eb-volume-mute:active,\n.eb-live-sync:active {\n background: rgba(255,255,255,0.25);\n}\n\n/* ============================================================\n Radio overlay\n ============================================================ */\n.eb-radio-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #000;\n z-index: 15;\n}\n\n.eb-radio-bars {\n display: flex;\n align-items: flex-end;\n gap: 4px;\n height: 40px;\n}\n\n.eb-radio-bar {\n display: block;\n width: 6px;\n background: #fff;\n border-radius: 3px;\n animation: eb-radio-bar-bounce 0.8s ease-in-out infinite;\n}\n\n.eb-radio-bar:nth-child(1) { animation-delay: 0s; height: 20px; }\n.eb-radio-bar:nth-child(2) { animation-delay: 0.1s; height: 32px; }\n.eb-radio-bar:nth-child(3) { animation-delay: 0.2s; height: 40px; }\n.eb-radio-bar:nth-child(4) { animation-delay: 0.3s; height: 28px; }\n.eb-radio-bar:nth-child(5) { animation-delay: 0.4s; height: 16px; }\n\n@keyframes eb-radio-bar-bounce {\n 0%, 100% { transform: scaleY(0.4); opacity: 0.7; }\n 50% { transform: scaleY(1); opacity: 1; }\n}\n\n/* Volume mute button — base styles shared via .eb-button group above */\n\n/* ============================================================\n Live sync button\n ============================================================ */\n.eb-live-sync[hidden] {\n display: none;\n}\n\n.eb-live-synced {\n color: var(--eb-accent, var(--eb-color-primary, #e53935));\n}\n\n/* Default theme: show icon only, hide text badge elements */\n.eb-live-sync__dot,\n.eb-live-sync__label {\n display: none;\n}\n\n/* ============================================================\n Overlay panels (error, info, socials — mounted in .eb-player)\n ============================================================ */\n.eb-error-slot,\n.eb-info-slot,\n.eb-socials-slot {\n position: absolute;\n inset: 0;\n z-index: 50;\n pointer-events: none;\n}\n\n.eb-toast-slot {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 50;\n pointer-events: none;\n}\n\n.eb-toast {\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n padding: 8px 20px;\n border-radius: 4px;\n font-size: 13px;\n white-space: nowrap;\n pointer-events: auto;\n}\n\n.eb-error,\n.eb-info-overlay,\n.eb-socials-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.75);\n color: #fff;\n z-index: 50;\n pointer-events: auto;\n padding: 24px;\n text-align: center;\n}\n\n.eb-error[hidden],\n.eb-info-overlay[hidden],\n.eb-socials-overlay[hidden] {\n display: none;\n}\n\n.eb-error-message {\n font-size: 16px;\n margin: 0 0 16px;\n}\n\n.eb-error-retry {\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n padding: 8px 24px;\n font-size: 14px;\n cursor: pointer;\n}\n\n.eb-error-retry:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n.eb-info-content {\n font-size: 14px;\n line-height: 1.5;\n max-width: 400px;\n margin-bottom: 16px;\n}\n\n.eb-info-close,\n.eb-socials-close {\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n padding: 8px 24px;\n font-size: 14px;\n cursor: pointer;\n}\n\n.eb-info-close:hover,\n.eb-socials-close:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n.eb-socials-links {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n justify-content: center;\n margin-bottom: 16px;\n}\n\n.eb-socials-link {\n color: #fff;\n text-decoration: none;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n padding: 8px 16px;\n font-size: 14px;\n text-transform: capitalize;\n}\n\n.eb-socials-link:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* ============================================================\n Loading spinner\n ============================================================ */\n.eb-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #fff;\n pointer-events: none;\n}\n\n.eb-loading[hidden] {\n display: none;\n}\n\n.eb-loading .eb-icon {\n width: 40px;\n height: 40px;\n animation: eb-spin 1s linear infinite;\n}\n\n.eb-loading-text {\n font-size: 14px;\n}\n\n@keyframes eb-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* ============================================================\n Controls visibility\n ============================================================ */\n.eb-controls-visible .eb-top-bar,\n.eb-controls-visible .eb-bottom-bar,\n.eb-controls-visible .eb-middle-bar {\n opacity: 1;\n transition: opacity 0.3s;\n}\n\n.eb-controls-hidden .eb-top-bar,\n.eb-controls-hidden .eb-bottom-bar,\n.eb-controls-hidden .eb-middle-bar {\n opacity: 0;\n transition: opacity 0.3s;\n pointer-events: none;\n}\n\n/* ============================================================\n iOS native controls fallback\n ============================================================ */\n.eb-ios-native .eb-top-bar,\n.eb-ios-native .eb-bottom-bar,\n.eb-ios-native .eb-middle-bar,\n.eb-ios-native .eb-overlay-zone,\n.eb-ios-native .eb-error-slot,\n.eb-ios-native .eb-info-slot,\n.eb-ios-native .eb-socials-slot,\n.eb-ios-native .eb-toast-slot {\n display: none;\n}\n\n/* ============================================================\n RTL support\n ============================================================ */\n[dir=\"rtl\"] .eb-bottom-bar__controls-row {\n flex-direction: row-reverse;\n}\n\n[dir=\"rtl\"] .eb-top-bar {\n flex-direction: row-reverse;\n}\n\n/* ============================================================\n Responsive: ensure container fills parent\n ============================================================ */\n.eb-player,\n.eb-player video.eb-video {\n max-width: 100%;\n max-height: 100%;\n}\n";
|
|
50
55
|
styleInject(css_248z);
|
|
51
56
|
|
|
52
57
|
/**
|
|
@@ -319,28 +324,61 @@ var EBPlayerBundle = (function (exports) {
|
|
|
319
324
|
right: ['forward']
|
|
320
325
|
}
|
|
321
326
|
};
|
|
327
|
+
/**
|
|
328
|
+
* Available themes — single source of truth for all theme names and labels.
|
|
329
|
+
* The test player reads this to populate the skin selector dynamically.
|
|
330
|
+
* Add new entries here when creating a new theme-*.css file.
|
|
331
|
+
*/
|
|
332
|
+
const AVAILABLE_THEMES = [
|
|
333
|
+
{ value: 'default', label: 'Default' },
|
|
334
|
+
{ value: 'forja', label: 'Forja', primaryColor: '#FC013B' },
|
|
335
|
+
{ value: 'radio', label: 'Radio', primaryColor: '#F4A261' },
|
|
336
|
+
{ value: 'snrt', label: 'SNRT', primaryColor: '#006633' },
|
|
337
|
+
{ value: 'modern', label: 'Modern', primaryColor: '#7c3aed' },
|
|
338
|
+
{ value: 'v2', label: 'V2', primaryColor: '#ff841f' },
|
|
339
|
+
{ value: 'lequipe', label: "L'Equipe", primaryColor: '#d61e00' },
|
|
340
|
+
];
|
|
322
341
|
/**
|
|
323
342
|
* Theme-specific default layouts.
|
|
324
343
|
* Used when config.layout is not explicitly provided but a theme is set.
|
|
325
344
|
*/
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
right: ['forward']
|
|
341
|
-
}
|
|
345
|
+
const V2_LAYOUT = {
|
|
346
|
+
topBar: {
|
|
347
|
+
left: [],
|
|
348
|
+
right: ['settings', 'pip', 'cast']
|
|
349
|
+
},
|
|
350
|
+
bottomBar: {
|
|
351
|
+
left: ['play-pause', 'live-sync', 'time'],
|
|
352
|
+
center: ['seekbar'],
|
|
353
|
+
right: ['volume', 'fullscreen']
|
|
354
|
+
},
|
|
355
|
+
middleBar: {
|
|
356
|
+
left: ['rewind'],
|
|
357
|
+
center: [],
|
|
358
|
+
right: ['forward']
|
|
342
359
|
}
|
|
343
360
|
};
|
|
361
|
+
const LEQUIPE_LAYOUT = {
|
|
362
|
+
topBar: {
|
|
363
|
+
left: [],
|
|
364
|
+
right: ['pip', 'settings']
|
|
365
|
+
},
|
|
366
|
+
bottomBar: {
|
|
367
|
+
left: ['play-pause', 'live-sync', 'time'],
|
|
368
|
+
center: ['seekbar'],
|
|
369
|
+
right: ['volume', 'fullscreen']
|
|
370
|
+
},
|
|
371
|
+
middleBar: {
|
|
372
|
+
left: ['rewind'],
|
|
373
|
+
center: [],
|
|
374
|
+
right: ['forward']
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
const THEME_LAYOUTS = {
|
|
378
|
+
v2: V2_LAYOUT,
|
|
379
|
+
lequipe: LEQUIPE_LAYOUT,
|
|
380
|
+
modern: V2_LAYOUT,
|
|
381
|
+
};
|
|
344
382
|
/**
|
|
345
383
|
* Returns the effective layout for a given config.
|
|
346
384
|
* Priority: explicit config.layout > theme default > DEFAULT_LAYOUT
|
|
@@ -560,6 +598,30 @@ var EBPlayerBundle = (function (exports) {
|
|
|
560
598
|
fr: 'La diffusion a échoué. Reprise de la lecture locale.',
|
|
561
599
|
ar: 'Casting failed. Resuming local playback.',
|
|
562
600
|
es: 'Error en la transmisión. Reanudando la reproducción local.'
|
|
601
|
+
},
|
|
602
|
+
'settings.audio': {
|
|
603
|
+
en: 'Audio track', fr: 'Piste audio', ar: 'مسار صوتي', es: 'Pista de audio'
|
|
604
|
+
},
|
|
605
|
+
'settings.subtitles': {
|
|
606
|
+
en: 'Subtitles', fr: 'Sous-titres', ar: 'ترجمات', es: 'Subtítulos'
|
|
607
|
+
},
|
|
608
|
+
'settings.speed': {
|
|
609
|
+
en: 'Playback speed', fr: 'Vitesse de lecture', ar: 'سرعة التشغيل', es: 'Velocidad'
|
|
610
|
+
},
|
|
611
|
+
'settings.quality': {
|
|
612
|
+
en: 'Quality', fr: 'Qualité', ar: 'الجودة', es: 'Calidad'
|
|
613
|
+
},
|
|
614
|
+
'settings.default': {
|
|
615
|
+
en: 'Default', fr: 'Défaut', ar: 'افتراضي', es: 'Predeterminado'
|
|
616
|
+
},
|
|
617
|
+
'settings.off': {
|
|
618
|
+
en: 'Off', fr: 'Désactivés', ar: 'إيقاف', es: 'Desactivado'
|
|
619
|
+
},
|
|
620
|
+
'settings.normal': {
|
|
621
|
+
en: 'Normal', fr: 'Normale', ar: 'عادي', es: 'Normal'
|
|
622
|
+
},
|
|
623
|
+
'settings.auto': {
|
|
624
|
+
en: 'Auto', fr: 'Auto', ar: 'تلقائي', es: 'Auto'
|
|
563
625
|
}
|
|
564
626
|
};
|
|
565
627
|
/**
|
|
@@ -1298,6 +1360,8 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1298
1360
|
this.tooltipX = 0;
|
|
1299
1361
|
this.previewVideoEl = null;
|
|
1300
1362
|
this.snapshotTake = null;
|
|
1363
|
+
this.trackEl = null;
|
|
1364
|
+
this.boundDocPointerMove = null;
|
|
1301
1365
|
}
|
|
1302
1366
|
onConnect() {
|
|
1303
1367
|
// Subscribe to snapshot handler readiness (emitted by eb-player.ts)
|
|
@@ -1318,6 +1382,10 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1318
1382
|
this.state.on('epgPrograms', () => this.scheduleRender(), { signal: this.signal });
|
|
1319
1383
|
this.render();
|
|
1320
1384
|
}
|
|
1385
|
+
disconnect() {
|
|
1386
|
+
this.stopDocumentTracking();
|
|
1387
|
+
super.disconnect();
|
|
1388
|
+
}
|
|
1321
1389
|
// ---- rAF batching ----
|
|
1322
1390
|
scheduleRender() {
|
|
1323
1391
|
if (this.rafPending)
|
|
@@ -1340,11 +1408,47 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1340
1408
|
const clamped = Math.min(1, Math.max(0, percent));
|
|
1341
1409
|
return clamped * this.state.duration;
|
|
1342
1410
|
}
|
|
1411
|
+
// ---- Document-level pointer tracking ----
|
|
1412
|
+
// pointerleave/mouseleave on the track are unreliable when the tooltip (a DOM child)
|
|
1413
|
+
// is absolutely positioned above the track — some browsers consider the pointer still
|
|
1414
|
+
// "inside" the track's subtree. Instead, we track pointer position at the document level
|
|
1415
|
+
// and hide the tooltip when the pointer moves outside the track's bounding rect.
|
|
1416
|
+
startDocumentTracking() {
|
|
1417
|
+
if (this.boundDocPointerMove)
|
|
1418
|
+
return;
|
|
1419
|
+
this.boundDocPointerMove = (event) => this.onDocPointerMove(event);
|
|
1420
|
+
document.addEventListener('pointermove', this.boundDocPointerMove);
|
|
1421
|
+
document.addEventListener('mouseleave', this.boundDocPointerMove);
|
|
1422
|
+
}
|
|
1423
|
+
stopDocumentTracking() {
|
|
1424
|
+
if (!this.boundDocPointerMove)
|
|
1425
|
+
return;
|
|
1426
|
+
document.removeEventListener('pointermove', this.boundDocPointerMove);
|
|
1427
|
+
document.removeEventListener('mouseleave', this.boundDocPointerMove);
|
|
1428
|
+
this.boundDocPointerMove = null;
|
|
1429
|
+
}
|
|
1430
|
+
onDocPointerMove(event) {
|
|
1431
|
+
if (this.isDragging)
|
|
1432
|
+
return;
|
|
1433
|
+
if (!this.trackEl)
|
|
1434
|
+
return;
|
|
1435
|
+
const rect = this.trackEl.getBoundingClientRect();
|
|
1436
|
+
const inBounds = event.clientX >= rect.left
|
|
1437
|
+
&& event.clientX <= rect.right
|
|
1438
|
+
&& event.clientY >= rect.top
|
|
1439
|
+
&& event.clientY <= rect.bottom;
|
|
1440
|
+
if (!inBounds) {
|
|
1441
|
+
this.tooltipVisible = false;
|
|
1442
|
+
this.stopDocumentTracking();
|
|
1443
|
+
this.render();
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1343
1446
|
// ---- Drag handlers ----
|
|
1344
1447
|
handlePointerDown(event) {
|
|
1345
1448
|
if (this.state.adPlaying)
|
|
1346
1449
|
return;
|
|
1347
1450
|
const trackEl = event.currentTarget;
|
|
1451
|
+
this.trackEl = trackEl;
|
|
1348
1452
|
// setPointerCapture ensures events continue firing even if pointer leaves the element
|
|
1349
1453
|
if (typeof trackEl.setPointerCapture === 'function') {
|
|
1350
1454
|
trackEl.setPointerCapture(event.pointerId);
|
|
@@ -1358,8 +1462,14 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1358
1462
|
const trackEl = event.currentTarget;
|
|
1359
1463
|
this.dragValue = this.eventToTime(event, trackEl);
|
|
1360
1464
|
this.scheduleRender();
|
|
1465
|
+
// During drag with pointer capture, only update tooltip when pointer is within track bounds
|
|
1466
|
+
const rect = trackEl.getBoundingClientRect();
|
|
1467
|
+
if (event.clientX >= rect.left && event.clientX <= rect.right) {
|
|
1468
|
+
this.updateTooltip(event);
|
|
1469
|
+
}
|
|
1470
|
+
return;
|
|
1361
1471
|
}
|
|
1362
|
-
// Always update tooltip on pointermove over the track
|
|
1472
|
+
// Always update tooltip on pointermove over the track when not dragging
|
|
1363
1473
|
this.updateTooltip(event);
|
|
1364
1474
|
}
|
|
1365
1475
|
handlePointerUp(event) {
|
|
@@ -1369,15 +1479,16 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1369
1479
|
const seekTime = this.eventToTime(event, trackEl);
|
|
1370
1480
|
this.isDragging = false;
|
|
1371
1481
|
this.bus.emit('seek', { time: seekTime });
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
handlePointerLeave() {
|
|
1482
|
+
// Always hide tooltip on pointer up — it reappears naturally via pointermove
|
|
1483
|
+
// if the pointer is still over the track.
|
|
1375
1484
|
this.tooltipVisible = false;
|
|
1485
|
+
this.stopDocumentTracking();
|
|
1376
1486
|
this.render();
|
|
1377
1487
|
}
|
|
1378
1488
|
// ---- Tooltip ----
|
|
1379
1489
|
updateTooltip(event) {
|
|
1380
1490
|
const trackEl = event.currentTarget;
|
|
1491
|
+
this.trackEl = trackEl;
|
|
1381
1492
|
const rect = trackEl.getBoundingClientRect();
|
|
1382
1493
|
// Compute hover time (use LTR calculation for tooltip position regardless of RTL)
|
|
1383
1494
|
const rawPercent = (event.clientX - rect.left) / rect.width;
|
|
@@ -1388,6 +1499,8 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1388
1499
|
// Position tooltip at pointer X relative to track, clamped to track edges
|
|
1389
1500
|
this.tooltipX = Math.min(rect.width, Math.max(0, event.clientX - rect.left));
|
|
1390
1501
|
this.tooltipVisible = true;
|
|
1502
|
+
// Start document-level tracking to detect when pointer leaves the track
|
|
1503
|
+
this.startDocumentTracking();
|
|
1391
1504
|
// Request snapshot frame for seekbar preview thumbnail
|
|
1392
1505
|
if (this.snapshotTake !== null) {
|
|
1393
1506
|
this.snapshotTake(this.tooltipTime);
|
|
@@ -1480,11 +1593,10 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1480
1593
|
const tooltip = b `
|
|
1481
1594
|
<div
|
|
1482
1595
|
class="eb-seekbar-tooltip"
|
|
1483
|
-
style="left: ${this.tooltipX}px"
|
|
1484
|
-
?hidden="${!this.tooltipVisible}"
|
|
1596
|
+
style="left: ${this.tooltipX}px; visibility: ${this.tooltipVisible ? 'visible' : 'hidden'}"
|
|
1485
1597
|
>
|
|
1486
|
-
${tooltipTimeText}
|
|
1487
1598
|
${this.previewVideoEl !== null ? this.previewVideoEl : b ``}
|
|
1599
|
+
${tooltipTimeText}
|
|
1488
1600
|
</div>
|
|
1489
1601
|
`;
|
|
1490
1602
|
return b `
|
|
@@ -1497,7 +1609,6 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1497
1609
|
@pointerdown="${(event) => this.handlePointerDown(event)}"
|
|
1498
1610
|
@pointermove="${(event) => this.handlePointerMove(event)}"
|
|
1499
1611
|
@pointerup="${(event) => this.handlePointerUp(event)}"
|
|
1500
|
-
@pointerleave="${() => this.handlePointerLeave()}"
|
|
1501
1612
|
>
|
|
1502
1613
|
<div class="eb-seekbar-buffered" style="width: ${bufferedPercent.toFixed(2)}%"></div>
|
|
1503
1614
|
<div class="eb-seekbar-progress" style="width: ${progressPercent.toFixed(2)}%">
|
|
@@ -1683,16 +1794,20 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1683
1794
|
this.mode = 'root';
|
|
1684
1795
|
this.verticalDir = 'up';
|
|
1685
1796
|
this.horizontalDir = 'right';
|
|
1797
|
+
this.outsideClickHandler = null;
|
|
1798
|
+
this.outsideClickTimer = null;
|
|
1686
1799
|
}
|
|
1687
1800
|
onConnect() {
|
|
1688
1801
|
this.state.on('settingsOpen', () => {
|
|
1689
1802
|
// When settings close, reset to root mode
|
|
1690
1803
|
if (!this.state.settingsOpen) {
|
|
1691
1804
|
this.mode = 'root';
|
|
1805
|
+
this.removeOutsideClickListener();
|
|
1692
1806
|
}
|
|
1693
1807
|
else {
|
|
1694
1808
|
// Compute placement when opening
|
|
1695
1809
|
this.computePlacement();
|
|
1810
|
+
this.addOutsideClickListener();
|
|
1696
1811
|
}
|
|
1697
1812
|
this.render();
|
|
1698
1813
|
}, { signal: this.signal });
|
|
@@ -1703,6 +1818,8 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1703
1818
|
this.state.on('subtitleTracks', () => this.render(), { signal: this.signal });
|
|
1704
1819
|
this.state.on('currentSubtitleTrack', () => this.render(), { signal: this.signal });
|
|
1705
1820
|
this.state.on('playbackRate', () => this.render(), { signal: this.signal });
|
|
1821
|
+
// Clean up outside-click listener when component disconnects
|
|
1822
|
+
this.signal.addEventListener('abort', () => this.removeOutsideClickListener());
|
|
1706
1823
|
this.render();
|
|
1707
1824
|
}
|
|
1708
1825
|
/**
|
|
@@ -1730,53 +1847,76 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1730
1847
|
this.mode = 'root';
|
|
1731
1848
|
this.render();
|
|
1732
1849
|
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Returns the display label for the currently selected value in a category.
|
|
1852
|
+
*/
|
|
1853
|
+
currentValueLabel(mode) {
|
|
1854
|
+
const i18n = this.i18n;
|
|
1855
|
+
if (mode === 'quality') {
|
|
1856
|
+
const levels = this.state.qualityLevels;
|
|
1857
|
+
const current = this.state.currentQuality;
|
|
1858
|
+
if (current === -1)
|
|
1859
|
+
return i18n.t('settings.auto');
|
|
1860
|
+
const level = levels[current];
|
|
1861
|
+
return level?.height ? `${level.height}p` : i18n.t('settings.auto');
|
|
1862
|
+
}
|
|
1863
|
+
if (mode === 'speed') {
|
|
1864
|
+
const rate = this.state.playbackRate;
|
|
1865
|
+
return rate === 1 ? i18n.t('settings.normal') : `${rate}x`;
|
|
1866
|
+
}
|
|
1867
|
+
if (mode === 'audio') {
|
|
1868
|
+
const tracks = this.state.audioTracks;
|
|
1869
|
+
const current = this.state.currentAudioTrack;
|
|
1870
|
+
const track = tracks[current];
|
|
1871
|
+
return track?.name || track?.lang || i18n.t('settings.default');
|
|
1872
|
+
}
|
|
1873
|
+
if (mode === 'subtitles') {
|
|
1874
|
+
const current = this.state.currentSubtitleTrack;
|
|
1875
|
+
if (current === -1)
|
|
1876
|
+
return i18n.t('settings.off');
|
|
1877
|
+
const tracks = this.state.subtitleTracks;
|
|
1878
|
+
const track = tracks[current];
|
|
1879
|
+
return track?.name || track?.lang || `Track ${current}`;
|
|
1880
|
+
}
|
|
1881
|
+
return '';
|
|
1882
|
+
}
|
|
1733
1883
|
renderRootMenu() {
|
|
1734
1884
|
const qualityLevels = this.state.qualityLevels;
|
|
1735
1885
|
const audioTracks = this.state.audioTracks;
|
|
1736
1886
|
const subtitleTracks = this.state.subtitleTracks;
|
|
1887
|
+
const i18n = this.i18n;
|
|
1737
1888
|
const showQuality = qualityLevels.length > 0;
|
|
1738
1889
|
const showSpeed = this.config.speed === true;
|
|
1739
1890
|
const showAudio = audioTracks.length > 1;
|
|
1740
1891
|
const showSubtitles = subtitleTracks.length > 0;
|
|
1892
|
+
const row = (iconName, label, value, mode) => b `
|
|
1893
|
+
<li>
|
|
1894
|
+
<button class="eb-settings-category" @click="${() => this.navigateTo(mode)}">
|
|
1895
|
+
<span class="eb-settings-category__icon">${icon(iconName)}</span>
|
|
1896
|
+
<span class="eb-settings-category__label">${label}</span>
|
|
1897
|
+
<span class="eb-settings-category__value">${value}</span>
|
|
1898
|
+
<span class="eb-settings-category__chevron">${icon('chevron-right')}</span>
|
|
1899
|
+
</button>
|
|
1900
|
+
</li>
|
|
1901
|
+
`;
|
|
1741
1902
|
return b `
|
|
1742
1903
|
<ul class="eb-settings-menu eb-settings-root">
|
|
1743
|
-
${
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
</button>
|
|
1748
|
-
</li>
|
|
1749
|
-
` : ''}
|
|
1750
|
-
${showSpeed ? b `
|
|
1751
|
-
<li>
|
|
1752
|
-
<button class="eb-settings-category" @click="${() => this.navigateTo('speed')}">
|
|
1753
|
-
Speed
|
|
1754
|
-
</button>
|
|
1755
|
-
</li>
|
|
1756
|
-
` : ''}
|
|
1757
|
-
${showAudio ? b `
|
|
1758
|
-
<li>
|
|
1759
|
-
<button class="eb-settings-category" @click="${() => this.navigateTo('audio')}">
|
|
1760
|
-
Audio
|
|
1761
|
-
</button>
|
|
1762
|
-
</li>
|
|
1763
|
-
` : ''}
|
|
1764
|
-
${showSubtitles ? b `
|
|
1765
|
-
<li>
|
|
1766
|
-
<button class="eb-settings-category" @click="${() => this.navigateTo('subtitles')}">
|
|
1767
|
-
Subtitles
|
|
1768
|
-
</button>
|
|
1769
|
-
</li>
|
|
1770
|
-
` : ''}
|
|
1904
|
+
${showAudio ? row('audio', i18n.t('settings.audio'), this.currentValueLabel('audio'), 'audio') : ''}
|
|
1905
|
+
${showSubtitles ? row('subtitle', i18n.t('settings.subtitles'), this.currentValueLabel('subtitles'), 'subtitles') : ''}
|
|
1906
|
+
${showSpeed ? row('speed', i18n.t('settings.speed'), this.currentValueLabel('speed'), 'speed') : ''}
|
|
1907
|
+
${showQuality ? row('quality', i18n.t('settings.quality'), this.currentValueLabel('quality'), 'quality') : ''}
|
|
1771
1908
|
</ul>
|
|
1772
1909
|
`;
|
|
1773
1910
|
}
|
|
1774
1911
|
renderSubMenu(title, items, onSelect) {
|
|
1775
1912
|
return b `
|
|
1776
1913
|
<div class="eb-settings-submenu">
|
|
1777
|
-
<
|
|
1778
|
-
${
|
|
1779
|
-
|
|
1914
|
+
<div class="eb-settings-header">
|
|
1915
|
+
<button class="eb-settings-back" @click="${() => this.navigateBack()}">
|
|
1916
|
+
${icon('chevron-left')}
|
|
1917
|
+
</button>
|
|
1918
|
+
<span class="eb-settings-header__title">${title}</span>
|
|
1919
|
+
</div>
|
|
1780
1920
|
<ul class="eb-settings-menu">
|
|
1781
1921
|
${items.map((item) => b `
|
|
1782
1922
|
<li>
|
|
@@ -1796,14 +1936,14 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1796
1936
|
const levels = this.state.qualityLevels;
|
|
1797
1937
|
const currentQuality = this.state.currentQuality;
|
|
1798
1938
|
const items = getQualityItems(levels, currentQuality);
|
|
1799
|
-
return this.renderSubMenu('
|
|
1939
|
+
return this.renderSubMenu(this.i18n.t('settings.quality'), items, (item) => {
|
|
1800
1940
|
this.bus.emit('settings-select-quality', { index: item.value });
|
|
1801
1941
|
});
|
|
1802
1942
|
}
|
|
1803
1943
|
renderSpeedMenu() {
|
|
1804
1944
|
const currentRate = this.state.playbackRate;
|
|
1805
1945
|
const items = getSpeedItems(currentRate);
|
|
1806
|
-
return this.renderSubMenu('
|
|
1946
|
+
return this.renderSubMenu(this.i18n.t('settings.speed'), items, (item) => {
|
|
1807
1947
|
this.bus.emit('settings-select-speed', { rate: item.value });
|
|
1808
1948
|
});
|
|
1809
1949
|
}
|
|
@@ -1811,7 +1951,7 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1811
1951
|
const tracks = this.state.audioTracks;
|
|
1812
1952
|
const currentTrack = this.state.currentAudioTrack;
|
|
1813
1953
|
const items = getAudioItems(tracks, currentTrack);
|
|
1814
|
-
return this.renderSubMenu('
|
|
1954
|
+
return this.renderSubMenu(this.i18n.t('settings.audio'), items, (item) => {
|
|
1815
1955
|
this.bus.emit('settings-select-audio', { index: item.value });
|
|
1816
1956
|
});
|
|
1817
1957
|
}
|
|
@@ -1819,10 +1959,37 @@ var EBPlayerBundle = (function (exports) {
|
|
|
1819
1959
|
const tracks = this.state.subtitleTracks;
|
|
1820
1960
|
const currentTrack = this.state.currentSubtitleTrack;
|
|
1821
1961
|
const items = getSubtitleItems(tracks, currentTrack);
|
|
1822
|
-
return this.renderSubMenu('
|
|
1962
|
+
return this.renderSubMenu(this.i18n.t('settings.subtitles'), items, (item) => {
|
|
1823
1963
|
this.bus.emit('settings-select-subtitle', { index: item.value });
|
|
1824
1964
|
});
|
|
1825
1965
|
}
|
|
1966
|
+
addOutsideClickListener() {
|
|
1967
|
+
this.removeOutsideClickListener();
|
|
1968
|
+
// Defer to next tick so the opening click doesn't immediately close
|
|
1969
|
+
this.outsideClickTimer = setTimeout(() => {
|
|
1970
|
+
this.outsideClickTimer = null;
|
|
1971
|
+
// Guard: panel may have closed before this timer fires
|
|
1972
|
+
if (!this.state?.settingsOpen)
|
|
1973
|
+
return;
|
|
1974
|
+
this.outsideClickHandler = (event) => {
|
|
1975
|
+
const wrapper = this.el?.querySelector('.eb-settings-wrapper');
|
|
1976
|
+
if (wrapper && !wrapper.contains(event.target)) {
|
|
1977
|
+
this.state.settingsOpen = false;
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
document.addEventListener('click', this.outsideClickHandler, { capture: true });
|
|
1981
|
+
}, 0);
|
|
1982
|
+
}
|
|
1983
|
+
removeOutsideClickListener() {
|
|
1984
|
+
if (this.outsideClickTimer !== null) {
|
|
1985
|
+
clearTimeout(this.outsideClickTimer);
|
|
1986
|
+
this.outsideClickTimer = null;
|
|
1987
|
+
}
|
|
1988
|
+
if (this.outsideClickHandler !== null) {
|
|
1989
|
+
document.removeEventListener('click', this.outsideClickHandler, { capture: true });
|
|
1990
|
+
this.outsideClickHandler = null;
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1826
1993
|
toggleSettings() {
|
|
1827
1994
|
this.state.settingsOpen = !this.state.settingsOpen;
|
|
1828
1995
|
}
|
|
@@ -2139,13 +2306,24 @@ var EBPlayerBundle = (function (exports) {
|
|
|
2139
2306
|
*
|
|
2140
2307
|
* - Calls screenfull.toggle() with the closest .eb-player ancestor on click
|
|
2141
2308
|
* - Subscribes to screenfull 'change' event to update state.isFullscreen
|
|
2142
|
-
* -
|
|
2309
|
+
* - Falls back to video-element fullscreen on mobile (iOS Safari webkitEnterFullscreen,
|
|
2310
|
+
* Android Chrome video.requestFullscreen) when the Fullscreen API is not available
|
|
2311
|
+
* for arbitrary elements
|
|
2143
2312
|
* - Re-renders when state.isFullscreen changes
|
|
2144
2313
|
*/
|
|
2145
2314
|
class FullscreenButton extends BaseComponent {
|
|
2146
2315
|
constructor() {
|
|
2147
2316
|
super(...arguments);
|
|
2148
2317
|
this.changeHandler = null;
|
|
2318
|
+
this.videoEl = null;
|
|
2319
|
+
this.videoFullscreenBeginHandler = null;
|
|
2320
|
+
this.videoFullscreenEndHandler = null;
|
|
2321
|
+
this.useVideoFallback = false;
|
|
2322
|
+
this.handleDocFullscreenChange = () => {
|
|
2323
|
+
const isFullscreen = document.fullscreenElement === this.videoEl;
|
|
2324
|
+
this.state.isFullscreen = isFullscreen;
|
|
2325
|
+
this.render();
|
|
2326
|
+
};
|
|
2149
2327
|
}
|
|
2150
2328
|
onConnect() {
|
|
2151
2329
|
this.state.on('isFullscreen', () => this.render(), { signal: this.signal });
|
|
@@ -2155,25 +2333,90 @@ var EBPlayerBundle = (function (exports) {
|
|
|
2155
2333
|
this.render();
|
|
2156
2334
|
};
|
|
2157
2335
|
screenfull$1.on('change', this.changeHandler);
|
|
2158
|
-
// Unsubscribe when signal aborts (on disconnect)
|
|
2159
2336
|
this.signal.addEventListener('abort', () => {
|
|
2160
2337
|
screenfull$1.off('change', this.changeHandler);
|
|
2161
2338
|
this.changeHandler = null;
|
|
2162
2339
|
});
|
|
2163
2340
|
}
|
|
2341
|
+
else {
|
|
2342
|
+
// Fullscreen API not available for elements — try video-element fallback (mobile)
|
|
2343
|
+
this.initVideoFallback();
|
|
2344
|
+
}
|
|
2164
2345
|
this.render();
|
|
2165
2346
|
}
|
|
2347
|
+
/**
|
|
2348
|
+
* On mobile browsers the Fullscreen API may not work on arbitrary elements,
|
|
2349
|
+
* but the <video> element itself supports fullscreen via webkitEnterFullscreen
|
|
2350
|
+
* (iOS Safari) or video.requestFullscreen() (Android Chrome).
|
|
2351
|
+
*/
|
|
2352
|
+
initVideoFallback() {
|
|
2353
|
+
const playerRoot = this.el?.closest('.eb-player');
|
|
2354
|
+
if (!playerRoot)
|
|
2355
|
+
return;
|
|
2356
|
+
const video = playerRoot.querySelector('video.eb-video');
|
|
2357
|
+
if (!video)
|
|
2358
|
+
return;
|
|
2359
|
+
// iOS Safari: webkitSupportsFullscreen + webkitEnterFullscreen
|
|
2360
|
+
const hasWebkitFullscreen = typeof video.webkitEnterFullscreen === 'function';
|
|
2361
|
+
// Android Chrome: standard requestFullscreen on the video element
|
|
2362
|
+
const hasRequestFullscreen = typeof video.requestFullscreen === 'function';
|
|
2363
|
+
if (!hasWebkitFullscreen && !hasRequestFullscreen)
|
|
2364
|
+
return;
|
|
2365
|
+
this.videoEl = video;
|
|
2366
|
+
this.useVideoFallback = true;
|
|
2367
|
+
// Track fullscreen state changes on the video element
|
|
2368
|
+
this.videoFullscreenBeginHandler = () => {
|
|
2369
|
+
this.state.isFullscreen = true;
|
|
2370
|
+
this.render();
|
|
2371
|
+
};
|
|
2372
|
+
this.videoFullscreenEndHandler = () => {
|
|
2373
|
+
this.state.isFullscreen = false;
|
|
2374
|
+
this.render();
|
|
2375
|
+
};
|
|
2376
|
+
// iOS Safari fires these events on the video element
|
|
2377
|
+
video.addEventListener('webkitbeginfullscreen', this.videoFullscreenBeginHandler);
|
|
2378
|
+
video.addEventListener('webkitendfullscreen', this.videoFullscreenEndHandler);
|
|
2379
|
+
// Android Chrome fires standard fullscreenchange on the document
|
|
2380
|
+
document.addEventListener('fullscreenchange', this.handleDocFullscreenChange);
|
|
2381
|
+
this.signal.addEventListener('abort', () => {
|
|
2382
|
+
video.removeEventListener('webkitbeginfullscreen', this.videoFullscreenBeginHandler);
|
|
2383
|
+
video.removeEventListener('webkitendfullscreen', this.videoFullscreenEndHandler);
|
|
2384
|
+
document.removeEventListener('fullscreenchange', this.handleDocFullscreenChange);
|
|
2385
|
+
this.videoFullscreenBeginHandler = null;
|
|
2386
|
+
this.videoFullscreenEndHandler = null;
|
|
2387
|
+
this.videoEl = null;
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2166
2390
|
handleClick() {
|
|
2167
|
-
if (
|
|
2391
|
+
if (screenfull$1.isEnabled) {
|
|
2392
|
+
const container = (this.el.closest('.eb-player') ?? this.el);
|
|
2393
|
+
screenfull$1.toggle(container);
|
|
2168
2394
|
return;
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2395
|
+
}
|
|
2396
|
+
if (this.useVideoFallback && this.videoEl) {
|
|
2397
|
+
if (this.state.isFullscreen) {
|
|
2398
|
+
// Exit fullscreen
|
|
2399
|
+
if (typeof this.videoEl.webkitExitFullscreen === 'function') {
|
|
2400
|
+
this.videoEl.webkitExitFullscreen();
|
|
2401
|
+
}
|
|
2402
|
+
else if (document.exitFullscreen) {
|
|
2403
|
+
document.exitFullscreen();
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
else {
|
|
2407
|
+
// Enter fullscreen
|
|
2408
|
+
if (typeof this.videoEl.webkitEnterFullscreen === 'function') {
|
|
2409
|
+
this.videoEl.webkitEnterFullscreen();
|
|
2410
|
+
}
|
|
2411
|
+
else if (typeof this.videoEl.requestFullscreen === 'function') {
|
|
2412
|
+
this.videoEl.requestFullscreen();
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2174
2416
|
}
|
|
2175
2417
|
template() {
|
|
2176
|
-
|
|
2418
|
+
const canFullscreen = screenfull$1.isEnabled || this.useVideoFallback;
|
|
2419
|
+
if (!canFullscreen) {
|
|
2177
2420
|
return b `<button class="eb-fullscreen" hidden aria-hidden="true">${icon('fullscreen')}</button>`;
|
|
2178
2421
|
}
|
|
2179
2422
|
const isFullscreen = this.state.isFullscreen;
|
|
@@ -3687,6 +3930,13 @@ var EBPlayerBundle = (function (exports) {
|
|
|
3687
3930
|
*/
|
|
3688
3931
|
mount(container) {
|
|
3689
3932
|
this._container = container;
|
|
3933
|
+
// Clear container DOM so a fresh <video> element is created on each mount.
|
|
3934
|
+
// This prevents EME/MediaKeys conflicts — setMediaKeys(null) is async and
|
|
3935
|
+
// hls.js destroy() doesn't wait for it, so reusing the same <video> element
|
|
3936
|
+
// causes "The existing ContentDecryptor" errors on skin switch.
|
|
3937
|
+
container.textContent = '';
|
|
3938
|
+
// Clear lit-html's internal render state so render() treats the container as fresh
|
|
3939
|
+
delete container['_$litPart$'];
|
|
3690
3940
|
// Clear any stale theme/style from a previous mount cycle
|
|
3691
3941
|
container.removeAttribute('data-theme');
|
|
3692
3942
|
container.removeAttribute('style');
|
|
@@ -4082,6 +4332,15 @@ var EBPlayerBundle = (function (exports) {
|
|
|
4082
4332
|
video.addEventListener('ended', () => {
|
|
4083
4333
|
state.playbackState = 'ended';
|
|
4084
4334
|
}, { signal });
|
|
4335
|
+
// Safety net: clear stale 'buffering' state when playback is clearly advancing.
|
|
4336
|
+
// In some edge cases (live stream segment boundaries), the browser fires 'waiting'
|
|
4337
|
+
// but never fires 'playing' even though video resumes from buffer. The timeupdate
|
|
4338
|
+
// event fires reliably while time advances, so we use it to recover.
|
|
4339
|
+
video.addEventListener('timeupdate', () => {
|
|
4340
|
+
if (state.playbackState === 'buffering' && !video.paused && video.readyState >= 3) {
|
|
4341
|
+
state.playbackState = 'playing';
|
|
4342
|
+
}
|
|
4343
|
+
}, { signal });
|
|
4085
4344
|
}
|
|
4086
4345
|
/**
|
|
4087
4346
|
* Seek to a specific time. Default implementation sets video.currentTime.
|
|
@@ -4902,6 +5161,7 @@ var EBPlayerBundle = (function (exports) {
|
|
|
4902
5161
|
// Private — NEVER in PlayerState (Pitfall 2)
|
|
4903
5162
|
this.driver = null;
|
|
4904
5163
|
this.tokenManager = null;
|
|
5164
|
+
this.autoQuality = true;
|
|
4905
5165
|
// Holds state reference for named driver event handlers
|
|
4906
5166
|
this.eventState = null;
|
|
4907
5167
|
this.liveSyncDisabled = false;
|
|
@@ -4909,6 +5169,14 @@ var EBPlayerBundle = (function (exports) {
|
|
|
4909
5169
|
getDriver() {
|
|
4910
5170
|
return this.driver;
|
|
4911
5171
|
}
|
|
5172
|
+
/**
|
|
5173
|
+
* Returns the CDN token manager used by this engine.
|
|
5174
|
+
* Allows the snapshot handler to share the same manager (avoids duplicate token requests).
|
|
5175
|
+
* Returns null when no token URL is configured or before init().
|
|
5176
|
+
*/
|
|
5177
|
+
getTokenManager() {
|
|
5178
|
+
return this.tokenManager;
|
|
5179
|
+
}
|
|
4912
5180
|
// -------------------------------------------------------------------------
|
|
4913
5181
|
// BaseEngine hooks
|
|
4914
5182
|
// -------------------------------------------------------------------------
|
|
@@ -4961,6 +5229,14 @@ var EBPlayerBundle = (function (exports) {
|
|
|
4961
5229
|
if (this.driver === null)
|
|
4962
5230
|
return;
|
|
4963
5231
|
this.driver.currentLevel = index;
|
|
5232
|
+
// When index is -1 (Auto/ABR), hls.js will fire LEVEL_SWITCHED with the
|
|
5233
|
+
// actual resolved level. We need to keep currentQuality as -1 so the UI
|
|
5234
|
+
// shows "Auto" as selected. Track ABR mode to prevent LEVEL_SWITCHED
|
|
5235
|
+
// from overwriting it.
|
|
5236
|
+
this.autoQuality = index === -1;
|
|
5237
|
+
if (this.state !== null) {
|
|
5238
|
+
this.state.currentQuality = index;
|
|
5239
|
+
}
|
|
4964
5240
|
}
|
|
4965
5241
|
setAudioTrack(index) {
|
|
4966
5242
|
if (this.driver === null)
|
|
@@ -5016,7 +5292,9 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5016
5292
|
if (!hlsjsUrl) {
|
|
5017
5293
|
throw new Error('HlsEngine: config.hlsjs URL is required');
|
|
5018
5294
|
}
|
|
5019
|
-
// Create token manager if a token URL is configured
|
|
5295
|
+
// Create token manager if a token URL is configured.
|
|
5296
|
+
// No initial fetchToken() here — updateUrlWithTokenParams() below handles it
|
|
5297
|
+
// and populates lastTokenResponse (used lazily by DRM licenseXhrSetup).
|
|
5020
5298
|
if (config.token) {
|
|
5021
5299
|
this.tokenManager = new CDNTokenManager({
|
|
5022
5300
|
token: config.token,
|
|
@@ -5025,15 +5303,8 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5025
5303
|
extraParamsCallback: (config.engineSettings.extraParamsCallback ?? config.extraParamsCallback),
|
|
5026
5304
|
onCDNTokenError: config.engineSettings.onCDNTokenError
|
|
5027
5305
|
});
|
|
5028
|
-
// Fetch initial token
|
|
5029
|
-
if (config.src) {
|
|
5030
|
-
await this.tokenManager.fetchToken({ src: config.src });
|
|
5031
|
-
}
|
|
5032
|
-
// Guard: abort if detached during token fetch
|
|
5033
|
-
if (this.detached)
|
|
5034
|
-
return;
|
|
5035
5306
|
}
|
|
5036
|
-
console.info('HlsEngine: loading hls.js from', hlsjsUrl)
|
|
5307
|
+
// console.info('HlsEngine: loading hls.js from', hlsjsUrl)
|
|
5037
5308
|
const Hls = await loadScript(hlsjsUrl, 'Hls');
|
|
5038
5309
|
// Guard: abort if detached during CDN script load
|
|
5039
5310
|
if (this.detached)
|
|
@@ -5046,7 +5317,7 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5046
5317
|
// Build driver config — only spread known engineSettings keys that hls.js recognises,
|
|
5047
5318
|
// not the entire engineSettings bag (which may contain player-specific keys like
|
|
5048
5319
|
// extraParamsCallback that should NOT leak into the hls.js constructor config).
|
|
5049
|
-
const { emeEnabled, drmSystems, ...hlsEngineSettings } = config.engineSettings;
|
|
5320
|
+
const { emeEnabled: _emeEnabled, drmSystems: _drmSystems, ...hlsEngineSettings } = config.engineSettings;
|
|
5050
5321
|
// Remove player-specific keys that are NOT hls.js config options
|
|
5051
5322
|
const hlsSafeSettings = { ...hlsEngineSettings };
|
|
5052
5323
|
delete hlsSafeSettings['extraParamsCallback'];
|
|
@@ -5114,7 +5385,6 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5114
5385
|
// Create the driver (NEVER stored in state)
|
|
5115
5386
|
const driver = new Hls(driverConfig);
|
|
5116
5387
|
this.driver = driver;
|
|
5117
|
-
this.resolveDriverReady();
|
|
5118
5388
|
// Pitfall 4: apply discontinuity workaround BEFORE attachMedia/loadSource
|
|
5119
5389
|
applyDiscontinuityWorkaround(driver, Hls.Events);
|
|
5120
5390
|
// Wire retry handler
|
|
@@ -5137,8 +5407,27 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5137
5407
|
}
|
|
5138
5408
|
}
|
|
5139
5409
|
driver.loadSource(src);
|
|
5410
|
+
// Resolve driverReady AFTER loadSource so consumers (P2P, snapshot handler)
|
|
5411
|
+
// don't start making token requests before the main engine's initial token
|
|
5412
|
+
// fetch completes and populates the cache.
|
|
5413
|
+
this.resolveDriverReady();
|
|
5140
5414
|
// Register driver event handlers
|
|
5141
5415
|
this.registerDriverEvents(Hls, state);
|
|
5416
|
+
// Pause/resume loading on video pause/play to stop manifest refreshes
|
|
5417
|
+
// (and thus CDN token requests) while the player is paused.
|
|
5418
|
+
// Only applies to live streams where hls.js continuously refreshes the manifest.
|
|
5419
|
+
const driverRef = driver;
|
|
5420
|
+
video.addEventListener('pause', () => {
|
|
5421
|
+
if (this.state?.isLive) {
|
|
5422
|
+
driverRef.stopLoad();
|
|
5423
|
+
}
|
|
5424
|
+
}, { signal });
|
|
5425
|
+
video.addEventListener('play', () => {
|
|
5426
|
+
if (this.state?.isLive) {
|
|
5427
|
+
// Defer startLoad to avoid re-entrancy (Pitfall 3)
|
|
5428
|
+
setTimeout(() => driverRef.startLoad(-1), 0);
|
|
5429
|
+
}
|
|
5430
|
+
}, { signal });
|
|
5142
5431
|
// Start stall watchdog
|
|
5143
5432
|
this.startWatchdog();
|
|
5144
5433
|
}
|
|
@@ -5190,8 +5479,12 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5190
5479
|
const state = this.eventState;
|
|
5191
5480
|
if (!state)
|
|
5192
5481
|
return;
|
|
5193
|
-
|
|
5194
|
-
|
|
5482
|
+
// In ABR mode (autoQuality), keep currentQuality as -1 so the UI shows "Auto".
|
|
5483
|
+
// Only update to the actual level index when the user picked a specific quality.
|
|
5484
|
+
if (!this.autoQuality) {
|
|
5485
|
+
const switchedData = data;
|
|
5486
|
+
state.currentQuality = switchedData.level;
|
|
5487
|
+
}
|
|
5195
5488
|
}
|
|
5196
5489
|
_onAudioTracksUpdated(_event, data) {
|
|
5197
5490
|
const state = this.eventState;
|
|
@@ -5570,7 +5863,7 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5570
5863
|
};
|
|
5571
5864
|
// Register with AbortSignal so it auto-removes when engine is detached
|
|
5572
5865
|
window.addEventListener('unhandledrejection', this.dvrErrorHandler, { signal });
|
|
5573
|
-
console.info('DashEngine: loading dashjs from', dashjsUrl)
|
|
5866
|
+
// console.info('DashEngine: loading dashjs from', dashjsUrl)
|
|
5574
5867
|
const dashjs = await loadScript(dashjsUrl, 'dashjs');
|
|
5575
5868
|
const player = dashjs.MediaPlayer().create();
|
|
5576
5869
|
if (!player) {
|
|
@@ -5736,7 +6029,9 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5736
6029
|
this.lib.start();
|
|
5737
6030
|
// Clean up on abort
|
|
5738
6031
|
signal.addEventListener('abort', () => {
|
|
5739
|
-
this.lib.stop
|
|
6032
|
+
if (this.lib !== null && typeof this.lib.stop === 'function') {
|
|
6033
|
+
this.lib.stop();
|
|
6034
|
+
}
|
|
5740
6035
|
this.lib = null;
|
|
5741
6036
|
}, { once: true });
|
|
5742
6037
|
}
|
|
@@ -5777,7 +6072,7 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5777
6072
|
init(HlsConstructor) {
|
|
5778
6073
|
// Create an off-screen video element for the snapshot player
|
|
5779
6074
|
const offscreenVideo = document.createElement('video');
|
|
5780
|
-
offscreenVideo.preload = '
|
|
6075
|
+
offscreenVideo.preload = 'metadata';
|
|
5781
6076
|
this.offscreenVideo = offscreenVideo;
|
|
5782
6077
|
// Capture tokenManager via closure (Pitfall 6)
|
|
5783
6078
|
const tokenManager = this.tokenManager;
|
|
@@ -5808,11 +6103,17 @@ var EBPlayerBundle = (function (exports) {
|
|
|
5808
6103
|
}
|
|
5809
6104
|
PLoader = SnapshotPLoader;
|
|
5810
6105
|
}
|
|
6106
|
+
// Strip player-specific keys that are NOT hls.js config options — they contain
|
|
6107
|
+
// non-serializable functions that cause DataCloneError when hls.js posts config to its worker.
|
|
6108
|
+
const rawSettings = { ...(this.config.engineSettings ?? {}) };
|
|
6109
|
+
delete rawSettings['extraParamsCallback'];
|
|
6110
|
+
delete rawSettings['onCDNTokenError'];
|
|
5811
6111
|
const driverConfig = {
|
|
5812
6112
|
startLevel: 0,
|
|
5813
6113
|
enableWebVTT: false,
|
|
6114
|
+
enableWorker: false,
|
|
5814
6115
|
maxBufferLength: 1,
|
|
5815
|
-
...
|
|
6116
|
+
...rawSettings,
|
|
5816
6117
|
...(PLoader ? { pLoader: PLoader } : {})
|
|
5817
6118
|
};
|
|
5818
6119
|
const driver = new HlsConstructor(driverConfig);
|
|
@@ -6069,7 +6370,7 @@ var EBPlayerBundle = (function (exports) {
|
|
|
6069
6370
|
*
|
|
6070
6371
|
* Returns a PlayerReference synchronously — never returns a Promise.
|
|
6071
6372
|
*/
|
|
6072
|
-
function start(runtimeConfig) {
|
|
6373
|
+
function start$1(runtimeConfig) {
|
|
6073
6374
|
// Dispose any existing instance before creating a new one
|
|
6074
6375
|
if (activeController !== null) {
|
|
6075
6376
|
destroy();
|
|
@@ -6143,7 +6444,13 @@ var EBPlayerBundle = (function (exports) {
|
|
|
6143
6444
|
else {
|
|
6144
6445
|
const win = window;
|
|
6145
6446
|
if (win.Hls) {
|
|
6146
|
-
|
|
6447
|
+
// Share the main engine's token manager with the snapshot handler
|
|
6448
|
+
// to avoid duplicate token requests (one CDNTokenManager per player instance)
|
|
6449
|
+
const sharedTokenManager = engine.getTokenManager();
|
|
6450
|
+
// Build DRM config (emeEnabled, drmSystems, licenseXhrSetup) for the snapshot hls.js instance
|
|
6451
|
+
const snapshotDrmConfigurator = new DrmConfigurator(sharedTokenManager);
|
|
6452
|
+
const snapshotDrmConfig = snapshotDrmConfigurator.buildHlsConfig(mergedConfig.engineSettings);
|
|
6453
|
+
const handler = new HlsSnapshotHandler({ src, engineSettings: { ...mergedConfig.engineSettings, ...snapshotDrmConfig } }, sharedTokenManager);
|
|
6147
6454
|
handler.init(win.Hls)
|
|
6148
6455
|
.then(() => {
|
|
6149
6456
|
activeSnapshotDestroy = () => handler.destroy();
|
|
@@ -6201,9 +6508,22 @@ var EBPlayerBundle = (function (exports) {
|
|
|
6201
6508
|
}, 100);
|
|
6202
6509
|
});
|
|
6203
6510
|
// Auto-open the stream if src is provided in config (matches legacy player behaviour
|
|
6204
|
-
// where consumers call start({ src: '...' }) and expect playback to begin immediately)
|
|
6511
|
+
// where consumers call start({ src: '...' }) and expect playback to begin immediately).
|
|
6512
|
+
// When autoplay is false, defer open() until the user requests play — this avoids
|
|
6513
|
+
// fetching CDN tokens and loading manifests before playback is actually needed.
|
|
6205
6514
|
if (mergedConfig.src) {
|
|
6206
|
-
|
|
6515
|
+
if (mergedConfig.autoplay) {
|
|
6516
|
+
reference.open(mergedConfig.src);
|
|
6517
|
+
}
|
|
6518
|
+
else {
|
|
6519
|
+
let deferredOpen = true;
|
|
6520
|
+
controller.bus.on('play', () => {
|
|
6521
|
+
if (deferredOpen) {
|
|
6522
|
+
deferredOpen = false;
|
|
6523
|
+
reference.open(mergedConfig.src);
|
|
6524
|
+
}
|
|
6525
|
+
}, { signal: controller.signal });
|
|
6526
|
+
}
|
|
6207
6527
|
}
|
|
6208
6528
|
return reference;
|
|
6209
6529
|
}
|
|
@@ -6232,10 +6552,17 @@ var EBPlayerBundle = (function (exports) {
|
|
|
6232
6552
|
}
|
|
6233
6553
|
}
|
|
6234
6554
|
// ---------------------------------------------------------------------------
|
|
6555
|
+
// Version
|
|
6556
|
+
// ---------------------------------------------------------------------------
|
|
6557
|
+
// Injected at build time by Rollup's @rollup/plugin-virtual or replaced by bundler.
|
|
6558
|
+
// Falls back to 'dev' when running unbundled (tests, dev server).
|
|
6559
|
+
const VERSION = typeof __EB_PLAYER_VERSION__ !== 'undefined' ? __EB_PLAYER_VERSION__ : 'dev';
|
|
6560
|
+
// ---------------------------------------------------------------------------
|
|
6235
6561
|
// window.EBPlayer assignment
|
|
6236
6562
|
// ---------------------------------------------------------------------------
|
|
6237
6563
|
if (typeof window !== 'undefined') {
|
|
6238
|
-
|
|
6564
|
+
console.info(`%cEBPlayer v${VERSION}`, 'color: #1FA9DD; font-weight: bold');
|
|
6565
|
+
window.EBPlayer = { start: start$1, stop, destroy, AVAILABLE_THEMES, THEME_LAYOUTS, version: VERSION };
|
|
6239
6566
|
}
|
|
6240
6567
|
|
|
6241
6568
|
var brandConfig = {"autoplay":true,"muted":true,"src":"https://live.easybroadcast.fr/hls/live/playlist.m3u8","liveButton":true,"showProgressThumb":true};
|
|
@@ -6244,16 +6571,36 @@ var EBPlayerBundle = (function (exports) {
|
|
|
6244
6571
|
* Standalone entry point — used for the generated player bundle (not the npm UMD build).
|
|
6245
6572
|
*
|
|
6246
6573
|
* This file is resolved by Rollup with @rollup/plugin-virtual injecting the brand config
|
|
6247
|
-
* from 'virtual:brand-config' at build time.
|
|
6248
|
-
*
|
|
6574
|
+
* from 'virtual:brand-config' at build time.
|
|
6575
|
+
*
|
|
6576
|
+
* The exported start() wraps eb-player's start() to merge the brand config as a base,
|
|
6577
|
+
* so consumers calling window.EBPlayer.start({src: '...'}) inherit brand settings
|
|
6578
|
+
* (skin, colors, tokens, etc.) without having to repeat them.
|
|
6249
6579
|
*
|
|
6250
6580
|
* Import chain:
|
|
6251
6581
|
* eb-player-standalone.ts → eb-player.ts (facade) + virtual:brand-config (brand config)
|
|
6252
6582
|
*/
|
|
6253
|
-
const
|
|
6583
|
+
const brand = brandConfig;
|
|
6584
|
+
/**
|
|
6585
|
+
* Start the player with brand config as the base layer.
|
|
6586
|
+
* Consumer's runtimeConfig overrides brand values, which override DEFAULT_CONFIG.
|
|
6587
|
+
* Merge order: DEFAULT_CONFIG → brandConfig → runtimeConfig
|
|
6588
|
+
*/
|
|
6589
|
+
function start(runtimeConfig) {
|
|
6590
|
+
const merged = mergeConfig(DEFAULT_CONFIG, brand, runtimeConfig ?? {});
|
|
6591
|
+
return start$1(merged);
|
|
6592
|
+
}
|
|
6593
|
+
// Expose on window.EBPlayer so the wrapped start() is used
|
|
6594
|
+
if (typeof window !== 'undefined') {
|
|
6595
|
+
const ebp = window.EBPlayer;
|
|
6596
|
+
if (ebp) {
|
|
6597
|
+
ebp.start = start;
|
|
6598
|
+
}
|
|
6599
|
+
}
|
|
6254
6600
|
// Auto-start if config.start is truthy (mirrors legacy generator/generate.js behaviour).
|
|
6255
6601
|
// Skip auto-start when the target container doesn't exist — this means the bundle is
|
|
6256
6602
|
// loaded as a library (e.g., by the test player) and the consumer will call start() itself.
|
|
6603
|
+
const mergedConfig = mergeConfig(DEFAULT_CONFIG, brand);
|
|
6257
6604
|
if (mergedConfig.start) {
|
|
6258
6605
|
const el = mergedConfig.el;
|
|
6259
6606
|
const containerExists = typeof el === 'string'
|