eb-player 2.0.7 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,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;
@@ -34,10 +36,10 @@ var EBPlayerBundle = (function (exports) {
34
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";
35
37
  styleInject(css_248z$6);
36
38
 
37
- 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: 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=\"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/* Red gradient fill */\n[data-theme=\"lequipe\"] .eb-player .eb-seekbar-progress {\n background: linear-gradient(90deg, #d61e00, color-mix(in srgb, #d61e00 70%, #fff));\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: #fff;\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(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=\"lequipe\"] .eb-player .eb-settings-menu {\n padding: 0;\n}\n\n[data-theme=\"lequipe\"] .eb-player .eb-settings-category,\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item,\n[data-theme=\"lequipe\"] .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=\"lequipe\"] .eb-player .eb-settings-category:last-child,\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-category:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item:hover,\n[data-theme=\"lequipe\"] .eb-player .eb-settings-back:hover {\n background: rgba(255,255,255,.05);\n}\n\n/* Selected item text */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item--selected {\n color: #fff;\n font-weight: 500;\n}\n\n/* Active selection dot (filled red) */\n[data-theme=\"lequipe\"] .eb-player .eb-settings-item--selected::after {\n content: '';\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--eb-accent, #d61e00);\n box-shadow: 0 0 0 3px rgba(214,30,0,.25);\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: 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=\"lequipe\"] .eb-player .eb-settings-back {\n gap: 14px;\n font-weight: 600;\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";
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";
38
40
  styleInject(css_248z$5);
39
41
 
40
- 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";
41
43
  styleInject(css_248z$4);
42
44
 
43
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";
@@ -46,10 +48,10 @@ var EBPlayerBundle = (function (exports) {
46
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";
47
49
  styleInject(css_248z$2);
48
50
 
49
- 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";
50
52
  styleInject(css_248z$1);
51
53
 
52
- 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";
53
55
  styleInject(css_248z);
54
56
 
55
57
  /**
@@ -322,6 +324,20 @@ var EBPlayerBundle = (function (exports) {
322
324
  right: ['forward']
323
325
  }
324
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
+ ];
325
341
  /**
326
342
  * Theme-specific default layouts.
327
343
  * Used when config.layout is not explicitly provided but a theme is set.
@@ -342,9 +358,25 @@ var EBPlayerBundle = (function (exports) {
342
358
  right: ['forward']
343
359
  }
344
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
+ };
345
377
  const THEME_LAYOUTS = {
346
378
  v2: V2_LAYOUT,
347
- lequipe: V2_LAYOUT,
379
+ lequipe: LEQUIPE_LAYOUT,
348
380
  modern: V2_LAYOUT,
349
381
  };
350
382
  /**
@@ -566,6 +598,30 @@ var EBPlayerBundle = (function (exports) {
566
598
  fr: 'La diffusion a échoué. Reprise de la lecture locale.',
567
599
  ar: 'Casting failed. Resuming local playback.',
568
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'
569
625
  }
570
626
  };
571
627
  /**
@@ -1304,6 +1360,8 @@ var EBPlayerBundle = (function (exports) {
1304
1360
  this.tooltipX = 0;
1305
1361
  this.previewVideoEl = null;
1306
1362
  this.snapshotTake = null;
1363
+ this.trackEl = null;
1364
+ this.boundDocPointerMove = null;
1307
1365
  }
1308
1366
  onConnect() {
1309
1367
  // Subscribe to snapshot handler readiness (emitted by eb-player.ts)
@@ -1324,6 +1382,10 @@ var EBPlayerBundle = (function (exports) {
1324
1382
  this.state.on('epgPrograms', () => this.scheduleRender(), { signal: this.signal });
1325
1383
  this.render();
1326
1384
  }
1385
+ disconnect() {
1386
+ this.stopDocumentTracking();
1387
+ super.disconnect();
1388
+ }
1327
1389
  // ---- rAF batching ----
1328
1390
  scheduleRender() {
1329
1391
  if (this.rafPending)
@@ -1346,11 +1408,47 @@ var EBPlayerBundle = (function (exports) {
1346
1408
  const clamped = Math.min(1, Math.max(0, percent));
1347
1409
  return clamped * this.state.duration;
1348
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
+ }
1349
1446
  // ---- Drag handlers ----
1350
1447
  handlePointerDown(event) {
1351
1448
  if (this.state.adPlaying)
1352
1449
  return;
1353
1450
  const trackEl = event.currentTarget;
1451
+ this.trackEl = trackEl;
1354
1452
  // setPointerCapture ensures events continue firing even if pointer leaves the element
1355
1453
  if (typeof trackEl.setPointerCapture === 'function') {
1356
1454
  trackEl.setPointerCapture(event.pointerId);
@@ -1364,8 +1462,14 @@ var EBPlayerBundle = (function (exports) {
1364
1462
  const trackEl = event.currentTarget;
1365
1463
  this.dragValue = this.eventToTime(event, trackEl);
1366
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;
1367
1471
  }
1368
- // Always update tooltip on pointermove over the track
1472
+ // Always update tooltip on pointermove over the track when not dragging
1369
1473
  this.updateTooltip(event);
1370
1474
  }
1371
1475
  handlePointerUp(event) {
@@ -1375,15 +1479,16 @@ var EBPlayerBundle = (function (exports) {
1375
1479
  const seekTime = this.eventToTime(event, trackEl);
1376
1480
  this.isDragging = false;
1377
1481
  this.bus.emit('seek', { time: seekTime });
1378
- this.render();
1379
- }
1380
- handlePointerLeave() {
1482
+ // Always hide tooltip on pointer up — it reappears naturally via pointermove
1483
+ // if the pointer is still over the track.
1381
1484
  this.tooltipVisible = false;
1485
+ this.stopDocumentTracking();
1382
1486
  this.render();
1383
1487
  }
1384
1488
  // ---- Tooltip ----
1385
1489
  updateTooltip(event) {
1386
1490
  const trackEl = event.currentTarget;
1491
+ this.trackEl = trackEl;
1387
1492
  const rect = trackEl.getBoundingClientRect();
1388
1493
  // Compute hover time (use LTR calculation for tooltip position regardless of RTL)
1389
1494
  const rawPercent = (event.clientX - rect.left) / rect.width;
@@ -1394,6 +1499,8 @@ var EBPlayerBundle = (function (exports) {
1394
1499
  // Position tooltip at pointer X relative to track, clamped to track edges
1395
1500
  this.tooltipX = Math.min(rect.width, Math.max(0, event.clientX - rect.left));
1396
1501
  this.tooltipVisible = true;
1502
+ // Start document-level tracking to detect when pointer leaves the track
1503
+ this.startDocumentTracking();
1397
1504
  // Request snapshot frame for seekbar preview thumbnail
1398
1505
  if (this.snapshotTake !== null) {
1399
1506
  this.snapshotTake(this.tooltipTime);
@@ -1486,11 +1593,10 @@ var EBPlayerBundle = (function (exports) {
1486
1593
  const tooltip = b `
1487
1594
  <div
1488
1595
  class="eb-seekbar-tooltip"
1489
- style="left: ${this.tooltipX}px"
1490
- ?hidden="${!this.tooltipVisible}"
1596
+ style="left: ${this.tooltipX}px; visibility: ${this.tooltipVisible ? 'visible' : 'hidden'}"
1491
1597
  >
1492
- ${tooltipTimeText}
1493
1598
  ${this.previewVideoEl !== null ? this.previewVideoEl : b ``}
1599
+ ${tooltipTimeText}
1494
1600
  </div>
1495
1601
  `;
1496
1602
  return b `
@@ -1503,7 +1609,6 @@ var EBPlayerBundle = (function (exports) {
1503
1609
  @pointerdown="${(event) => this.handlePointerDown(event)}"
1504
1610
  @pointermove="${(event) => this.handlePointerMove(event)}"
1505
1611
  @pointerup="${(event) => this.handlePointerUp(event)}"
1506
- @pointerleave="${() => this.handlePointerLeave()}"
1507
1612
  >
1508
1613
  <div class="eb-seekbar-buffered" style="width: ${bufferedPercent.toFixed(2)}%"></div>
1509
1614
  <div class="eb-seekbar-progress" style="width: ${progressPercent.toFixed(2)}%">
@@ -1689,16 +1794,20 @@ var EBPlayerBundle = (function (exports) {
1689
1794
  this.mode = 'root';
1690
1795
  this.verticalDir = 'up';
1691
1796
  this.horizontalDir = 'right';
1797
+ this.outsideClickHandler = null;
1798
+ this.outsideClickTimer = null;
1692
1799
  }
1693
1800
  onConnect() {
1694
1801
  this.state.on('settingsOpen', () => {
1695
1802
  // When settings close, reset to root mode
1696
1803
  if (!this.state.settingsOpen) {
1697
1804
  this.mode = 'root';
1805
+ this.removeOutsideClickListener();
1698
1806
  }
1699
1807
  else {
1700
1808
  // Compute placement when opening
1701
1809
  this.computePlacement();
1810
+ this.addOutsideClickListener();
1702
1811
  }
1703
1812
  this.render();
1704
1813
  }, { signal: this.signal });
@@ -1709,6 +1818,8 @@ var EBPlayerBundle = (function (exports) {
1709
1818
  this.state.on('subtitleTracks', () => this.render(), { signal: this.signal });
1710
1819
  this.state.on('currentSubtitleTrack', () => this.render(), { signal: this.signal });
1711
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());
1712
1823
  this.render();
1713
1824
  }
1714
1825
  /**
@@ -1736,53 +1847,76 @@ var EBPlayerBundle = (function (exports) {
1736
1847
  this.mode = 'root';
1737
1848
  this.render();
1738
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
+ }
1739
1883
  renderRootMenu() {
1740
1884
  const qualityLevels = this.state.qualityLevels;
1741
1885
  const audioTracks = this.state.audioTracks;
1742
1886
  const subtitleTracks = this.state.subtitleTracks;
1887
+ const i18n = this.i18n;
1743
1888
  const showQuality = qualityLevels.length > 0;
1744
1889
  const showSpeed = this.config.speed === true;
1745
1890
  const showAudio = audioTracks.length > 1;
1746
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
+ `;
1747
1902
  return b `
1748
1903
  <ul class="eb-settings-menu eb-settings-root">
1749
- ${showQuality ? b `
1750
- <li>
1751
- <button class="eb-settings-category" @click="${() => this.navigateTo('quality')}">
1752
- Quality
1753
- </button>
1754
- </li>
1755
- ` : ''}
1756
- ${showSpeed ? b `
1757
- <li>
1758
- <button class="eb-settings-category" @click="${() => this.navigateTo('speed')}">
1759
- Speed
1760
- </button>
1761
- </li>
1762
- ` : ''}
1763
- ${showAudio ? b `
1764
- <li>
1765
- <button class="eb-settings-category" @click="${() => this.navigateTo('audio')}">
1766
- Audio
1767
- </button>
1768
- </li>
1769
- ` : ''}
1770
- ${showSubtitles ? b `
1771
- <li>
1772
- <button class="eb-settings-category" @click="${() => this.navigateTo('subtitles')}">
1773
- Subtitles
1774
- </button>
1775
- </li>
1776
- ` : ''}
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') : ''}
1777
1908
  </ul>
1778
1909
  `;
1779
1910
  }
1780
1911
  renderSubMenu(title, items, onSelect) {
1781
1912
  return b `
1782
1913
  <div class="eb-settings-submenu">
1783
- <button class="eb-settings-back" @click="${() => this.navigateBack()}">
1784
- ${title}
1785
- </button>
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>
1786
1920
  <ul class="eb-settings-menu">
1787
1921
  ${items.map((item) => b `
1788
1922
  <li>
@@ -1802,14 +1936,14 @@ var EBPlayerBundle = (function (exports) {
1802
1936
  const levels = this.state.qualityLevels;
1803
1937
  const currentQuality = this.state.currentQuality;
1804
1938
  const items = getQualityItems(levels, currentQuality);
1805
- return this.renderSubMenu('Quality', items, (item) => {
1939
+ return this.renderSubMenu(this.i18n.t('settings.quality'), items, (item) => {
1806
1940
  this.bus.emit('settings-select-quality', { index: item.value });
1807
1941
  });
1808
1942
  }
1809
1943
  renderSpeedMenu() {
1810
1944
  const currentRate = this.state.playbackRate;
1811
1945
  const items = getSpeedItems(currentRate);
1812
- return this.renderSubMenu('Speed', items, (item) => {
1946
+ return this.renderSubMenu(this.i18n.t('settings.speed'), items, (item) => {
1813
1947
  this.bus.emit('settings-select-speed', { rate: item.value });
1814
1948
  });
1815
1949
  }
@@ -1817,7 +1951,7 @@ var EBPlayerBundle = (function (exports) {
1817
1951
  const tracks = this.state.audioTracks;
1818
1952
  const currentTrack = this.state.currentAudioTrack;
1819
1953
  const items = getAudioItems(tracks, currentTrack);
1820
- return this.renderSubMenu('Audio', items, (item) => {
1954
+ return this.renderSubMenu(this.i18n.t('settings.audio'), items, (item) => {
1821
1955
  this.bus.emit('settings-select-audio', { index: item.value });
1822
1956
  });
1823
1957
  }
@@ -1825,10 +1959,37 @@ var EBPlayerBundle = (function (exports) {
1825
1959
  const tracks = this.state.subtitleTracks;
1826
1960
  const currentTrack = this.state.currentSubtitleTrack;
1827
1961
  const items = getSubtitleItems(tracks, currentTrack);
1828
- return this.renderSubMenu('Subtitles', items, (item) => {
1962
+ return this.renderSubMenu(this.i18n.t('settings.subtitles'), items, (item) => {
1829
1963
  this.bus.emit('settings-select-subtitle', { index: item.value });
1830
1964
  });
1831
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
+ }
1832
1993
  toggleSettings() {
1833
1994
  this.state.settingsOpen = !this.state.settingsOpen;
1834
1995
  }
@@ -2145,13 +2306,24 @@ var EBPlayerBundle = (function (exports) {
2145
2306
  *
2146
2307
  * - Calls screenfull.toggle() with the closest .eb-player ancestor on click
2147
2308
  * - Subscribes to screenfull 'change' event to update state.isFullscreen
2148
- * - Hidden when screenfull.isEnabled is false (e.g. iOS Safari)
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
2149
2312
  * - Re-renders when state.isFullscreen changes
2150
2313
  */
2151
2314
  class FullscreenButton extends BaseComponent {
2152
2315
  constructor() {
2153
2316
  super(...arguments);
2154
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
+ };
2155
2327
  }
2156
2328
  onConnect() {
2157
2329
  this.state.on('isFullscreen', () => this.render(), { signal: this.signal });
@@ -2161,25 +2333,90 @@ var EBPlayerBundle = (function (exports) {
2161
2333
  this.render();
2162
2334
  };
2163
2335
  screenfull$1.on('change', this.changeHandler);
2164
- // Unsubscribe when signal aborts (on disconnect)
2165
2336
  this.signal.addEventListener('abort', () => {
2166
2337
  screenfull$1.off('change', this.changeHandler);
2167
2338
  this.changeHandler = null;
2168
2339
  });
2169
2340
  }
2341
+ else {
2342
+ // Fullscreen API not available for elements — try video-element fallback (mobile)
2343
+ this.initVideoFallback();
2344
+ }
2170
2345
  this.render();
2171
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
+ }
2172
2390
  handleClick() {
2173
- if (!screenfull$1.isEnabled)
2391
+ if (screenfull$1.isEnabled) {
2392
+ const container = (this.el.closest('.eb-player') ?? this.el);
2393
+ screenfull$1.toggle(container);
2174
2394
  return;
2175
- // Use the closest .eb-player ancestor as the fullscreen target,
2176
- // falling back to this component's own element.
2177
- // this.el is always non-null when this handler is called from a mounted button.
2178
- const container = (this.el.closest('.eb-player') ?? this.el);
2179
- screenfull$1.toggle(container);
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
+ }
2180
2416
  }
2181
2417
  template() {
2182
- if (!screenfull$1.isEnabled) {
2418
+ const canFullscreen = screenfull$1.isEnabled || this.useVideoFallback;
2419
+ if (!canFullscreen) {
2183
2420
  return b `<button class="eb-fullscreen" hidden aria-hidden="true">${icon('fullscreen')}</button>`;
2184
2421
  }
2185
2422
  const isFullscreen = this.state.isFullscreen;
@@ -3693,6 +3930,13 @@ var EBPlayerBundle = (function (exports) {
3693
3930
  */
3694
3931
  mount(container) {
3695
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$'];
3696
3940
  // Clear any stale theme/style from a previous mount cycle
3697
3941
  container.removeAttribute('data-theme');
3698
3942
  container.removeAttribute('style');
@@ -4088,6 +4332,15 @@ var EBPlayerBundle = (function (exports) {
4088
4332
  video.addEventListener('ended', () => {
4089
4333
  state.playbackState = 'ended';
4090
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 });
4091
4344
  }
4092
4345
  /**
4093
4346
  * Seek to a specific time. Default implementation sets video.currentTime.
@@ -4908,6 +5161,7 @@ var EBPlayerBundle = (function (exports) {
4908
5161
  // Private — NEVER in PlayerState (Pitfall 2)
4909
5162
  this.driver = null;
4910
5163
  this.tokenManager = null;
5164
+ this.autoQuality = true;
4911
5165
  // Holds state reference for named driver event handlers
4912
5166
  this.eventState = null;
4913
5167
  this.liveSyncDisabled = false;
@@ -4915,6 +5169,14 @@ var EBPlayerBundle = (function (exports) {
4915
5169
  getDriver() {
4916
5170
  return this.driver;
4917
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
+ }
4918
5180
  // -------------------------------------------------------------------------
4919
5181
  // BaseEngine hooks
4920
5182
  // -------------------------------------------------------------------------
@@ -4967,6 +5229,14 @@ var EBPlayerBundle = (function (exports) {
4967
5229
  if (this.driver === null)
4968
5230
  return;
4969
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
+ }
4970
5240
  }
4971
5241
  setAudioTrack(index) {
4972
5242
  if (this.driver === null)
@@ -5022,7 +5292,9 @@ var EBPlayerBundle = (function (exports) {
5022
5292
  if (!hlsjsUrl) {
5023
5293
  throw new Error('HlsEngine: config.hlsjs URL is required');
5024
5294
  }
5025
- // 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).
5026
5298
  if (config.token) {
5027
5299
  this.tokenManager = new CDNTokenManager({
5028
5300
  token: config.token,
@@ -5031,15 +5303,8 @@ var EBPlayerBundle = (function (exports) {
5031
5303
  extraParamsCallback: (config.engineSettings.extraParamsCallback ?? config.extraParamsCallback),
5032
5304
  onCDNTokenError: config.engineSettings.onCDNTokenError
5033
5305
  });
5034
- // Fetch initial token
5035
- if (config.src) {
5036
- await this.tokenManager.fetchToken({ src: config.src });
5037
- }
5038
- // Guard: abort if detached during token fetch
5039
- if (this.detached)
5040
- return;
5041
5306
  }
5042
- console.info('HlsEngine: loading hls.js from', hlsjsUrl);
5307
+ // console.info('HlsEngine: loading hls.js from', hlsjsUrl)
5043
5308
  const Hls = await loadScript(hlsjsUrl, 'Hls');
5044
5309
  // Guard: abort if detached during CDN script load
5045
5310
  if (this.detached)
@@ -5052,7 +5317,7 @@ var EBPlayerBundle = (function (exports) {
5052
5317
  // Build driver config — only spread known engineSettings keys that hls.js recognises,
5053
5318
  // not the entire engineSettings bag (which may contain player-specific keys like
5054
5319
  // extraParamsCallback that should NOT leak into the hls.js constructor config).
5055
- const { emeEnabled, drmSystems, ...hlsEngineSettings } = config.engineSettings;
5320
+ const { emeEnabled: _emeEnabled, drmSystems: _drmSystems, ...hlsEngineSettings } = config.engineSettings;
5056
5321
  // Remove player-specific keys that are NOT hls.js config options
5057
5322
  const hlsSafeSettings = { ...hlsEngineSettings };
5058
5323
  delete hlsSafeSettings['extraParamsCallback'];
@@ -5120,7 +5385,6 @@ var EBPlayerBundle = (function (exports) {
5120
5385
  // Create the driver (NEVER stored in state)
5121
5386
  const driver = new Hls(driverConfig);
5122
5387
  this.driver = driver;
5123
- this.resolveDriverReady();
5124
5388
  // Pitfall 4: apply discontinuity workaround BEFORE attachMedia/loadSource
5125
5389
  applyDiscontinuityWorkaround(driver, Hls.Events);
5126
5390
  // Wire retry handler
@@ -5143,8 +5407,27 @@ var EBPlayerBundle = (function (exports) {
5143
5407
  }
5144
5408
  }
5145
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();
5146
5414
  // Register driver event handlers
5147
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 });
5148
5431
  // Start stall watchdog
5149
5432
  this.startWatchdog();
5150
5433
  }
@@ -5196,8 +5479,12 @@ var EBPlayerBundle = (function (exports) {
5196
5479
  const state = this.eventState;
5197
5480
  if (!state)
5198
5481
  return;
5199
- const switchedData = data;
5200
- state.currentQuality = switchedData.level;
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
+ }
5201
5488
  }
5202
5489
  _onAudioTracksUpdated(_event, data) {
5203
5490
  const state = this.eventState;
@@ -5576,7 +5863,7 @@ var EBPlayerBundle = (function (exports) {
5576
5863
  };
5577
5864
  // Register with AbortSignal so it auto-removes when engine is detached
5578
5865
  window.addEventListener('unhandledrejection', this.dvrErrorHandler, { signal });
5579
- console.info('DashEngine: loading dashjs from', dashjsUrl);
5866
+ // console.info('DashEngine: loading dashjs from', dashjsUrl)
5580
5867
  const dashjs = await loadScript(dashjsUrl, 'dashjs');
5581
5868
  const player = dashjs.MediaPlayer().create();
5582
5869
  if (!player) {
@@ -5742,7 +6029,9 @@ var EBPlayerBundle = (function (exports) {
5742
6029
  this.lib.start();
5743
6030
  // Clean up on abort
5744
6031
  signal.addEventListener('abort', () => {
5745
- this.lib.stop();
6032
+ if (this.lib !== null && typeof this.lib.stop === 'function') {
6033
+ this.lib.stop();
6034
+ }
5746
6035
  this.lib = null;
5747
6036
  }, { once: true });
5748
6037
  }
@@ -5783,7 +6072,7 @@ var EBPlayerBundle = (function (exports) {
5783
6072
  init(HlsConstructor) {
5784
6073
  // Create an off-screen video element for the snapshot player
5785
6074
  const offscreenVideo = document.createElement('video');
5786
- offscreenVideo.preload = 'none';
6075
+ offscreenVideo.preload = 'metadata';
5787
6076
  this.offscreenVideo = offscreenVideo;
5788
6077
  // Capture tokenManager via closure (Pitfall 6)
5789
6078
  const tokenManager = this.tokenManager;
@@ -5814,11 +6103,17 @@ var EBPlayerBundle = (function (exports) {
5814
6103
  }
5815
6104
  PLoader = SnapshotPLoader;
5816
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'];
5817
6111
  const driverConfig = {
5818
6112
  startLevel: 0,
5819
6113
  enableWebVTT: false,
6114
+ enableWorker: false,
5820
6115
  maxBufferLength: 1,
5821
- ...(this.config.engineSettings ?? {}),
6116
+ ...rawSettings,
5822
6117
  ...(PLoader ? { pLoader: PLoader } : {})
5823
6118
  };
5824
6119
  const driver = new HlsConstructor(driverConfig);
@@ -6075,7 +6370,7 @@ var EBPlayerBundle = (function (exports) {
6075
6370
  *
6076
6371
  * Returns a PlayerReference synchronously — never returns a Promise.
6077
6372
  */
6078
- function start(runtimeConfig) {
6373
+ function start$1(runtimeConfig) {
6079
6374
  // Dispose any existing instance before creating a new one
6080
6375
  if (activeController !== null) {
6081
6376
  destroy();
@@ -6149,7 +6444,13 @@ var EBPlayerBundle = (function (exports) {
6149
6444
  else {
6150
6445
  const win = window;
6151
6446
  if (win.Hls) {
6152
- const handler = new HlsSnapshotHandler({ src, engineSettings: mergedConfig.engineSettings }, null);
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);
6153
6454
  handler.init(win.Hls)
6154
6455
  .then(() => {
6155
6456
  activeSnapshotDestroy = () => handler.destroy();
@@ -6207,9 +6508,22 @@ var EBPlayerBundle = (function (exports) {
6207
6508
  }, 100);
6208
6509
  });
6209
6510
  // Auto-open the stream if src is provided in config (matches legacy player behaviour
6210
- // 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.
6211
6514
  if (mergedConfig.src) {
6212
- reference.open(mergedConfig.src);
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
+ }
6213
6527
  }
6214
6528
  return reference;
6215
6529
  }
@@ -6238,28 +6552,55 @@ var EBPlayerBundle = (function (exports) {
6238
6552
  }
6239
6553
  }
6240
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
+ // ---------------------------------------------------------------------------
6241
6561
  // window.EBPlayer assignment
6242
6562
  // ---------------------------------------------------------------------------
6243
6563
  if (typeof window !== 'undefined') {
6244
- window.EBPlayer = { start, stop, destroy };
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 };
6245
6566
  }
6246
6567
 
6247
- var brandConfig = {"el":"#equipe_eb_player","loading":true,"start":false,"autoplay":true,"muted":false,"chromecast":false,"socialMediaList":{"facebook":"https://www.facebook.com/sharer/sharer.php?u=https://www.facebook.com/lequipe.fr/","twitter":"https://x.com/lequipe?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor","website":"https://www.lequipe.fr/"},"skin":"lequipe","isLive":true,"liveButton":true,"seekbar":true,"disableCustomAbr":true,"about":false,"template":"/Volumes/Dev-ext/dev/players/web/player-master/configs/videos/equipe/index.html","tokenType":"bunny","token":"https://secure.ctv.lequipe.eu/api/bunny-cdn/token/generate","srcInTokenRequest":true,"lib":"https://libs.easybroadcast.io/assets/js/eblib/hls1/latest/eblib.bundle.js","libSettings":"{ resourceManager: { timeoutV2V: 6000, storageSize: 300, randomWaitForPeers: [2000, 4000], enableV2V: true }, statsOutput: { enable: true, intervalMs: 30000 } }","stats":"https://stats.easybroadcast.fr","statsOrigin":"player.easybroadcast.fr"};
6568
+ var brandConfig = {"el":"#equipe_eb_player","loading":true,"start":false,"autoplay":true,"muted":false,"chromecast":false,"showProgressThumb":true,"socialMediaList":{"facebook":"https://www.facebook.com/sharer/sharer.php?u=https://www.facebook.com/lequipe.fr/","twitter":"https://x.com/lequipe?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor","website":"https://www.lequipe.fr/"},"skin":"lequipe","isLive":true,"liveButton":true,"seekbar":true,"disableCustomAbr":true,"about":false,"template":"/Volumes/Dev-ext/dev/players/web/player-master/configs/videos/equipe/index.html","tokenType":"bunny","token":"https://secure.ctv.lequipe.eu/api/bunny-cdn/token/generate","srcInTokenRequest":true,"lib":"https://libs.easybroadcast.io/assets/js/eblib/hls1/latest/eblib.bundle.js","libSettings":"{ resourceManager: { timeoutV2V: 6000, storageSize: 300, randomWaitForPeers: [2000, 4000], enableV2V: true }, statsOutput: { enable: true, intervalMs: 30000 } }","stats":"https://stats.easybroadcast.fr","statsOrigin":"player.easybroadcast.fr"};
6248
6569
 
6249
6570
  /**
6250
6571
  * Standalone entry point — used for the generated player bundle (not the npm UMD build).
6251
6572
  *
6252
6573
  * This file is resolved by Rollup with @rollup/plugin-virtual injecting the brand config
6253
- * from 'virtual:brand-config' at build time. The merged config is passed to start()
6254
- * automatically if config.start is truthy (the default).
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.
6255
6579
  *
6256
6580
  * Import chain:
6257
6581
  * eb-player-standalone.ts → eb-player.ts (facade) + virtual:brand-config (brand config)
6258
6582
  */
6259
- const mergedConfig = mergeConfig(DEFAULT_CONFIG, brandConfig);
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
+ }
6260
6600
  // Auto-start if config.start is truthy (mirrors legacy generator/generate.js behaviour).
6261
6601
  // Skip auto-start when the target container doesn't exist — this means the bundle is
6262
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);
6263
6604
  if (mergedConfig.start) {
6264
6605
  const el = mergedConfig.el;
6265
6606
  const containerExists = typeof el === 'string'