saltfish 0.3.91 → 0.3.93

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,6 @@
1
1
  /*!
2
- * Saltfish playlist Player v0.3.91
2
+ * Saltfish playlist Player v0.3.93
3
3
  * (c) 2026
4
4
  * Released under the MIT License.
5
5
  */
6
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).SaltfishplaylistPlayer=e()}(this,(function(){"use strict";var t=Object.defineProperty,e=(e,n,i)=>((e,n,i)=>n in e?t(e,n,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[n]=i)(e,"symbol"!=typeof n?n+"":n,i);const n={};var i=Symbol.for("immer-nothing"),s=Symbol.for("immer-draftable"),r=Symbol.for("immer-state");function a(t,...e){throw new Error(`[Immer] minified error nr: ${t}. Full error at: https://bit.ly/3cXEKWf`)}var o=Object.getPrototypeOf;function l(t){return!!t&&!!t[r]}function c(t){var e;return!!t&&(h(t)||Array.isArray(t)||!!t[s]||!!(null==(e=t.constructor)?void 0:e[s])||f(t)||y(t))}var d=Object.prototype.constructor.toString();function h(t){if(!t||"object"!=typeof t)return!1;const e=o(t);if(null===e)return!0;const n=Object.hasOwnProperty.call(e,"constructor")&&e.constructor;return n===Object||"function"==typeof n&&Function.toString.call(n)===d}function u(t,e){0===p(t)?Reflect.ownKeys(t).forEach((n=>{e(n,t[n],t)})):t.forEach(((n,i)=>e(i,n,t)))}function p(t){const e=t[r];return e?e.type_:Array.isArray(t)?1:f(t)?2:y(t)?3:0}function g(t,e){return 2===p(t)?t.has(e):Object.prototype.hasOwnProperty.call(t,e)}function m(t,e,n){const i=p(t);2===i?t.set(e,n):3===i?t.add(n):t[e]=n}function f(t){return t instanceof Map}function y(t){return t instanceof Set}function v(t){return t.copy_||t.base_}function b(t,e){if(f(t))return new Map(t);if(y(t))return new Set(t);if(Array.isArray(t))return Array.prototype.slice.call(t);const n=h(t);if(!0===e||"class_only"===e&&!n){const e=Object.getOwnPropertyDescriptors(t);delete e[r];let n=Reflect.ownKeys(e);for(let i=0;i<n.length;i++){const s=n[i],r=e[s];!1===r.writable&&(r.writable=!0,r.configurable=!0),(r.get||r.set)&&(e[s]={configurable:!0,writable:!0,enumerable:r.enumerable,value:t[s]})}return Object.create(o(t),e)}{const e=o(t);if(null!==e&&n)return{...t};const i=Object.create(e);return Object.assign(i,t)}}function w(t,e=!1){return E(t)||l(t)||!c(t)||(p(t)>1&&(t.set=t.add=t.clear=t.delete=S),Object.freeze(t),e&&Object.entries(t).forEach((([t,e])=>w(e,!0)))),t}function S(){a(2)}function E(t){return Object.isFrozen(t)}var M,x={};function I(t){const e=x[t];return e||a(0),e}function P(){return M}function C(t,e){e&&(I("Patches"),t.patches_=[],t.inversePatches_=[],t.patchListener_=e)}function _(t){k(t),t.drafts_.forEach(A),t.drafts_=null}function k(t){t===M&&(M=t.parent_)}function T(t){return M={drafts_:[],parent_:M,immer_:t,canAutoFreeze_:!0,unfinalizedDrafts_:0}}function A(t){const e=t[r];0===e.type_||1===e.type_?e.revoke_():e.revoked_=!0}function z(t,e){e.unfinalizedDrafts_=e.drafts_.length;const n=e.drafts_[0];return void 0!==t&&t!==n?(n[r].modified_&&(_(e),a(4)),c(t)&&(t=L(e,t),e.parent_||O(e,t)),e.patches_&&I("Patches").generateReplacementPatches_(n[r].base_,t,e.patches_,e.inversePatches_)):t=L(e,n,[]),_(e),e.patches_&&e.patchListener_(e.patches_,e.inversePatches_),t!==i?t:void 0}function L(t,e,n){if(E(e))return e;const i=e[r];if(!i)return u(e,((s,r)=>V(t,i,e,s,r,n))),e;if(i.scope_!==t)return e;if(!i.modified_)return O(t,i.base_,!0),i.base_;if(!i.finalized_){i.finalized_=!0,i.scope_.unfinalizedDrafts_--;const e=i.copy_;let s=e,r=!1;3===i.type_&&(s=new Set(e),e.clear(),r=!0),u(s,((s,a)=>V(t,i,e,s,a,n,r))),O(t,e,!1),n&&t.patches_&&I("Patches").generatePatches_(i,n,t.patches_,t.inversePatches_)}return i.copy_}function V(t,e,n,i,s,r,a){if(l(s)){const a=L(t,s,r&&e&&3!==e.type_&&!g(e.assigned_,i)?r.concat(i):void 0);if(m(n,i,a),!l(a))return;t.canAutoFreeze_=!1}else a&&n.add(s);if(c(s)&&!E(s)){if(!t.immer_.autoFreeze_&&t.unfinalizedDrafts_<1)return;L(t,s),e&&e.scope_.parent_||"symbol"==typeof i||!Object.prototype.propertyIsEnumerable.call(n,i)||O(t,s)}}function O(t,e,n=!1){!t.parent_&&t.immer_.autoFreeze_&&t.canAutoFreeze_&&w(e,n)}var D={get(t,e){if(e===r)return t;const n=v(t);if(!g(n,e))return function(t,e,n){var i;const s=B(e,n);return s?"value"in s?s.value:null==(i=s.get)?void 0:i.call(t.draft_):void 0}(t,n,e);const i=n[e];return t.finalized_||!c(i)?i:i===U(t.base_,e)?(R(t),t.copy_[e]=H(i,t)):i},has:(t,e)=>e in v(t),ownKeys:t=>Reflect.ownKeys(v(t)),set(t,e,n){const i=B(v(t),e);if(null==i?void 0:i.set)return i.set.call(t.draft_,n),!0;if(!t.modified_){const i=U(v(t),e),o=null==i?void 0:i[r];if(o&&o.base_===n)return t.copy_[e]=n,t.assigned_[e]=!1,!0;if(((s=n)===(a=i)?0!==s||1/s==1/a:s!=s&&a!=a)&&(void 0!==n||g(t.base_,e)))return!0;R(t),N(t)}var s,a;return t.copy_[e]===n&&(void 0!==n||e in t.copy_)||Number.isNaN(n)&&Number.isNaN(t.copy_[e])||(t.copy_[e]=n,t.assigned_[e]=!0),!0},deleteProperty:(t,e)=>(void 0!==U(t.base_,e)||e in t.base_?(t.assigned_[e]=!1,R(t),N(t)):delete t.assigned_[e],t.copy_&&delete t.copy_[e],!0),getOwnPropertyDescriptor(t,e){const n=v(t),i=Reflect.getOwnPropertyDescriptor(n,e);return i?{writable:!0,configurable:1!==t.type_||"length"!==e,enumerable:i.enumerable,value:n[e]}:i},defineProperty(){a(11)},getPrototypeOf:t=>o(t.base_),setPrototypeOf(){a(12)}},F={};function U(t,e){const n=t[r];return(n?v(n):t)[e]}function B(t,e){if(!(e in t))return;let n=o(t);for(;n;){const t=Object.getOwnPropertyDescriptor(n,e);if(t)return t;n=o(n)}}function N(t){t.modified_||(t.modified_=!0,t.parent_&&N(t.parent_))}function R(t){t.copy_||(t.copy_=b(t.base_,t.scope_.immer_.useStrictShallowCopy_))}function H(t,e){const n=f(t)?I("MapSet").proxyMap_(t,e):y(t)?I("MapSet").proxySet_(t,e):function(t,e){const n=Array.isArray(t),i={type_:n?1:0,scope_:e?e.scope_:P(),modified_:!1,finalized_:!1,assigned_:{},parent_:e,base_:t,draft_:null,copy_:null,revoke_:null,isManual_:!1};let s=i,r=D;n&&(s=[i],r=F);const{revoke:a,proxy:o}=Proxy.revocable(s,r);return i.draft_=o,i.revoke_=a,o}(t,e);return(e?e.scope_:P()).drafts_.push(n),n}function $(t){if(!c(t)||E(t))return t;const e=t[r];let n;if(e){if(!e.modified_)return e.base_;e.finalized_=!0,n=b(t,e.scope_.immer_.useStrictShallowCopy_)}else n=b(t,!0);return u(n,((t,e)=>{m(n,t,$(e))})),e&&(e.finalized_=!1),n}u(D,((t,e)=>{F[t]=function(){return arguments[0]=arguments[0][0],e.apply(this,arguments)}})),F.deleteProperty=function(t,e){return F.set.call(this,t,e,void 0)},F.set=function(t,e,n){return D.set.call(this,t[0],e,n,t[0])};var Y=new class{constructor(t){this.autoFreeze_=!0,this.useStrictShallowCopy_=!1,this.produce=(t,e,n)=>{if("function"==typeof t&&"function"!=typeof e){const n=e;e=t;const i=this;return function(t=n,...s){return i.produce(t,(t=>e.call(this,t,...s)))}}let s;if("function"!=typeof e&&a(6),void 0!==n&&"function"!=typeof n&&a(7),c(t)){const i=T(this),r=H(t,void 0);let a=!0;try{s=e(r),a=!1}finally{a?_(i):k(i)}return C(i,n),z(s,i)}if(!t||"object"!=typeof t){if(s=e(t),void 0===s&&(s=t),s===i&&(s=void 0),this.autoFreeze_&&w(s,!0),n){const e=[],i=[];I("Patches").generateReplacementPatches_(t,s,e,i),n(e,i)}return s}a(1)},this.produceWithPatches=(t,e)=>{if("function"==typeof t)return(e,...n)=>this.produceWithPatches(e,(e=>t(e,...n)));let n,i;return[this.produce(t,e,((t,e)=>{n=t,i=e})),n,i]},"boolean"==typeof(null==t?void 0:t.autoFreeze)&&this.setAutoFreeze(t.autoFreeze),"boolean"==typeof(null==t?void 0:t.useStrictShallowCopy)&&this.setUseStrictShallowCopy(t.useStrictShallowCopy)}createDraft(t){c(t)||a(8),l(t)&&(t=function(t){return l(t)||a(10),$(t)}(t));const e=T(this),n=H(t,void 0);return n[r].isManual_=!0,k(e),n}finishDraft(t,e){const n=t&&t[r];n&&n.isManual_||a(9);const{scope_:i}=n;return C(i,e),z(void 0,i)}setAutoFreeze(t){this.autoFreeze_=t}setUseStrictShallowCopy(t){this.useStrictShallowCopy_=t}applyPatches(t,e){let n;for(n=e.length-1;n>=0;n--){const i=e[n];if(0===i.path.length&&"replace"===i.op){t=i.value;break}}n>-1&&(e=e.slice(n+1));const i=I("Patches").applyPatches_;return l(t)?i(t,e):this.produce(t,(t=>i(t,e)))}},X=Y.produce;Y.produceWithPatches.bind(Y),Y.setAutoFreeze.bind(Y),Y.setUseStrictShallowCopy.bind(Y),Y.applyPatches.bind(Y),Y.createDraft.bind(Y),Y.finishDraft.bind(Y);function j(t,e){void 0!==e?console.info(t,e):console.info(t)}function W(t,e){console.warn(t)}function q(t,e){void 0!==e?console.error(t,e):console.error(t)}class Z{constructor(t,n){e(this,"currentState"),e(this,"config"),e(this,"context"),e(this,"actionHandlers",{}),this.config=t,this.currentState=t.initial,this.context=n,this.runEntryActions(this.currentState)}registerActions(t){this.actionHandlers={...this.actionHandlers,...t},Object.keys(t).join(", ")}executeAction(t,e){if("string"==typeof t){const n=this.actionHandlers[t];n&&n(this.context,e)}else t(this.context,e)}send(t){const e=this.config.states[this.currentState].on[t.type];return e?(this.currentState,e.target,t.type,this.runExitActions(this.currentState),this.updateContextFromEvent(t),e.actions&&e.actions.forEach((e=>this.executeAction(e,t))),this.currentState,this.currentState=e.target,this.runEntryActions(this.currentState),this.currentState,this.currentState):(t.type,this.currentState,this.currentState)}updateContextFromEvent(t){"TRANSITION_TO_STEP"===t.type||"MANIFEST_LOADED"===t.type||"VIDEO_FINISHED_WAIT"===t.type?this.context.currentStep=t.step:"ERROR"===t.type&&(this.context.error=t.error)}getState(){return this.currentState}getContext(){return this.context}updateContext(t){const e=t(this.context);this.context={...this.context,...e}}runEntryActions(t){const e=this.config.states[t];e.entry&&e.entry.forEach((t=>this.executeAction(t)))}runExitActions(t){const e=this.config.states[t];e.exit&&e.exit.forEach((t=>this.executeAction(t)))}}const G={initial:"idle",states:{idle:{on:{INITIALIZE:{target:"idle"},LOAD_MANIFEST:{target:"loading"}}},loading:{on:{MANIFEST_LOADED:{target:"paused"},ERROR:{target:"error"}},entry:["showLoadingState"],exit:["hideLoadingState"]},playing:{on:{PAUSE:{target:"paused"},MINIMIZE:{target:"minimized"},VIDEO_FINISHED_WAIT:{target:"waitingForInteraction"},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"},TRANSITION_TO_STEP:{target:"playing"},ERROR:{target:"error"},COMPLETE_PLAYLIST:{target:"completed"},COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION:{target:"completedWaitingForInteraction"}},entry:["startVideoPlayback","showVideoControls","hidePlayButton"],exit:["pauseVideoPlayback"]},paused:{on:{PLAY:{target:"playing"},START_IDLE_MODE:{target:"idleMode"},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"},MINIMIZE:{target:"minimized"},TRANSITION_TO_STEP:{target:"playing"}},entry:["pauseVideoPlayback","showPlayButton"]},minimized:{on:{MAXIMIZE:{target:"playing"},EXIT:{target:"closing"}},entry:["pauseVideoPlayback"]},waitingForInteraction:{on:{PLAY:{target:"playing"},PAUSE:{target:"paused"},MINIMIZE:{target:"minimized"},COMPLETE_PLAYLIST:{target:"completed"},COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION:{target:"completedWaitingForInteraction"},TRANSITION_TO_STEP:{target:"playing"}},entry:["showPlayButton"]},autoplayBlocked:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["enterCompactMode","startMutedLoopedVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls","exitCompactMode"]},idleMode:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["startIdleModeVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls","exitCompactMode"]},error:{on:{INITIALIZE:{target:"idle"},PLAY:{target:"playing"},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"}},entry:["handleError","showPlayButton"],exit:["hideError"]},completedWaitingForInteraction:{on:{COMPLETE_PLAYLIST:{target:"completed"},INITIALIZE:{target:"idle"},TRANSITION_TO_STEP:{target:"playing"},PLAY:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["showPlayButton"]},completed:{on:{INITIALIZE:{target:"idle"}},entry:["trackPlaylistComplete"]},closing:{on:{},entry:["triggerPlaylistDismissed"]}}},K="saltfish_progress",J="saltfish_session",Q="saltfish_anonymous_user_data",tt="saltfish_pending_navigation",et="sf-player--minimized",nt="sf-error-display--visible",it="sf-error-display__message",st=class t{constructor(){e(this,"isLocalStorageAvailable"),this.isLocalStorageAvailable=this.checkLocalStorageAvailability(),this.isLocalStorageAvailable}static getInstance(){return t.instance||(t.instance=new t),t.instance}static resetInstance(){t.instance=null}checkLocalStorageAvailability(){if("undefined"==typeof window)return!1;try{const t="__storage_test__";return localStorage.setItem(t,"test"),localStorage.removeItem(t),!0}catch(t){return!1}}safeGetItem(t){if(!this.isLocalStorageAvailable)return null;try{const e=localStorage.getItem(t);return null===e?null:JSON.parse(e)}catch(e){return this.safeClearItem(t),null}}safeSetItem(t,e){if(!this.isLocalStorageAvailable)return!1;try{return localStorage.setItem(t,JSON.stringify(e)),!0}catch(n){if(n instanceof DOMException&&22===n.code){this.clearOldData();try{return localStorage.setItem(t,JSON.stringify(e)),!0}catch(t){}}return!1}}safeClearItem(t){if(this.isLocalStorageAvailable)try{localStorage.removeItem(t)}catch(t){}}clearOldData(){this.safeClearItem(J)}getProgress(t){const e=this.safeGetItem(K);return e?t&&e.userId&&e.userId!==t?(e.userId,null):e.playlists||null:null}setProgress(t,e){const n={userId:e,playlists:t};return this.safeSetItem(K,n)}clearProgress(){this.safeClearItem(K)}getSession(){return this.safeGetItem(J)}setSession(t){return this.safeSetItem(J,t)}clearSession(){this.safeClearItem(J)}getAnonymousUserData(){return this.safeGetItem(Q)}setAnonymousUserData(t){return this.safeSetItem(Q,t)}clearAnonymousUserData(){this.safeClearItem(Q)}getPendingNavigation(){return this.safeGetItem(tt)}setPendingNavigation(t){return t.nextStepId,t.urlPattern,this.safeSetItem(tt,t)}clearPendingNavigation(){this.safeClearItem(tt)}clearAll(){this.clearProgress(),this.clearSession(),this.clearAnonymousUserData(),this.clearPendingNavigation()}};e(st,"instance",null);let rt=st;const at=rt.getInstance(),ot=(t=>{let e;const i=new Set,s=(t,n)=>{const s="function"==typeof t?t(e):t;if(!Object.is(s,e)){const t=e;e=(null!=n?n:"object"!=typeof s||null===s)?s:Object.assign({},e,s),i.forEach((n=>n(e,t)))}},r=()=>e,a={setState:s,getState:r,getInitialState:()=>o,subscribe:t=>(i.add(t),()=>i.delete(t)),destroy:()=>{"production"!==(n?"production":void 0)&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),i.clear()}},o=e=t(s,r,a);return a})((t=>(e,n,i)=>(i.setState=(t,n,...i)=>{const s="function"==typeof t?X(t):t;return e(s,n,...i)},t(i.setState,n,i)))(((t,e)=>{let n=new Z(G,{currentStep:null,error:null});const i=t=>n.send(t),s=e=>{const i=n.send(e);return t((t=>{t.currentState=i})),i};return{config:null,user:null,userData:null,currentState:n.getState(),manifest:null,currentStepId:null,isMinimized:!1,position:null,progress:{},error:null,playlistOptions:null,backendPlaylists:[],isAdmin:!1,isMuted:!1,abTests:[],abTestAssignments:{},initialize:async e=>{t((t=>{t.config=e,t.currentState=i({type:"INITIALIZE"})}))},setPlaylistOptions:e=>{t((t=>{if(t.playlistOptions=e,e.position){const n="bottom-left"===e.position||"bottom-right"===e.position?e.position:"bottom-right";t.position={x:0,y:0},t.playlistOptions={...e,position:n}}}))},identifyUser:(e,n)=>{const i={id:e,...n};t((t=>{t.user=i}))},mergeUserFields:e=>{t((t=>{t.user&&Object.assign(t.user,e)}))},setUserData:e=>{t((t=>{var n;const i=(null==e?void 0:e.watchedPlaylists)||{},s=(null==(n=t.userData)?void 0:n.watchedPlaylists)||{},r={...i};for(const[t,e]of Object.entries(s)){if(!e)continue;const n=r[t],i="completed"===e.status||"dismissed"===e.status,s=!!n&&("completed"===n.status||"dismissed"===n.status);if(i&&!s)r[t]=e,e.status,null==n||n.status;else if(n){const i=Math.max(e.visitCount??0,n.visitCount??0);(n.visitCount??0)!==i&&(r[t]={...n,visitCount:i})}}t.userData={...e,watchedPlaylists:r}}))},updateWatchedPlaylist:(e,n,i)=>{t((t=>{t.userData||(t.userData={watchedPlaylists:{}}),t.userData.watchedPlaylists||(t.userData.watchedPlaylists={});const s=t.userData.watchedPlaylists[e],r=null==s?void 0:s.status,a=(null==s?void 0:s.visitCount)??0,o=("completed"===n||"dismissed"===n)&&r!==n,l=Date.now();t.userData.watchedPlaylists[e]={status:n,currentStepId:"completed"===n?null:i??t.currentStepId??null,timestamp:l,lastProgressAt:l,visitCount:o?a+1:a}}))},setManifest:(e,n)=>{t((t=>{t.manifest=e,t.currentStepId=n;const s=e.steps.find((t=>t.id===n));t.currentState=i(s?{type:"MANIFEST_LOADED",step:s}:{type:"ERROR",error:new Error(`Start step '${n}' not found in manifest`)})}))},play:()=>{const{currentState:n}=e();t((t=>{t.currentState=i({type:"PLAY"})}))},pause:()=>{const{currentState:n}=e();t((t=>{t.currentState=i({type:"PAUSE"})}))},minimize:()=>{const{currentState:n}=e();t((t=>{"playing"===t.currentState&&(t.currentState=i({type:"PAUSE"})),t.currentState=i({type:"MINIMIZE"}),t.isMinimized=!0}))},maximize:()=>{t((t=>{t.currentState=i({type:"MAXIMIZE"}),t.isMinimized=!1}))},goToStep:n=>{const{manifest:r}=e();if("completed"!==n){if(r&&r.steps.some((t=>t.id===n))){const e=r.steps.find((t=>t.id===n));t((t=>{var s,a,o;if(t.currentStepId=n,e&&(t.currentState=i({type:"TRANSITION_TO_STEP",step:e}),(t.position||(null==(s=t.playlistOptions)?void 0:s.position))&&(t.position={x:0,y:0})),t.progress[r.id]={...t.progress[r.id],lastStepId:n,lastVisited:(new Date).toISOString()},(null==(a=t.playlistOptions)?void 0:a.persistence)??1){const e=null==(o=t.user)?void 0:o.id;at.setProgress(t.progress,e)}}))}}else s({type:"COMPLETE_PLAYLIST"})},reset:()=>{t((t=>{t.config=null,t.user=null,t.userData=null,t.currentState=n.getState(),t.manifest=null,t.currentStepId=null,t.isMinimized=!1,t.position=null,t.progress={},t.error=null,n=new Z(G,{currentStep:null,error:null})}))},setError:e=>{t((t=>{t.currentState=i({type:"ERROR",error:e}),t.error=e}))},setAutoplayFallback:()=>{t((t=>{t.currentState=i({type:"AUTOPLAY_FALLBACK"})}))},setIdleMode:()=>{t((t=>{t.currentState=i({type:"START_IDLE_MODE"})}))},setMuted:e=>{t((t=>{t.isMuted=e}))},setBackendPlaylists:e=>{t((t=>{t.backendPlaylists=e}))},setIsAdmin:e=>{t((t=>{t.isAdmin=e}))},completePlaylist:()=>{s({type:"COMPLETE_PLAYLIST"})},resetForNewPlaylist:()=>{t((t=>{const e=t.config,i=t.user,s=t.userData,r=t.progress;t.manifest=null,t.currentStepId=null,t.isMinimized=!1,t.position=null,t.error=null,t.playlistOptions=null,n=new Z(G,{currentStep:null,error:null}),t.currentState=n.getState(),t.config=e,t.user=i,t.userData=s,t.progress=r}))},loadPlaylistProgress:(e,n)=>{t((t=>{t.progress[e]=n}))},registerStateMachineActions:t=>{n.registerActions(t)},sendStateMachineEvent:t=>{s(t)},updateProgressWithCompletion:(e,n)=>{t((t=>{var s,r;if(t.currentState=i({type:"COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION"}),t.progress[e]={...t.progress[e],lastStepId:n,lastVisited:(new Date).toISOString(),completedWaitingForInteraction:!0},(null==(s=t.playlistOptions)?void 0:s.persistence)??1){const e=null==(r=t.user)?void 0:r.id;at.setProgress(t.progress,e)}}))},setABTests:e=>{t((t=>{t.abTests=e}))},setABTestAssignments:e=>{t((t=>{t.abTestAssignments=e}))},getFilteredPlaylists:()=>{const t=e(),n=t.backendPlaylists||[],i=t.abTests||[],s=t.abTestAssignments||{};if(0===i.length)return n;const r=new Set;for(const t of i){const e=s[t.id];e&&e.assigned||r.add(t.playlistId)}return n.filter((t=>!r.has(t.id)))}}}))),lt={getState:()=>ot.getState(),setState:ot.setState,subscribe:ot.subscribe,destroy:ot.destroy};function ct(){try{return lt.getState()}catch(t){throw new Error(`[storeUtils] Failed to access Saltfish store: ${t}`)}}function dt(t){if(!t)return null;if(t.lastProgressAt&&"object"==typeof t.lastProgressAt&&"_seconds"in t.lastProgressAt&&"_nanoseconds"in t.lastProgressAt){const e=t.lastProgressAt;return 1e3*e._seconds+Math.floor(e._nanoseconds/1e6)}return t.timestamp&&"number"==typeof t.timestamp?t.timestamp:t.lastProgressAt&&"number"==typeof t.lastProgressAt?t.lastProgressAt:null}function ht(t,e=6e3){const n=dt(t);if(!n)return{isValid:!1,ageMs:null,timestampMs:null};const i=Date.now()-n;return{isValid:i<=e,ageMs:i,timestampMs:n}}class ut{static handle(t,e={},n={}){var i;const s={...this.DEFAULT_OPTIONS,...n},r=this.normalizeError(t,e);if(s.shouldLog&&this.logError(r,e,s.severity),s.shouldUpdateStore&&this.updateStore(r),s.shouldTriggerEvent&&this.triggerErrorEvent(r,e,null==(i=e.component)?void 0:i.toLowerCase()),s.shouldDestroy&&this.destroyPlayer(),s.shouldThrow)throw r;return r}static handleInitializationError(t,e={}){return this.handle(t,{...e,component:"Initialization"},{severity:"critical",shouldLog:!0,shouldUpdateStore:!0,shouldDestroy:!0,shouldThrow:!0})}static handlePlaylistError(t,e={}){return this.handle(t,{...e,component:"Playlist"},{severity:"error",shouldLog:!0,shouldUpdateStore:!0,shouldTriggerEvent:!0})}static handleVideoError(t,e={}){return this.handle(t,{...e,component:"Video"},{severity:"error",shouldLog:!0,shouldUpdateStore:!0,shouldTriggerEvent:!0})}static handleNetworkError(t,e={}){return this.handle(t,{...e,component:"Network"},{severity:"warning",shouldLog:!0,shouldTriggerEvent:!0})}static handleWarning(t,e={}){return this.handle(t,e,{severity:"warning",shouldLog:!0,shouldThrow:!1})}static handleCleanupError(t,e={}){return this.handle(t,{...e,component:"Cleanup"},{severity:"warning",shouldLog:!0,shouldThrow:!1})}static normalizeError(t,e){if(t instanceof Error)return t;if("string"==typeof t)return new Error(t);const n=String(t&&"object"==typeof t&&"message"in t?t.message:t);return new Error(`Unknown error in ${e.component||"application"}: ${n}`)}static formatErrorMessage(t,e){const n=[];return e.component&&n.push(`[${e.component}]`),e.method&&n.push(`${e.method}:`),n.push(t.message),n.join(" ")}static logError(t,e,n){const i=this.formatErrorMessage(t,e),s={error:{name:t.name,message:t.message,stack:t.stack},context:e,severity:n,timestamp:(new Date).toISOString()};switch(n){case"info":break;case"warning":console.warn(i,s);break;case"error":case"critical":console.error(i,s)}}static updateStore(t){try{ct().setError(t)}catch(t){console.error("Failed to update store with error:",t)}}static triggerErrorEvent(t,e,n){var i,s;try{const r=ct();if("undefined"!=typeof window&&window._saltfishPlayer){const a=window._saltfishPlayer;a&&a.eventManager&&a.eventManager.trigger("error",{timestamp:Date.now(),playlistId:e.playlistId||(null==(i=r.manifest)?void 0:i.id),stepId:e.stepId||r.currentStepId,error:t,errorType:e.errorType||n||(null==(s=e.component)?void 0:s.toLowerCase())||"unknown"})}}catch(t){console.error("Failed to trigger error event:",t)}}static destroyPlayer(){try{if("undefined"!=typeof window&&window._saltfishPlayer){const t=window._saltfishPlayer;t&&"function"==typeof t.destroy&&t.destroy()}}catch(t){console.error("Failed to destroy player during error handling:",t)}}static createError(t,e={}){const n=new Error(this.formatErrorMessage(new Error(t),e));return e.component&&(n.component=e.component),e.method&&(n.method=e.method),e.playlistId&&(n.playlistId=e.playlistId),e.stepId&&(n.stepId=e.stepId),n}static isRecoverable(t){return!!(t.message.includes("fetch")||t.message.includes("network")||t.message.includes("timeout"))||[/autoplay.*blocked/i,/video.*failed.*load/i,/manifest.*not.*found/i].some((e=>e.test(t.message)))}static async safeExecute(t,e={},n={}){try{return await t()}catch(t){return this.handle(t,e,n),null}}}e(ut,"DEFAULT_OPTIONS",{severity:"error",shouldLog:!0,shouldThrow:!1,shouldUpdateStore:!1,shouldTriggerEvent:!1,shouldDestroy:!1});class pt{detectShareIdFromUrl(){try{const t=window.location.href,e=/saltfish-share-id=([^&#]*)/,n=t.match(e);if(n&&n[1]){return n[1]}return null}catch(t){return null}}async fetchShareData(t){try{const e=await fetch(`https://studio-api.saltfish.ai/studio/flows2/share/${t}`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error(`Share API returned status ${e.status}`);const n=await e.json();if(!n.flowId)throw new Error("Share API response missing flowId");return n.shareId,n.flowId,n.createdBy,n}catch(e){throw ut.handleInitializationError(e,{component:"ShareLinkService",method:"fetchShareData",additionalData:{shareId:t}})}}async shouldAutoStartSharePlaylist(){try{const t=this.detectShareIdFromUrl();if(!t)return null;const e=await this.fetchShareData(t);return e.flowId,e.isGlobal,e}catch(t){return null}}}const gt=100;function mt(t){try{let e=t.replace(/[?&]saltfish-share-id=[^&#]*/g,((e,n)=>e.startsWith("?")&&t.substring(n+e.length).startsWith("&")?"?":""));return e=e.replace(/\?&/g,"?"),e=e.replace(/&&/g,"&"),e=e.replace(/\?$/g,""),e=e.replace(/&$/g,""),e}catch(e){return t}}function ft(t){const{pattern:e,matchType:n}=t;if(!e)return!0;const i=mt(window.location.href),s=window.location.pathname;if("regex"===n)try{const t=new RegExp(e),n=t.test(i),r=t.test(s);return n||r}catch(t){return!1}return"contains"===n?i.includes(e)||s.includes(e):i===e||s===e}class yt{constructor(t){e(this,"managers"),e(this,"userManagementService"),e(this,"playlistOrchestrator"),e(this,"shareLinkService"),e(this,"lastConfig",null),e(this,"boundVisibilityHandler",null),e(this,"lastUserDataFetchTimestamp",0),e(this,"currentUserId",null),e(this,"currentUserData"),e(this,"isAnonymousUser",!1),this.managers=t,this.shareLinkService=new pt}setUserManagementService(t){this.userManagementService=t}setPlaylistOrchestrator(t){this.playlistOrchestrator=t}getLastConfig(){return this.lastConfig}async initialize(t){var e;try{const n=await fetch("https://player.saltfish.ai/validate-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t.token,playerVersion:"0.3.81"})}),i=await n.json();if(!i.isValid)throw ut.handleInitializationError(i.error||"Token validation failed",{component:"PlayerInitializationService",method:"initialize",additionalData:{token:(null==(e=t.token)?void 0:e.substring(0,10))+"..."}});const s={...t,showLogo:!1!==i.showLogo};this.lastConfig=s;const r=ct();if(r.initialize(s),this.managers.analyticsManager.initialize(t,this.managers.sessionManager.getSessionId()),i.isAdmin&&r.setIsAdmin&&r.setIsAdmin(!0),i.playlists&&Array.isArray(i.playlists)&&r.setBackendPlaylists)i.playlists,r.setBackendPlaylists(i.playlists),i.playlists.length>0?this.managers.triggerManager.registerTriggers(i.playlists):i.isAdmin,i.abTests&&Array.isArray(i.abTests)&&(i.abTests,this.managers.abTestManager.initializeTests(i.abTests));else if(!i.isAdmin)throw ut.handleInitializationError("Backend validation successful, but no playlists array provided in the response. Cannot initialize player.",{component:"PlayerInitializationService",method:"initialize",additionalData:{responseData:i}});this.managers.eventManager.trigger("initialized",{timestamp:Date.now()})}catch(t){throw ut.handleInitializationError(t,{component:"PlayerInitializationService",method:"initialize"})}}async fetchUserData(t,e){var n;try{const i=ct();if(!(null==(n=i.config)?void 0:n.token))return void ut.handleWarning("Cannot fetch user data: Token not available",{component:"PlayerInitializationService",method:"fetchUserData",userId:t});const s=await fetch(`https://player.saltfish.ai/clients/${i.config.token}/users/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userData:e})});if(!s.ok)return await s.text(),s.status,void s.statusText;const r=await s.json();if(r.success){this.currentUserId=t,this.currentUserData=e,this.isAnonymousUser=!1,this.lastUserDataFetchTimestamp=Date.now(),r.firstIdentifiedAt&&i.mergeUserFields({firstIdentifiedAt:r.firstIdentifiedAt}),i.setUserData({watchedPlaylists:r.watchedPlaylists||{},language:r.language});const n=r.userListAssignments||{},s=r.abTestAssignments||{};this.managers.abTestManager.assignUserToTests(t,s,n),this.setupVisibilityChangeListener(),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:r.watchedPlaylists||{}}}),this.userManagementService&&this.userManagementService.resolveUserDataLoaded();if(!await this.checkAndResumeFromPendingNavigation()&&!await this.checkAndResumeInProgressPlaylist(r.watchedPlaylists||{})){const t=await this.shareLinkService.shouldAutoStartSharePlaylist();t&&this.playlistOrchestrator?(t.flowId,await this.playlistOrchestrator.startPlaylist(t.flowId,{once:!1,position:"bottom-right",_startedFromShareLink:!0,_isGlobalShare:t.isGlobal})):this.managers.triggerManager.startMonitoring()}}else this.userManagementService&&this.userManagementService.resolveUserDataLoaded()}catch(e){ut.handleNetworkError(e,{component:"PlayerInitializationService",method:"fetchUserData",userId:t}),this.userManagementService&&this.userManagementService.resolveUserDataLoaded()}}async loadAnonymousUserData(t,e){try{if("undefined"==typeof window)return;const n=this.managers.abTestManager.assignUserToTests(t,void 0,{}),i=this.managers.storageManager.getAnonymousUserData();let s={userId:t,userData:e||{},watchedPlaylists:{},abTestAssignments:n,timestamp:Date.now()};if(i){const n=i.abTestAssignments||{},r=this.managers.abTestManager.assignUserToTests(t,n);s={userId:t,userData:{...i.userData,...e},watchedPlaylists:i.watchedPlaylists||{},abTestAssignments:r,timestamp:Date.now()}}this.managers.storageManager.setAnonymousUserData(s),this.currentUserId=t,this.currentUserData=e,this.isAnonymousUser=!0,this.lastUserDataFetchTimestamp=Date.now(),ct().setUserData({watchedPlaylists:s.watchedPlaylists||{},language:null==e?void 0:e.language}),this.setupVisibilityChangeListener(),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:s.watchedPlaylists||{}}});const r=await this.checkAndResumeFromPendingNavigation(),a=s.watchedPlaylists||{};if(!r&&!await this.checkAndResumeInProgressPlaylist(a)){const t=await this.shareLinkService.shouldAutoStartSharePlaylist();t&&this.playlistOrchestrator?(t.flowId,await this.playlistOrchestrator.startPlaylist(t.flowId,{once:!1,position:"bottom-right",_startedFromShareLink:!0,_isGlobalShare:t.isGlobal})):this.managers.triggerManager.startMonitoring()}}catch(e){ut.handleNetworkError(e,{component:"PlayerInitializationService",method:"loadAnonymousUserData",userId:t})}}async checkAndResumeInProgressPlaylist(t){var e;if(!t)return!1;const n=ct(),i=null==(e=n.manifest)?void 0:e.id,s=n.currentState;if(i&&"idle"!==s&&"error"!==s)return!1;const r=Object.entries(t).find((([t,e])=>{if("in_progress"!==(null==e?void 0:e.status))return!1;const{isValid:n,ageMs:i}=ht(e);return!!n}));if(r){const[t,e]=r;dt(e);try{if(this.playlistOrchestrator)return await this.playlistOrchestrator.startPlaylist(t),!0}catch(t){return!1}}return!1}async checkAndResumeFromPendingNavigation(){const t=this.managers.storageManager.getPendingNavigation();if(!t)return!1;if(Date.now()-t.timestamp>6e4)return this.managers.storageManager.clearPendingNavigation(),!1;if(!this.isURLPathMatch(t.urlPattern))return t.urlPattern,this.managers.storageManager.clearPendingNavigation(),!1;t.playlistId,t.nextStepId,this.managers.storageManager.clearPendingNavigation();try{if(this.playlistOrchestrator)return await this.playlistOrchestrator.startPlaylist(t.playlistId,{startNodeId:t.nextStepId}),!0}catch(t){return!1}return!1}isURLPathMatch(t){if(!t||"undefined"==typeof window)return!1;const e=mt(window.location.href),n=window.location.pathname,i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*"),s=new RegExp(i);return s.test(e)||s.test(n)}getOrCreateAnonymousUserId(){if("undefined"==typeof window)return`anonymous_${Date.now()}_${Math.random().toString(36).substring(2,11)}`;const t=this.managers.storageManager.getAnonymousUserData();if(null==t?void 0:t.userId)return t.userId,t.userId;const e=`anonymous_${Date.now()}_${Math.random().toString(36).substring(2,11)}`;return this.managers.storageManager.setAnonymousUserData({userId:e,userData:{},watchedPlaylists:{},timestamp:Date.now()}),e}setupVisibilityChangeListener(){"undefined"!=typeof window&&"undefined"!=typeof document&&(this.removeVisibilityChangeListener(),this.boundVisibilityHandler=()=>this.handleVisibilityChange(),document.addEventListener("visibilitychange",this.boundVisibilityHandler))}removeVisibilityChangeListener(){this.boundVisibilityHandler&&"undefined"!=typeof document&&(document.removeEventListener("visibilitychange",this.boundVisibilityHandler),this.boundVisibilityHandler=null)}async handleVisibilityChange(){if("visible"!==document.visibilityState)return;if(!this.currentUserId)return;if(Date.now()-this.lastUserDataFetchTimestamp<5e3)return;const t=ct().currentState;if(!["playing","paused","loading","waitingForInteraction","autoplayBlocked","minimized","idleMode"].includes(t))try{this.isAnonymousUser?await this.refreshAnonymousUserData():await this.refreshIdentifiedUserData()}catch(t){}}async refreshIdentifiedUserData(){var t;const e=ct();if((null==(t=e.config)?void 0:t.token)&&this.currentUserId){this.currentUserId;try{const t=await fetch(`https://player.saltfish.ai/clients/${e.config.token}/users/${this.currentUserId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userData:this.currentUserData})});if(!t.ok)return;const n=await t.json();if(n.success){this.lastUserDataFetchTimestamp=Date.now(),n.firstIdentifiedAt&&e.mergeUserFields({firstIdentifiedAt:n.firstIdentifiedAt}),e.setUserData({watchedPlaylists:n.watchedPlaylists||{},language:n.language});const t=n.userListAssignments||{},i=n.abTestAssignments||{};this.managers.abTestManager.assignUserToTests(this.currentUserId,i,t),this.managers.triggerManager.evaluateAllTriggers()}}catch(t){}}}async refreshAnonymousUserData(){var t;if(!this.currentUserId)return;this.currentUserId,this.lastUserDataFetchTimestamp=Date.now();const e=this.managers.storageManager.getAnonymousUserData();e&&(ct().setUserData({watchedPlaylists:e.watchedPlaylists||{},language:null==(t=this.currentUserData)?void 0:t.language}),this.managers.triggerManager.evaluateAllTriggers())}destroy(){this.removeVisibilityChangeListener(),this.lastConfig=null,this.currentUserId=null,this.currentUserData=void 0,this.lastUserDataFetchTimestamp=0,this.isAnonymousUser=!1}}function vt(t){if(t)return"auto"===t?function(){try{const t=navigator.language||navigator.userLanguage;if(!t)return;return t.split("-")[0].toLowerCase()}catch(t){return}}():t.split("-")[0].toLowerCase()}class bt{constructor(t){e(this,"managers"),e(this,"playerInitializationService"),e(this,"userDataLoadedPromise",null),e(this,"userDataLoadedResolve",null),e(this,"lastUserIdentification",null),this.managers=t}setPlayerInitializationService(t){this.playerInitializationService=t}getLastUserIdentification(){return this.lastUserIdentification}getUserDataLoadedPromise(){return this.userDataLoadedPromise}identifyUser(t,e){let n=e;if(e&&"string"==typeof e.language){const t=vt(e.language);n={...e,language:t},e.language}this.lastUserIdentification={userId:t,userData:n};const i=ct();i.identifyUser(t,n),this.managers.analyticsManager.setUser({id:t,...n}),(i.abTests||[]).length>0&&(this.userDataLoadedPromise=new Promise((t=>{this.userDataLoadedResolve=t}))),this.playerInitializationService&&this.playerInitializationService.fetchUserData(t,n)}async identifyAnonymous(t){if(!this.playerInitializationService)throw new Error("PlayerInitializationService not set");let e=t;if(t&&"string"==typeof t.language){const n=vt(t.language);e={...t,language:n},t.language}const n=this.playerInitializationService.getOrCreateAnonymousUserId();this.lastUserIdentification={userId:n,userData:e},ct().identifyUser(n,{...e,__isAnonymous:!0}),this.managers.analyticsManager.setUser({id:n,...e}),await this.playerInitializationService.loadAnonymousUserData(n,e)}async recordABTestAttempt(t){var e;try{const n=ct(),i=n.user;if(!i||!(null==(e=n.config)?void 0:e.token))return;const s=(n.abTests||[]).find((e=>e.playlistId===t));if(!s)return;const r=(n.abTestAssignments||{})[s.id];if(!r)return void s.id;s.name,r.assigned;const a=await fetch(`https://player.saltfish.ai/clients/${n.config.token}/users/${i.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({abTestAssignments:{[s.id]:r}})});a.ok?s.name:(a.status,a.statusText)}catch(t){}}resolveUserDataLoaded(){this.userDataLoadedResolve&&(this.userDataLoadedResolve(),this.userDataLoadedResolve=null,this.userDataLoadedPromise=null)}destroy(){this.userDataLoadedPromise=null,this.userDataLoadedResolve=null,this.lastUserIdentification=null}}class wt{async validatePlaylistStart(t){const{playlistId:e,options:n,eventManager:i}=t;try{const t=ct();if(!t.config)return{isValid:!1,error:"Saltfish Player must be initialized before starting a playlist"};if(!0===t.isAdmin)return{isValid:!0,manifestPath:`https://storage.saltfish.ai/flows2/drafts/${e}.json`,updatedOptions:n};if(!0===(null==n?void 0:n._startedFromShareLink)&&!0===(null==n?void 0:n._isGlobalShare))return{isValid:!0,manifestPath:`https://storage.saltfish.ai/flows2/drafts/${e}.json`,updatedOptions:n};!0===(null==n?void 0:n._startedFromShareLink)&&(null==n||n._isGlobalShare);const s=t.backendPlaylists;if(!s||0===s.length)return ut.handlePlaylistError("No playlist list available from backend validation",{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,errorType:"playlist_backend_unavailable"}),{isValid:!1,error:"No backend playlists available"};const r=s.find((t=>t.id===e));if(!r)return ut.handlePlaylistError(`Playlist ID '${e}' not found in the list provided by backend validation`,{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,errorType:"playlist_not_found",additionalData:{backendPlaylists:s}}),{isValid:!1,error:"Playlist not found in backend list"};if((null==r?void 0:r.hasTriggers)??(null==r?void 0:r.autoStart)){const t=await this.validateTriggerConditions(e,r,i);if(!t.isValid)return t}let a=n;if(null==n?void 0:n.once){const t=await this.validateOnceOptionConditions(e,n,i);if(!t.isValid)return t;a=t.updatedOptions||n}const o=await this.validateDeviceCompatibility(r,e);return o.isValid?{isValid:!0,manifestPath:r.path,updatedOptions:a}:o}catch(t){const n=t instanceof Error?t.message:"Unknown validation error";return ut.handlePlaylistError(`Playlist validation failed: ${n}`,{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,additionalData:{error:t}}),{isValid:!1,error:n}}}async validateTriggerConditions(t,e,n){var i,s;const r=ct();if(!r.user)return ut.handlePlaylistError("User must be identified before starting auto-start playlist",{component:"PlaylistValidator",method:"validateAutoStartConditions",playlistId:t,errorType:"playlist_user_required"}),{isValid:!1,error:"User identification required for triggered playlist"};r.userData||await this.waitForUserData(n);const a=(null==(i=ct().userData)?void 0:i.watchedPlaylists)||{},o=e.hasTriggers??e.autoStart??!1,l=a[t],c=null==(s=e.triggers)?void 0:s.maxVisits,d=(null==l?void 0:l.visitCount)??("completed"===(null==l?void 0:l.status)||"dismissed"===(null==l?void 0:l.status)?1:0);return o&&null!=c&&d>=c?(j(`Playlist ${t} has hasTriggers enabled with maxVisits:${c} and user has ${d} visits. Skipping playlist start.`,{watchedPlaylists:a,triggers:e.triggers}),{isValid:!1,error:`Playlist visit limit reached (${d}/${c})`}):{isValid:!0}}async validateOnceOptionConditions(t,e,n){var i;const s=ct();if(!s.user)return ut.handlePlaylistError("User must be identified before starting playlist with once option",{component:"PlaylistValidator",method:"validateOnceOptionConditions",playlistId:t,errorType:"playlist_auth_required"}),{isValid:!1,error:"User identification required for once option"};s.userData||await this.waitForUserData(n);const r=(null==(i=ct().userData)?void 0:i.watchedPlaylists)||{},a=r[t];return!a||"completed"!==a.status&&"dismissed"!==a.status?a&&"in_progress"===a.status&&!(null==e?void 0:e.startNodeId)&&a.currentStepId?{isValid:!0,updatedOptions:{...e,startNodeId:a.currentStepId}}:{isValid:!0}:(j(`Playlist ${t} has once option enabled and has already been ${a.status}. Skipping playlist start.`,{watchedPlaylists:r,playlistStatus:a.status}),{isValid:!1,error:`Playlist already ${a.status} with once option`})}async validateDeviceCompatibility(t,e){try{const n=t.deviceType||"both",{isDeviceCompatible:i}=await Promise.resolve().then((()=>_t));return i(n)?{isValid:!0}:(ut.handlePlaylistError(`Playlist '${e}' is not compatible with this device. Required: ${n}`,{component:"PlaylistValidator",method:"validateDeviceCompatibility",playlistId:e,errorType:"playlist_device_incompatible",additionalData:{requiredDeviceType:n,manifestPath:t.path}}),{isValid:!1,error:`Device incompatible. Required: ${n}`})}catch(n){const i=n instanceof Error?n.message:"Unknown error";return ut.handlePlaylistError(`Device compatibility check failed: ${i}`,{component:"PlaylistValidator",method:"validateDeviceCompatibility",playlistId:e,additionalData:{error:n,manifestPath:t.path}}),{isValid:!1,error:`Device compatibility check failed: ${i}`}}}async waitForUserData(t){return new Promise(((e,n)=>{const i=setTimeout((()=>{t.off("userDataLoaded",s),n(new Error("Timeout waiting for user data"))}),5e3),s=()=>{clearTimeout(i),ct(),e()};t.on("userDataLoaded",s)}))}}class St{constructor(t){e(this,"managers"),e(this,"userManagementService"),e(this,"managerOrchestrator"),e(this,"playerInitializationService"),e(this,"stateMachineActionHandler"),this.managers=t}setUserManagementService(t){this.userManagementService=t}setManagerOrchestrator(t){this.managerOrchestrator=t}setPlayerInitializationService(t){this.playerInitializationService=t}setStateMachineActionHandler(t){this.stateMachineActionHandler=t}async startPlaylist(t,e){var n,i,s,r,a;try{const o=this.isInitialized()&&!this.managers.uiManager.getPlayerElement();if(!this.isInitialized()&&this.playerInitializationService){const e=this.playerInitializationService.getLastConfig();if(e)try{await this.playerInitializationService.initialize(e);const t=null==(n=this.userManagementService)?void 0:n.getLastUserIdentification();t&&this.userManagementService&&this.userManagementService.identifyUser(t.userId,t.userData),this.resetManagers(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()}catch(e){throw ut.handleInitializationError(`Failed to reinitialize player: ${e instanceof Error?e.message:"Unknown error"}`,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,additionalData:{reinitError:e}})}}o&&(this.resetManagers(),this.managers.transitionManager.setTriggerManager(this.managers.triggerManager),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions());const l=ct();if(!l.config){if(!(null==(i=this.playerInitializationService)?void 0:i.getLastConfig()))throw ut.createError("Saltfish Player must be initialized at least once before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t});throw ut.createError("Saltfish Player must be initialized before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t})}l.manifest&&("playing"===l.currentState||"paused"===l.currentState||"loading"===l.currentState||"waitingForInteraction"===l.currentState||"autoplayBlocked"===l.currentState||"minimized"===l.currentState||"idleMode"===l.currentState)&&(this.managerOrchestrator&&this.managerOrchestrator.cleanupCurrentPlaylist(),l.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()),"completed"!==l.currentState&&"closing"!==l.currentState||(l.currentState,l.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()),this.managers.sessionManager.startNewRun(),this.managers.triggerManager.markPlaylistAsTriggered(t);const c=null==(s=this.userManagementService)?void 0:s.getUserDataLoadedPromise();if(c&&await c,this.userManagementService&&await this.userManagementService.recordABTestAttempt(t),!0!==(null==e?void 0:e._startedFromShareLink)){if(!this.managers.abTestManager.isPlaylistAvailable(t))return}else null==e||e._startedFromShareLink;const d=new wt,h=await d.validatePlaylistStart({playlistId:t,options:e,eventManager:this.managers.eventManager});if(!h.isValid)return;e=h.updatedOptions||e;const u=h.manifestPath,p=e||{};p?(l.setPlaylistOptions(p),p.position||l.setPlaylistOptions({...p,position:"bottom-right"})):l.setPlaylistOptions({position:"bottom-right"}),this.managers.uiManager.createPlayerUI(this.managers.videoManager,this.managers.cursorManager,this.managers.interactionManager),this.managerOrchestrator&&this.managerOrchestrator.setupUpdaters(),this.managers.uiManager.updatePosition(),l.sendStateMachineEvent({type:"LOAD_MANIFEST"});const g=null==e?void 0:e.persistence;if("undefined"!=typeof window){const e=null==(r=l.user)?void 0:r.id,n=this.managers.storageManager.getProgress(e);if(n&&n[t])l.loadPlaylistProgress(t,n[t]);else if(l.progress[t]){const e={...l.progress};delete e[t],lt.setState((t=>{t.progress=e}))}}this.managers.cursorManager.resetFirstAnimation(),await this.managers.playlistManager.load(u,{...p,persistence:g});const m=ct();if(m.manifest){const t=p.persistence??m.manifest.isPersistent??!0,e=m.playlistOptions||{};m.setPlaylistOptions({...e,...p,persistence:t})}if(p.startNodeId&&m.manifest&&(m.manifest.steps.find((t=>t.id===p.startNodeId))?m.goToStep(p.startNodeId):console.warn(`[PlaylistOrchestrator] startNodeId '${p.startNodeId}' not found in manifest steps. Starting from default step.`)),m.manifest){m.manifest.cursorColor&&this.managers.cursorManager.setColor(m.manifest.cursorColor),m.manifest.cursorLabel&&this.managers.cursorManager.setLabel(m.manifest.cursorLabel),p._triggeredByTriggerManager;const t=m.currentStepId===(null==(a=m.manifest.steps[0])?void 0:a.id);if(m.manifest.idleMode&&t){if(m.manifest.compactFirstStep){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.add("sf-player--compact"),m.manifest.compactLabel&&this.managers.uiManager.showCompactLabel(m.manifest.compactLabel)}l.setIdleMode()}else l.play()}else l.play();j(`Playlist started: ${t}${m.manifest?` (${m.manifest.name})`:""}`)}catch(e){this.managers.uiManager.hideLoading(),ct().sendStateMachineEvent({type:"ERROR",error:e instanceof Error?e:new Error(String(e))}),ut.handlePlaylistError(e,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,errorType:"playlist_load_failed"})}}resetPlaylist(){const t=ct();t.manifest&&t.goToStep(t.manifest.startStep)}isInitialized(){return!!ct().config}resetManagers(){this.managers.videoManager.reset(),this.managers.cursorManager.reset(),this.managers.interactionManager.reset(),this.managers.transitionManager.reset(),this.managers.uiManager.reset(),this.managers.stepTimeoutManager.reset()}destroy(){}}class Et{constructor(t,n){e(this,"listener",null),e(this,"videoElement",null),e(this,"stepId",null),this.managers=t,this.logPrefix=n}cleanup(t){if(t&&this.stepId&&t!==this.stepId)return this.logPrefix,void this.stepId;this.listener&&this.videoElement&&(this.videoElement.removeEventListener("timeupdate",this.listener),this.listener=null,this.videoElement=null,this.stepId=null)}schedule(t,e){this.cleanup();let n=t.showAtSeconds??0;if("number"==typeof n&&isFinite(n)||(this.logPrefix,n=0),n<0&&(this.logPrefix,n=0),n<=0)return this.logPrefix,void this.managers.cursorManager.animate(t);this.logPrefix;const i=this.managers.videoManager.getVideoElement();if(!i)return void this.logPrefix;let s=!1,r=!1;const a=()=>{if(s)return;const e=i.currentTime,a=i.duration;if(a&&!isNaN(a)&&n>a&&!r)return this.logPrefix,r=!0,s=!0,this.cleanup(),void this.managers.cursorManager.animate(t);e>=n&&(s=!0,this.logPrefix,this.cleanup(),this.managers.cursorManager.animate(t))};this.listener=()=>{a()},this.videoElement=i,this.stepId=e,i.addEventListener("timeupdate",this.listener),i.addEventListener("ended",(()=>{if(s)return;const n=ct();if(n.currentStepId!==e)return this.logPrefix,n.currentStepId,void this.cleanup(e);i.duration,this.logPrefix,s=!0,this.managers.cursorManager.animate(t),this.cleanup()}),{once:!0})}}class Mt{constructor(t){e(this,"managers"),e(this,"destroyCallback",null),e(this,"cursorScheduler"),this.managers=t,this.cursorScheduler=new Et(t,"StateMachineActionHandler")}setDestroyCallback(t){this.destroyCallback=t}registerStateMachineActions(){ct().registerStateMachineActions({startVideoPlayback:t=>this.handleStartVideoPlayback(t),startIdleModeVideo:t=>this.handleStartIdleModeVideo(t),handleError:t=>this.handleError(t),pauseVideoPlayback:()=>this.handlePauseVideoPlayback(),startMutedLoopedVideo:()=>this.handleStartMutedLoopedVideo(),trackPlaylistComplete:()=>this.handleTrackPlaylistComplete(),hideError:()=>this.handleHideError(),showLoadingState:()=>this.handleShowLoadingState(),hideLoadingState:()=>this.handleHideLoadingState(),hideVideoControls:()=>this.handleHideVideoControls(),showVideoControls:()=>this.handleShowVideoControls(),showPlayButton:()=>this.handleShowPlayButton(),hidePlayButton:()=>this.handleHidePlayButton(),enablePlayButtonProminent:()=>this.handleEnablePlayButtonProminent(),disablePlayButtonProminent:()=>this.handleDisablePlayButtonProminent(),enterCompactMode:()=>this.handleEnterCompactMode(),exitCompactMode:()=>this.handleExitCompactMode(),triggerPlaylistDismissed:()=>this.handleTriggerPlaylistDismissed(),scheduleDestroy:()=>this.handleScheduleDestroy()})}getVideoUrl(t){var e;const n=null==(e=ct().userData)?void 0:e.language;let i;return i=n&&t.translations&&t.translations[n]?t.translations[n].videoUrl:t.compressedUrl||t.videoUrl,i&&""!==i.trim()||!t.audioUrl||""===t.audioUrl.trim()?i:(t.id,t.audioUrl)}isUsingAudioFallback(t){var e;const n=null==(e=ct().userData)?void 0:e.language;let i;return i=n&&t.translations&&t.translations[n]?t.translations[n].videoUrl:t.compressedUrl||t.videoUrl,!(i&&""!==i.trim()||!t.audioUrl||""===t.audioUrl.trim())}findNextVideoUrl(t){const e=ct();if(!e.manifest||!t)return null;if(t.transitions.length>0){const n=t.transitions[0];if("url-path"===n.type||"dom-click"===n.type)return null;const i=n.nextStep,s=e.manifest.steps.find((t=>t.id===i));if(s)return this.getVideoUrl(s)}const n=e.manifest.steps.findIndex((e=>e.id===t.id));return n>=0&&n<e.manifest.steps.length-1?this.getVideoUrl(e.manifest.steps[n+1]):null}destroy(){this.cursorScheduler.cleanup()}async validateStepUrlRequirement(t){if(!t.urlRequirement)return!0;t.id,this.managers.transitionManager.startStateMachineValidation();try{const e=await async function(t,e=20,n=100){if(!t)return!0;for(let i=0;i<e;i++){if(ft(t))return!0;if(i<e-1&&(await new Promise((t=>setTimeout(t,n))),!window._saltfishPlayer))return!1}return t.pattern,t.matchType,!1}(t.urlRequirement);if(!e){t.id;const e=window._saltfishPlayer;e&&"function"==typeof e.destroy&&e.destroy()}return e}finally{this.managers.transitionManager.endStateMachineValidation()}}async handleStartVideoPlayback(t){if(!t.currentStep)return;const e=t.currentStep;if(e.urlRequirement&&(e.id,!await this.validateStepUrlRequirement(e)))return;this.managers.uiManager.updatePosition(),this.managers.uiManager.showPlayer();const n=this.getVideoUrl(e),i=this.isUsingAudioFallback(e);this.showOrHideAudioOverlay(e,i);try{this.managers.interactionManager.clearButtons(),e.buttons&&this.managers.interactionManager.createButtons(e.buttons);const t=e.buttons&&e.buttons.length>0||e.transitions.some((t=>"dom-click"===t.type||"url-path"===t.type||"dom-element-visible"===t.type));t&&this.managers.transitionManager.setupTransitions(e,!1,!0),this.managers.videoManager.setCompletionPolicy(t?"manual":"auto",(()=>this.handleStepVideoEnded(e,t))),this.managers.videoManager.loadVideo(n).then((()=>this.handleStepVideoLoaded(e,i))).catch((t=>this.handleStepVideoLoadError(t,e)))}catch(t){}}showOrHideAudioOverlay(t,e){if(e){const e=ct().manifest;this.managers.videoManager.showAudioFallbackOverlay(t.gifUrl,null==e?void 0:e.avatarThumbnailUrl)}else this.managers.videoManager.hideAudioFallbackOverlay()}handleStepVideoEnded(t,e){var n;const i=ct();if(!e){const e=t.transitions.find((t=>"timeout"===t.type));return e&&e.timeout&&e.timeout>0?(e.timeout,this.managers.transitionManager.setupTransitions(t,!1)):this.managers.transitionManager.setupTransitions(t,!0),void(t.transitions.some((t=>i.manifest.steps.some((e=>e.id===t.nextStep))))||i.sendStateMachineEvent({type:"COMPLETE_PLAYLIST"}))}const s=t.transitions.find((t=>"timeout"===t.type)),r=null==(n=t.buttons)?void 0:n.some((t=>"goto"===t.action.type||"next"===t.action.type));if(s&&!r){const e=s.timeout||0;s.nextStep,setTimeout((()=>{var e;const n=ct();n.currentStepId!==t.id||"waitingForInteraction"!==n.currentState&&"playing"!==n.currentState?n.currentState:(s.nextStep,null==(e=n.goToStep)||e.call(n,s.nextStep))}),e)}i.sendStateMachineEvent({type:"VIDEO_FINISHED_WAIT",step:t})}handleStepVideoLoaded(t,e){this.managers.uiManager.hideError(),this.loadTranscriptForStep(t),t.cursorAnimations&&t.cursorAnimations.length>0?(t.id,this.managers.cursorManager.setShouldShowCursor(!0),this.cursorScheduler.schedule(t.cursorAnimations[0],t.id)):(t.id,this.managers.cursorManager.setShouldShowCursor(!1)),e?this.managers.videoManager.startAudioVisualization():this.managers.videoManager.initializeAudioForVideo(),this.managers.videoManager.play();const n=this.findNextVideoUrl(t);n&&this.managers.videoManager.preloadNextVideo(n)}handleStepVideoLoadError(t,e){var n;const i=t instanceof Error?t:new Error(`Failed to load video: ${t}`);this.managers.uiManager.showError(i,"video");const s=ct(),r=t;this.managers.eventManager.trigger("error",{timestamp:Date.now(),playlistId:(null==(n=s.manifest)?void 0:n.id)||void 0,stepId:e.id,error:i,errorType:"video",videoUrl:null==r?void 0:r.videoUrl,mediaErrorCode:null==r?void 0:r.mediaErrorCode,mediaErrorMessage:null==r?void 0:r.mediaErrorMessage,failureReason:null==r?void 0:r.failureReason})}loadTranscriptForStep(t){var e,n;const i=ct(),s=(null==(e=i.manifest)?void 0:e.captions)??!0,r=null==(n=i.userData)?void 0:n.language;let a=t.transcript;if(r&&t.translations&&t.translations[r]){const e=t.translations[r].transcript;e&&(a=e,t.id)}a?(t.id,this.managers.videoManager.loadTranscript(a,s)):(t.id,this.managers.videoManager.loadTranscript(null,!0))}handlePauseVideoPlayback(){this.managers.videoManager.pause()}handleStartMutedLoopedVideo(){const t=this.managers.videoManager.getVideoElement();t&&(t.muted=!0,t.loop=!0,t.play().catch((()=>{})))}handleStartIdleModeVideo(t){if(!t.currentStep)return;const e=t.currentStep,n=this.getVideoUrl(e),i=this.isUsingAudioFallback(e);this.managers.uiManager.showPlayer(),this.showOrHideAudioOverlay(e,i),this.managers.videoManager.loadVideo(n).then((()=>{this.managers.uiManager.hideError(),i&&this.managers.videoManager.startAudioVisualization();const t=this.managers.videoManager.getVideoElement();t&&(t.muted=!0,t.loop=!0,t.play().catch((()=>{})))})).catch((t=>{}))}handleTrackPlaylistComplete(){var t,e;const n=ct();if(n.manifest&&this.managers.eventManager){const i=n.manifest.id;if(this.managers.eventManager.trigger("playlistEnded",{timestamp:Date.now(),playlist:{id:i,title:n.manifest.name}}),((null==(t=n.playlistOptions)?void 0:t.persistence)??1)&&n.progress[i]){const t={...n.progress};delete t[i];const s=null==(e=n.user)?void 0:e.id;this.managers.storageManager.setProgress(t,s)}}}handleError(t){var e,n;if(null==(e=t.error)||e.message,t.error&&this.managers.uiManager.getPlayerElement()){this.managers.uiManager.showError(t.error,"player");const e=ct();this.managers.eventManager.trigger("error",{timestamp:Date.now(),playlistId:(null==(n=e.manifest)?void 0:n.id)||void 0,stepId:e.currentStepId||void 0,error:t.error,errorType:"player"})}}handleHideError(){this.managers.uiManager.hideError()}handleShowLoadingState(){this.managers.uiManager.showLoading("Loading...")}handleHideLoadingState(){this.managers.uiManager.hideLoading()}handleHideVideoControls(){this.managers.videoManager.hideProgressBar(),this.managers.videoManager.hideMuteButton()}handleShowVideoControls(){this.managers.videoManager.showProgressBar(),this.managers.videoManager.showMuteButton()}handleShowPlayButton(){this.managers.uiManager.updatePlayPauseButton("paused")}handleHidePlayButton(){this.managers.uiManager.updatePlayPauseButton("playing")}handleEnablePlayButtonProminent(){this.managers.uiManager.enablePlayButtonProminent()}handleDisablePlayButtonProminent(){this.managers.uiManager.disablePlayButtonProminent()}handleEnterCompactMode(){var t,e,n;const i=ct();if(i.manifest&&i.currentStepId===(null==(t=i.manifest.steps[0])?void 0:t.id)&&(null==(e=i.manifest)?void 0:e.compactFirstStep)){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.add("sf-player--compact"),(null==(n=i.manifest)?void 0:n.compactLabel)&&this.managers.uiManager.showCompactLabel(i.manifest.compactLabel)}}handleExitCompactMode(){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.remove("sf-player--compact"),this.managers.uiManager.hideCompactLabel()}handleTriggerPlaylistDismissed(){const t=ct();t.manifest&&this.managers.eventManager&&this.managers.eventManager.trigger("playlistDismissed",{timestamp:Date.now(),playlist:{id:t.manifest.id,title:t.manifest.name}})}handleScheduleDestroy(){setTimeout((()=>{this.destroyCallback&&this.destroyCallback()}),0)}}const xt=class t{constructor(t){e(this,"managers"),e(this,"uiUpdaterUnsubscribe",null),e(this,"eventUpdaterUnsubscribe",null),e(this,"cursorScheduler"),e(this,"isInitialized",!1),this.managers=t,this.cursorScheduler=new Et(t,"ManagerOrchestrator")}setInitialized(t){this.isInitialized=t}setupUpdaters(){this.uiUpdaterUnsubscribe&&this.uiUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe&&this.eventUpdaterUnsubscribe();const t=this.managers.uiManager.getPlayerElement();t&&(this.uiUpdaterUnsubscribe=function(t,e){let n=null;const i=()=>{n=t.querySelector(".sf-player__minimize-button")};i();let s={currentState:"",isMinimized:!1,currentStepId:null};function r(t,n){var i;if(!e)return;const s=null==(i=null==n?void 0:n.steps)?void 0:i.find((e=>e.id===t));s&&s.cursorAnimations&&s.cursorAnimations.length>0&&e.setShouldShowCursor(!0)}return lt.subscribe((a=>{var o,l,c,d;n||i(),a.currentState!==s.currentState&&(o=a.currentState,["sf-player--idle","sf-player--loading","sf-player--playing","sf-player--paused","sf-player--waitingForInteraction","sf-player--autoplayBlocked","sf-player--idleMode","sf-player--error","sf-player--completed","sf-player--completedWaitingForInteraction"].forEach((e=>{t.classList.remove(e)})),t.classList.add(`sf-player--${o}`)),a.isMinimized!==s.isMinimized&&(l=a.isMinimized,c=a.currentStepId,d=a.manifest,l?(t.classList.add("sf-player--minimized"),e&&e.setShouldShowCursor(!1)):(t.classList.remove("sf-player--minimized"),r(c,d)),function(t){n&&(n.innerHTML=t?'\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>\n ':'\n <svg width="20" height="20" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>\n </svg>\n ')}(a.isMinimized)),a.currentStepId!==s.currentStepId&&(a.isMinimized||r(a.currentStepId,a.manifest)),s={currentState:a.currentState,isMinimized:a.isMinimized,currentStepId:a.currentStepId}}))}(t,this.managers.cursorManager)),this.eventUpdaterUnsubscribe=function(t){let e=null,n=null,i=null,s=null,r={playlistData:null,stepData:null},a=null;const o=()=>{a&&(clearTimeout(a),a=null),r.playlistData&&t.trigger("playlistStarted",{timestamp:Date.now(),playlist:r.playlistData}),r.stepData&&t.trigger("stepStarted",{timestamp:Date.now(),step:{id:r.stepData.id,title:r.stepData.title},playlist:{id:r.stepData.playlistId,title:r.stepData.playlistTitle}}),r={playlistData:null,stepData:null}};return lt.subscribe((l=>{var c;if(e===l.currentState&&i===l.isMinimized&&s===l.currentStepId)return;const d=e,h=n,u=i,p=s;n=e,e=l.currentState,i=l.isMinimized,s=l.currentStepId;const g={prevPreviousState:h,previousState:d,currentState:l.currentState,currentStepId:l.currentStepId,isMinimized:l.isMinimized};null==(c=l.manifest)||c.id,"playing"===g.previousState&&("autoplayBlocked"===g.currentState||"idleMode"===g.currentState?(a&&(clearTimeout(a),a=null),(r.playlistData||r.stepData)&&(r={playlistData:null,stepData:null})):(r.playlistData||r.stepData)&&o()),"autoplayBlocked"!==g.currentState&&"idleMode"!==g.currentState||"autoplayBlocked"===g.previousState||"idleMode"===g.previousState||l.manifest&&(l.manifest.id,t.trigger("bubbleShown",{timestamp:Date.now(),playlist:{id:l.manifest.id,title:l.manifest.name}})),function(t,e,n,i){const{prevPreviousState:s,previousState:r,currentState:a,currentStepId:o}=t,l="playing"===a&&"paused"===r&&"loading"===s,c="playing"===a&&("autoplayBlocked"===r||"idleMode"===r);if(e.manifest&&o&&o===e.manifest.startStep){if(c)return e.manifest.id,void n.trigger("playlistStarted",{timestamp:Date.now(),playlist:{id:e.manifest.id,title:e.manifest.name}});if(l)return e.manifest.id,void(i.playlistData={id:e.manifest.id,title:e.manifest.name})}"paused"===r&&"playing"===a?n.trigger("playerResumed",{timestamp:Date.now(),previousState:r,currentState:a}):"playing"===r&&"paused"===a&&n.trigger("playerPaused",{timestamp:Date.now(),previousState:r,currentState:a})}(g,l,t,r),function(t,e,n,i){const{previousState:s,currentState:r,isMinimized:a}=t,o=i||!1;!a&&o?n.trigger("playerMaximized",{timestamp:Date.now(),previousState:s,currentState:r}):a&&!o&&n.trigger("playerMinimized",{timestamp:Date.now(),previousState:s,currentState:r})}(g,0,t,u),function(t,e,n,i,s){var r,a,o;const{prevPreviousState:l,previousState:c,currentStepId:d,currentState:h}=t,u=e.currentStepId?((null==(r=e.manifest)?void 0:r.steps)||[]).find((t=>t.id===e.currentStepId)):null;null==u||u.id,null==(a=e.manifest)||a.id,e.manifest;const p=i&&e.manifest&&(i!==d||"waitingForInteraction"===h||"completed"===h);if(e.manifest,p){const t=((null==(o=e.manifest)?void 0:o.steps)||[]).find((t=>t.id===i));null==t||t.id,t&&(t.id,n.trigger("stepEnded",{timestamp:Date.now(),step:{id:t.id,title:t.title||t.id},playlist:{id:e.manifest.id,title:e.manifest.name}}))}const g=d!==i&&"playing"===h,m=("autoplayBlocked"===c||"idleMode"===c)&&"playing"===h&&i===d,f="loading"===l&&"paused"===c&&"playing"===h&&d,y=e.manifest&&d===e.manifest.startStep,v=y&&f,b=!y&&f;null==u||u.id,e.manifest,u&&e.manifest&&(g||m||b?(u.id,n.trigger("stepStarted",{timestamp:Date.now(),step:{id:u.id,title:u.title||u.id},playlist:{id:e.manifest.id,title:e.manifest.name}})):v&&(u.id,s.stepData={id:u.id,title:u.title||u.id,playlistId:e.manifest.id,playlistTitle:e.manifest.name}))}(g,l,t,p,r),function(t,e,n){var i;const{currentState:s,previousState:r}=t;"error"===s&&"error"!==r&&e.error&&n.trigger("error",{timestamp:Date.now(),playlistId:null==(i=e.manifest)?void 0:i.id,stepId:e.currentStepId,error:e.error,errorType:"state"})}(g,l,t),!r.playlistData&&!r.stepData||a||(a&&clearTimeout(a),a=setTimeout((()=>{(r.playlistData||r.stepData)&&o(),a=null}),500))}))}(this.managers.eventManager);const e=lt.subscribe((t=>{this.managers.stepTimeoutManager.update({currentState:t.currentState,currentStepId:t.currentStepId,isMinimized:t.isMinimized,previousState:void 0})})),n=this.eventUpdaterUnsubscribe;this.eventUpdaterUnsubscribe=()=>{n&&n(),e()}}handleStoreChanges(){if(!this.isInitialized)return;const e=ct();if(e.currentState!==t.prevState.currentState||e.currentStepId!==t.prevState.currentStepId||e.isMinimized!==t.prevState.isMinimized){if(t.prevState.currentState,e.currentState,t.prevState.currentStepId,e.currentStepId,t.prevState.isMinimized,e.isMinimized,this.managers.uiManager.getPlayerRoot()&&this.managers.uiManager.getPlayerElement()&&this.managers.uiManager.updatePosition(),this.managers.videoManager.transcriptManager.handleStateChange(e.currentState),"autoplayBlocked"===e.currentState)this.managers.cursorManager.stopAnimation(),this.managers.cursorManager.setShouldShowCursor(!1);else if("playing"===e.currentState&&"autoplayBlocked"===t.prevState.currentState){const t=e.manifest,n=null==t?void 0:t.steps.find((t=>t.id===e.currentStepId));(null==n?void 0:n.cursorAnimations)&&n.cursorAnimations.length>0&&(this.managers.cursorManager.setShouldShowCursor(!0),this.cursorScheduler.schedule(n.cursorAnimations[0],e.currentStepId||"unknown"))}else"completed"!==e.currentState&&"closing"!==e.currentState||this.cleanupPlaylist();e.isMinimized!==t.prevState.isMinimized&&this.managers.uiManager.handleMinimizeStateChange(e.isMinimized),t.prevState={currentState:e.currentState,currentStepId:e.currentStepId,isMinimized:e.isMinimized}}}cleanupCurrentPlaylist(){try{this.cursorScheduler.cleanup(),this.eventUpdaterUnsubscribe&&(this.eventUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe=null),this.managers.stepTimeoutManager&&this.managers.stepTimeoutManager.reset(),this.managers.videoManager&&(this.managers.videoManager.pause(),this.managers.videoManager.reset()),this.managers.cursorManager&&(this.managers.cursorManager.stopAnimation(),this.managers.cursorManager.setShouldShowCursor(!1)),this.managers.transitionManager&&this.managers.transitionManager.cleanupTransitions(),this.managers.interactionManager&&this.managers.interactionManager.clearButtons(),this.managers.uiManager.reset()}catch(t){ut.handleCleanupError(t,{component:"ManagerOrchestrator",method:"cleanupCurrentPlaylist"})}}cleanupPlaylist(){var t;if(this.isInitialized)try{const e=ct();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,this.uiUpdaterUnsubscribe&&(this.uiUpdaterUnsubscribe(),this.uiUpdaterUnsubscribe=null),this.managers.transitionManager.reset(),this.managers.videoManager.destroy(),this.managers.cursorManager.destroy(),this.managers.interactionManager.destroy(),this.managers.playlistManager.destroy(),this.managers.stepTimeoutManager.destroy(),this.managers.uiManager.destroy()}catch(t){ut.handleCleanupError(t,{component:"ManagerOrchestrator",method:"cleanupPlaylist"})}else console.warn("Saltfish playlist Player is not initialized")}destroyAll(){var t;if(this.isInitialized)try{const e=ct();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,this.cursorScheduler.cleanup(),this.uiUpdaterUnsubscribe&&(this.uiUpdaterUnsubscribe(),this.uiUpdaterUnsubscribe=null),this.eventUpdaterUnsubscribe&&(this.eventUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe=null),this.managers.transitionManager.destroy(),this.managers.triggerManager.destroy(),this.managers.videoManager.destroy(),this.managers.cursorManager.destroy(),this.managers.interactionManager.destroy(),this.managers.analyticsManager.destroy(),this.managers.sessionManager.destroy(),this.managers.playlistManager.destroy(),this.managers.stepTimeoutManager.destroy(),this.managers.uiManager.destroy(),this.isInitialized=!1,e.reset()}catch(t){ut.handleCleanupError(t,{component:"ManagerOrchestrator",method:"destroyAll"});try{this.isInitialized=!1,ct().reset()}catch(e){ut.handleCleanupError(e,{component:"ManagerOrchestrator",method:"destroyAll",additionalData:{originalError:t}})}}else console.warn("Saltfish playlist Player is not initialized")}getManagers(){return this.managers}destroy(){this.destroyAll()}};e(xt,"prevState",{currentState:"idle",currentStepId:null,isMinimized:!1});let It=xt;class Pt{constructor(){e(this,"container",null),e(this,"shadowRoot",null),e(this,"styleElement",null)}create(){if(this.container)return;this.container=document.createElement("div"),this.container.id="saltfish-container",this.container.appendChild(document.createTextNode("​")),document.body.appendChild(this.container),this.shadowRoot=this.container.attachShadow({mode:"open"});try{const t=new CSSStyleSheet;t.replaceSync(this.getBaseStyles()),this.shadowRoot.adoptedStyleSheets=[t]}catch(t){this.styleElement=document.createElement("style"),this.styleElement.textContent=this.getBaseStyles(),this.shadowRoot.appendChild(this.styleElement)}const t=document.createElement("div");t.id="sf-player-root",this.shadowRoot.appendChild(t)}getShadowRoot(){return this.shadowRoot}getRootElement(){return this.shadowRoot?this.shadowRoot.getElementById("sf-player-root"):null}addStyles(t){if(this.shadowRoot){if(this.shadowRoot.adoptedStyleSheets&&this.shadowRoot.adoptedStyleSheets.length>0)try{const e=this.shadowRoot.adoptedStyleSheets[0],n=Array.from(e.cssRules).map((t=>t.cssText)).join("\n");return void e.replaceSync(n+"\n"+t)}catch(t){console.warn("ShadowDOMManager: Failed to append to adoptedStyleSheet:",t)}this.styleElement&&(this.styleElement.textContent+=t)}}remove(){this.container&&(document.body.removeChild(this.container),this.container=null,this.shadowRoot=null,this.styleElement=null)}getBaseStyles(){return"\n /* \n * CSS Reset for the Saltfish playlist Player\n * Minimal reset for the Shadow DOM to ensure consistent rendering\n */\n\n:host {\n all: initial;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n box-sizing: border-box;\n}\n\n:host *,\n:host *::before,\n:host *::after {\n box-sizing: inherit;\n margin: 0;\n padding: 0;\n}\n\nbutton {\n background: none;\n border: none;\n cursor: pointer;\n font: inherit;\n outline: none;\n padding: 0;\n}\n\n/* Utility classes for CSP-compliant styling */\n.sf-hidden {\n display: none !important;\n} \n /* \n * Variables for the Saltfish playlist Player\n * Defines all design tokens used throughout the application\n */\n\n:host {\n /* Colors */\n --sf-primary-color: #4a9bff;\n --sf-secondary-color: #6ccfff;\n --sf-background-color: #1e1e1e;\n --sf-text-color: #ffffff;\n --sf-button-bg: rgba(0, 0, 0, 0.5);\n --sf-button-hover-bg: rgba(0, 0, 0, 0.7);\n --sf-overlay-gradient: linear-gradient(180deg, rgba(0, 0, 0, 0.7) 0%, transparent 30%, transparent 70%, rgba(0, 0, 0, 0.7) 100%);\n --sf-progress-gradient: linear-gradient(90deg, var(--sf-primary-color), var(--sf-secondary-color));\n --sf-error-color: #ff4d4d;\n --sf-error-bg: rgba(255, 77, 77, 0.1);\n \n /* Spacing */\n --sf-spacing-xs: 4px;\n --sf-spacing-sm: 8px;\n --sf-spacing-md: 12px;\n --sf-spacing-lg: 16px;\n --sf-spacing-xl: 24px;\n \n /* Sizes */\n --sf-player-width: 240px;\n --sf-player-height: 336px;\n --sf-player-min-width: 80px;\n --sf-player-min-height: 80px;\n --sf-player-compact-width: 120px;\n --sf-player-compact-height: 120px;\n --sf-control-button-size: 24px;\n --sf-play-button-size: 60px;\n --sf-play-button-compact-size: 44px;\n --sf-minimize-button-size: 34px;\n --sf-mute-button-size: 32px;\n --sf-cc-button-size: 32px;\n --sf-cursor-size: 32px;\n \n /* Border radius */\n --sf-border-radius-sm: 4px;\n --sf-border-radius-md: 8px;\n --sf-border-radius-lg: 16px;\n --sf-border-radius-circle: 50%;\n \n /* Transitions */\n --sf-transition-fast: 0.1s ease;\n --sf-transition-normal: 0.2s ease;\n --sf-transition-slow: 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n \n /* Shadows */\n --sf-shadow-small: 0 2px 5px rgba(0, 0, 0, 0.2);\n --sf-shadow-medium: 0 4px 8px rgba(0, 0, 0, 0.15);\n --sf-shadow-large: 0 10px 25px rgba(0, 0, 0, 0.2);\n \n /* Z-index layering */\n --sf-z-index-base: 1;\n --sf-z-index-overlay: 2;\n --sf-z-index-controls: 10;\n --sf-z-index-cursor: 9999;\n --sf-z-index-player: 2147483648;\n \n /* Font sizes */\n --sf-font-size-sm: 14px;\n --sf-font-size-md: 16px;\n --sf-font-size-lg: 18px;\n --sf-font-size-xl: 24px;\n} \n\n/* Mobile device responsive adjustments - make player smaller for mobile screens */\n@media (max-width: 768px) {\n :host {\n /* Reduce player size on mobile for better space utilization */\n --sf-player-width: 180px; /* 25% smaller than desktop (240px -> 180px) */\n --sf-player-height: 252px; /* 25% smaller than desktop (336px -> 252px) */\n --sf-player-min-width: 60px; /* Smaller when minimized (80px -> 60px) */\n --sf-player-min-height: 60px; /* Smaller when minimized (80px -> 60px) */\n --sf-player-compact-width: 90px; /* Smaller compact mode for mobile (120px -> 90px) */\n --sf-player-compact-height: 90px; /* Smaller compact mode for mobile (120px -> 90px) */\n\n /* Keep controls touch-friendly despite smaller player size */\n --sf-play-button-size: 44px; /* Smaller but still touch-friendly (60px -> 44px) */\n --sf-play-button-compact-size: 36px; /* Touch-friendly compact play button */\n --sf-control-button-size: 28px; /* Keep larger for touch targets (24px -> 28px) */\n --sf-mute-button-size: 26px; /* Smaller for mobile (32px -> 26px) */\n --sf-cc-button-size: 26px; /* Smaller for mobile (32px -> 26px) */\n --sf-minimize-button-size: 26px; /* Match other mobile button sizes */\n }\n}\n\n/* Touch device specific adjustments (tablets and larger touch devices, excluding mobile) */\n@media (pointer: coarse) and (min-width: 769px) {\n :host {\n /* Ensure touch-friendly sizes even on larger touch devices */\n --sf-control-button-size: 28px;\n --sf-mute-button-size: 38px;\n --sf-cc-button-size: 38px;\n --sf-minimize-button-size: 38px; /* Match other touch device button sizes */\n }\n} \n\n /* \n * Player component styles for the Saltfish playlist Player\n * Following BEM naming convention\n */\n\n/* Main player container */\n.sf-player {\n border-radius: var(--sf-border-radius-md);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15), 0 5px 15px rgba(0, 0, 0, 0.08);\n position: relative;\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n opacity: 0;\n /* Smooth transitions for size changes and opacity */\n transition: opacity 0.3s ease-in-out,\n width 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),\n height 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),\n border-radius 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n/* Player visible state - show with fade in */\n.sf-player--visible {\n opacity: 1;\n}\n\n/* Gradient overlay now moved to video container - see _video.css */\n\n/* Full-size player state */\n.sf-player:not(.sf-player--minimized) {\n width: var(--sf-player-width);\n height: var(--sf-player-height);\n}\n\n/* Autoplay fallback state - ensure play button is visible */\n.sf-player--waiting-for-user-interaction .sf-controls-container__play-button {\n display: flex !important;\n opacity: 1 !important;\n visibility: visible !important;\n}\n\n/* Also show the center play button in autoplay fallback state */\n.sf-player--waiting-for-user-interaction .sf-player__center-play-button {\n display: flex !important;\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 20) !important; /* Higher z-index to appear above overlay */\n}\n\n/* Make the autoplay fallback state more prominent to indicate need for interaction */\n.sf-player--waiting-for-user-interaction::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n}\n\n/* Player state: minimized */\n.sf-player--minimized {\n /* Equal width and height are essential for maintaining a perfect circle when using border-radius: 50% */\n width: var(--sf-player-min-width);\n height: var(--sf-player-min-height);\n border-radius: var(--sf-border-radius-circle);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.20), 0 5px 15px rgba(0, 0, 0, 0.12);\n cursor: pointer;\n /* Force overriding any inline styles that might be applied */\n max-width: var(--sf-player-min-width) !important;\n max-height: var(--sf-player-min-height) !important;\n min-width: var(--sf-player-min-width) !important;\n min-height: var(--sf-player-min-height) !important;\n}\n\n/* Player state: compact (first step, small rounded) */\n.sf-player--compact {\n width: var(--sf-player-compact-width) !important;\n height: var(--sf-player-compact-height) !important;\n border-radius: var(--sf-border-radius-circle);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.20), 0 5px 15px rgba(0, 0, 0, 0.12);\n cursor: pointer; /* Whole bubble is clickable */\n /* Force overriding any inline styles that might be applied */\n max-width: var(--sf-player-compact-width) !important;\n max-height: var(--sf-player-compact-height) !important;\n min-width: var(--sf-player-compact-width) !important;\n min-height: var(--sf-player-compact-height) !important;\n}\n\n/* Hide center play button in compact mode - the whole bubble is clickable */\n.sf-player--compact .sf-player__center-play-button {\n display: none !important;\n}\n\n/* Hide elements in compact mode */\n.sf-player--compact .sf-player__logo,\n.sf-player--compact .sf-player__minimize-button {\n display: none;\n}\n\n/* Hide gradient overlay when in compact mode - see _video.css */\n.sf-player--compact .sf-video-container::after {\n display: none;\n}\n\n/* Hide controls when minimized */\n.sf-player--minimized .sf-controls-container {\n display: none;\n}\n\n/* Hide controls when in compact mode */\n.sf-player--compact .sf-controls-container {\n display: none;\n}\n\n/* Only show the minimize button when hovering on minimized player */\n.sf-player--minimized .sf-player__minimize-button {\n opacity: 0;\n}\n\n.sf-player--minimized:hover .sf-player__minimize-button {\n opacity: 1;\n}\n\n/* Player root element */\n#sf-player-root {\n position: fixed;\n z-index: var(--sf-z-index-player);\n}\n\n/* Fixed positioning classes */\n.sf-player-root--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.sf-player-root--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n/* Player error message */\n.sf-player__error {\n padding: var(--sf-spacing-md);\n color: var(--sf-error-color);\n background-color: var(--sf-error-bg);\n border-radius: var(--sf-border-radius-md);\n margin: var(--sf-spacing-sm);\n font-size: var(--sf-font-size-sm);\n border-left: 4px solid var(--sf-error-color);\n}\n\n/* Minimize button */\n.sf-player__minimize-button {\n position: absolute;\n top: 8px;\n right: 4px;\n width: var(--sf-minimize-button-size);\n height: var(--sf-minimize-button-size);\n background: none !important;\n border-radius: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: calc(var(--sf-font-size-sm) + 4px);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n opacity: 0;\n}\n\n/* Minimize button background circle */\n.sf-player__minimize-button::before {\n content: '';\n position: absolute;\n width: 80%;\n height: 80%;\n background-color: rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n z-index: -1;\n transition: all var(--sf-transition-normal);\n}\n\n/* Minimize button hover state */\n.sf-player__minimize-button:hover {\n transform: scale(1.1);\n}\n\n/* Show minimize button on player hover */\n.sf-player:hover .sf-player__minimize-button {\n opacity: 1;\n}\n\n/* Mobile and touch device overrides for minimize button visibility */\n/* Ensure minimize button is always visible on touch devices, even when minimized */\n@media (pointer: coarse) {\n .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for touch devices */\n }\n \n .sf-player--minimized .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for touch devices */\n }\n}\n\n/* Ensure minimize button is always visible on mobile screens under 768px */\n@media (max-width: 768px) {\n .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for mobile */\n /* Position closer to top right corner on mobile */\n top: var(--sf-spacing-xs) !important; /* 4px from top instead of 16px */\n right: var(--sf-spacing-xs) !important; /* 4px from right instead of 12px */\n }\n \n .sf-player--minimized .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for mobile */\n /* Position closer to top right corner on mobile */\n top: var(--sf-spacing-xs) !important; /* 4px from top instead of 16px */\n right: var(--sf-spacing-xs) !important; /* 4px from right instead of 12px */\n }\n}\n\n/* Player title */\n.sf-player__title {\n position: absolute;\n top: var(--sf-spacing-md);\n left: var(--sf-spacing-md);\n color: var(--sf-text-color);\n font-size: var(--sf-font-size-md);\n font-weight: 600;\n z-index: var(--sf-z-index-controls);\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n max-width: 70%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Centered play/pause button overlay */\n.sf-player__center-play-button {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: var(--sf-play-button-size);\n height: var(--sf-play-button-size);\n background-color: rgba(0, 0, 0, 0.5);\n border-radius: var(--sf-border-radius-circle);\n display: none; /* Hidden by default */\n justify-content: center;\n align-items: center;\n z-index: calc(var(--sf-z-index-controls) + 10); /* Ensure higher z-index than other elements */\n color: white;\n border: none;\n font-size: var(--sf-control-button-size);\n cursor: pointer;\n transition: transform var(--sf-transition-normal), background-color var(--sf-transition-normal), opacity var(--sf-transition-normal);\n backdrop-filter: blur(1px);\n -webkit-backdrop-filter: blur(1px);\n pointer-events: auto; /* Enable pointer events to capture clicks */\n}\n\n/* Icon visibility control - use opacity for smooth transitions */\n.sf-player__center-play-button__pause-icon,\n.sf-player__center-play-button__play-icon {\n position: absolute;\n transition: opacity var(--sf-transition-normal);\n}\n\n.sf-player__center-play-button__pause-icon {\n opacity: 0;\n}\n\n.sf-player__center-play-button__play-icon {\n opacity: 1;\n}\n\n/* When playing, make button hoverable but invisible (desktop only) */\n@media (hover: hover) and (pointer: fine) {\n .sf-player--playing .sf-player__center-play-button {\n display: flex;\n opacity: 0;\n pointer-events: auto;\n }\n\n /* Show pause icon on hover when playing */\n .sf-player--playing .sf-player__center-play-button:hover {\n opacity: 1;\n }\n\n .sf-player--playing .sf-player__center-play-button:hover .sf-player__center-play-button__play-icon {\n opacity: 0;\n transition: none; /* Instant switch when hovering during playback */\n }\n\n .sf-player--playing .sf-player__center-play-button:hover .sf-player__center-play-button__pause-icon {\n opacity: 1;\n transition: none; /* Instant switch when hovering during playback */\n }\n\n /* Delay icon switch when not hovering during playback so pause icon stays visible during fade-out */\n .sf-player--playing .sf-player__center-play-button .sf-player__center-play-button__play-icon,\n .sf-player--playing .sf-player__center-play-button .sf-player__center-play-button__pause-icon {\n transition: opacity 0s 0.2s; /* Instant transition but delayed by button fade duration */\n }\n}\n\n/* Replay icon hidden by default */\n.sf-player__center-play-button__replay-icon {\n opacity: 0;\n position: absolute;\n transition: opacity var(--sf-transition-normal);\n}\n\n/* Show replay icon when video completed or waiting for interaction */\n.sf-player--completedWaitingForInteraction .sf-player__center-play-button__replay-icon,\n.sf-player--waitingForInteraction .sf-player__center-play-button__replay-icon {\n opacity: 1;\n transition: none;\n}\n\n/* Hide play/pause icons when showing replay */\n.sf-player--completedWaitingForInteraction .sf-player__center-play-button__play-icon,\n.sf-player--completedWaitingForInteraction .sf-player__center-play-button__pause-icon,\n.sf-player--waitingForInteraction .sf-player__center-play-button__play-icon,\n.sf-player--waitingForInteraction .sf-player__center-play-button__pause-icon {\n opacity: 0;\n transition: none;\n}\n\n/* Center play button visible state */\n.sf-player__center-play-button--visible {\n display: flex !important;\n}\n\n/* Center play button prominent state (for autoplay blocked, idle mode) */\n.sf-player__center-play-button--prominent {\n opacity: 1 !important;\n pointer-events: auto !important;\n}\n\n/* Center play button hover state */\n.sf-player__center-play-button:hover {\n transform: translate(-50%, -50%) scale(1.1);\n}\n\n/* Hide center play button in minimized state */\n.sf-player--minimized .sf-player__center-play-button {\n display: none !important;\n}\n\n/* Center play button with dynamic positioning when buttons are present */\n/* Positions button centered between top of player and top of first button */\n.sf-player__center-play-button--with-buttons {\n /* Available space above buttons = playerHeight - bottomSpacing - buttonContainerHeight */\n /* Center point = availableSpace / 2 */\n top: calc((var(--sf-player-height) - var(--sf-spacing-xl) - var(--sf-button-container-height, 0px)) / 2) !important;\n transform: translate(-50%, -50%) !important;\n}\n\n/* Maintain scale on hover for buttons with dynamic positioning */\n.sf-player__center-play-button--with-buttons:hover {\n transform: translate(-50%, -50%) scale(1.1) !important;\n}\n\n/* Exit button for minimized mode */\n.sf-player__exit-button {\n position: absolute;\n top: -22px; /* Position it above the player */\n right: 0;\n width: 22px;\n height: 22px;\n background-color: rgba(0, 0, 0, 0.5);\n border-radius: var(--sf-border-radius-circle);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: var(--sf-font-size-md);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n}\n\n.sf-player__exit-button svg {\n width: 18px;\n height: 18px;\n}\n\n/* Exit button hover state */\n.sf-player__exit-button:hover {\n transform: scale(1.1);\n background-color: rgba(0, 0, 0, 0.7);\n}\n\n/* Show exit button on minimized player hover */\n.sf-player--minimized:hover .sf-player__exit-button {\n opacity: 1;\n}\n\n/* Saltfish logo */\n.sf-player__logo {\n position: absolute;\n bottom: var(--sf-spacing-xs);\n left: 0;\n right: 0;\n height: 18px;\n z-index: var(--sf-z-index-controls);\n opacity: 0.7;\n transition: opacity var(--sf-transition-normal);\n cursor: pointer;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.sf-player__logo svg {\n width: 55px;\n height: 20px;\n}\n\n/* Logo hover state */\n.sf-player:hover .sf-player__logo {\n opacity: 0.9;\n}\n\n/* Hide logo when minimized */\n.sf-player--minimized .sf-player__logo {\n display: none;\n} \n /* \n * Video component styles for the Saltfish playlist Player\n * Following BEM naming convention\n */\n\n/* Video container */\n.sf-video-container {\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: var(--sf-border-radius-md);\n overflow: hidden;\n pointer-events: auto; /* Ensure clicks on video container are captured */\n background-color: #000; /* Fallback background for audio-only mode */\n /* Force clean border-radius clipping */\n isolation: isolate;\n transform: translateZ(0);\n -webkit-mask-image: -webkit-radial-gradient(white, black);\n /* Ensure video container and its children (including captions) sit above the gradient overlay */\n z-index: 3;\n /* Smooth transition for border-radius changes */\n transition: border-radius var(--sf-transition-slow);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-lg) var(--sf-border-radius-lg);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-lg) var(--sf-border-radius-lg);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Audio fallback poster image */\n.sf-video-container--audio-fallback {\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n background-image: var(--sf-audio-poster-url, none);\n}\n\n/* Audio fallback overlay */\n.sf-audio-fallback-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.6);\n z-index: 2;\n pointer-events: none;\n}\n\n/* Avatar mode overlay - no background, just container */\n.sf-audio-fallback-overlay--avatar {\n background: none;\n}\n\n.sf-audio-fallback-overlay__icon {\n width: 60px;\n height: 60px;\n margin-bottom: 16px;\n color: white;\n opacity: 0.9;\n}\n\n.sf-audio-fallback-overlay__text {\n color: white;\n font-size: 14px;\n text-align: center;\n padding: 0 20px;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\n opacity: 0.9;\n}\n\n.sf-audio-fallback-overlay__avatar {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 1;\n}\n\n/* Semi-transparent overlay on top of avatar */\n.sf-audio-fallback-overlay__dim {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.3);\n z-index: 2;\n}\n\n/* Soundbar-only mode overlay - dark background for soundbar visibility */\n.sf-audio-fallback-overlay--soundbar-only {\n background: rgba(0, 0, 0, 0.85);\n}\n\n/* Audio visualization soundbar container */\n.sf-audio-soundbar {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n height: 120px;\n width: auto;\n max-width: 300px;\n z-index: 3;\n position: relative;\n padding: 0 20px;\n}\n\n/* Individual soundbar frequency bar */\n.sf-audio-soundbar__bar {\n flex: 1;\n min-width: 8px;\n max-width: 20px;\n height: var(--sf-bar-height, 10%);\n background-color: var(--sf-bar-color, hsla(180, 70%, 60%, 0.3));\n border-radius: 4px;\n transition: height 0.05s ease-out, background-color 0.1s ease-out;\n transform-origin: center;\n will-change: height, background-color;\n}\n\n/* Video element */\n.sf-video-container__video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n background-color: white;\n /* Ensure video is visible on mobile */\n display: block;\n /* Add explicit positioning to ensure video is visible */\n position: relative;\n z-index: 1;\n /* Remove any border-radius - let container's overflow: hidden do the clipping */\n border-radius: 0;\n /* Force GPU acceleration for cleaner clipping with scale effect */\n transform: scale(1.04) translateZ(0);\n backface-visibility: hidden;\n transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n/* Video blur effect (for end-of-video transitions) */\n.sf-video-container__video--blurred {\n filter: blur(3px);\n transform: scale(1.04) translateZ(0);\n transition: filter 0.3s ease-out, transform 0.3s ease-out;\n}\n\n\n\n/* Mobile-specific video styles */\n@media (max-width: 768px) {\n\n .sf-video-container__video {\n /* Force video dimensions on mobile */\n width: 100% !important;\n height: 100% !important;\n object-fit: cover !important;\n /* Prevent video from being hidden */\n opacity: 1 !important;\n visibility: visible !important;\n position: relative !important;\n }\n \n /* Make controls more touch-friendly on mobile */\n .sf-video-container__controls {\n height: 5px; /* Thicker on mobile for easier touch */\n }\n \n /* Adjust pseudo-element for mobile touch target */\n .sf-video-container__controls::before {\n height: 14px; /* Larger touch target on mobile */\n }\n \n .sf-video-container__mute-button {\n /* Use CSS variable for consistent sizing */\n min-width: var(--sf-mute-button-size) !important;\n min-height: var(--sf-mute-button-size) !important;\n opacity: 1; /* Always visible on mobile (no hover) */\n }\n \n .sf-video-container__cc-button {\n /* Use CSS variable for consistent sizing */\n min-width: var(--sf-cc-button-size) !important;\n min-height: var(--sf-cc-button-size) !important;\n opacity: 1; /* Always visible on mobile (no hover) */\n }\n}\n\n/* Touch device specific styles */\n@media (pointer: coarse) {\n .sf-video-container__controls:hover {\n height: 5px; /* Keep consistent height on touch devices */\n }\n \n /* Maintain consistent clickable area on touch devices */\n .sf-video-container__controls::before,\n .sf-video-container__controls:hover::before {\n height: 14px; /* Consistent touch target */\n }\n \n .sf-video-container__mute-button {\n opacity: 1; /* Always show on touch devices */\n }\n \n .sf-video-container__cc-button {\n opacity: 1; /* Always show on touch devices */\n }\n \n .sf-video-container:hover .sf-video-container__mute-button {\n opacity: 1;\n }\n}\n\n/* Video in minimized state */\n.sf-player--minimized .sf-video-container {\n border-radius: var(--sf-border-radius-circle);\n cursor: pointer;\n z-index: var(--sf-z-index-base);\n width: 100%;\n height: 100%;\n /* Ensure clean clipping in circular state */\n isolation: isolate;\n transform: translateZ(0);\n}\n\n/* Hide gradient overlay when minimized */\n.sf-player--minimized .sf-video-container::after {\n display: none;\n}\n\n.sf-player--minimized .sf-video-container__video {\n border-radius: 0; /* Let container handle clipping */\n object-fit: cover;\n width: 100%;\n height: 100%;\n transform: scale(1.2) translateZ(0);\n}\n\n/* Hide progress bar in minimized state */\n.sf-player--minimized .sf-video-container__controls {\n display: none !important;\n}\n\n/* Also hide mute button in minimized state */\n.sf-player--minimized .sf-video-container__mute-button {\n display: none !important;\n}\n\n/* Also hide CC button in minimized state */\n.sf-player--minimized .sf-video-container__cc-button {\n display: none !important;\n}\n\n/* Progress bar container */\n.sf-video-container__controls {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n width: 100%;\n height: 4px;\n background-color: rgba(255, 255, 255, 0.3);\n z-index: var(--sf-z-index-controls);\n /* Match the container's top border-radius for seamless integration */\n border-radius: var(--sf-border-radius-md) var(--sf-border-radius-md) 0 0;\n cursor: pointer;\n /* Ensure pixel-perfect alignment and edge-to-edge coverage */\n transform: translateZ(0);\n backface-visibility: hidden;\n /* Smooth transition for height change on hover */\n transition: height 0.15s ease-in-out, background-color 0.15s ease-in-out;\n /* Ensure it covers the full width */\n margin: 0;\n box-sizing: border-box;\n}\n\n/* Invisible pseudo-element to extend clickable area downward */\n.sf-video-container__controls::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 10px; /* Visual height (4px) + extended clickable area (6px) */\n cursor: pointer;\n}\n\n/* Show slightly thicker progress bar on hover for better UX */\n.sf-video-container__controls:hover {\n height: 6px;\n background-color: rgba(255, 255, 255, 0.35);\n}\n\n/* Extend pseudo-element when progress bar grows on hover */\n.sf-video-container__controls:hover::before {\n height: 12px; /* Visual height (6px) + extended clickable area (6px) */\n}\n\n/* Progress indicator */\n.sf-video-container__progress {\n height: 100%;\n background: linear-gradient(90deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.85) 100%);\n width: var(--sf-progress-width, 0%);\n transition: var(--sf-progress-transition, width 0.1s linear);\n /* Only apply top-left border-radius to maintain seamless look */\n border-radius: var(--sf-border-radius-md) 0 0 0;\n cursor: pointer;\n transform-origin: left;\n /* Ensure smooth rendering */\n will-change: width;\n}\n\n/* Mute button */\n.sf-video-container__mute-button {\n position: absolute;\n top: calc(8px + var(--sf-minimize-button-size) + 6px);\n right: 4px;\n width: var(--sf-mute-button-size);\n height: var(--sf-mute-button-size);\n background: none !important;\n border-radius: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: calc(var(--sf-font-size-md) + 2px);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n opacity: 0;\n}\n\n/* Mute button background circle */\n.sf-video-container__mute-button::before {\n content: '';\n position: absolute;\n width: 80%;\n height: 80%;\n background-color: rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n z-index: -1;\n transition: all var(--sf-transition-normal);\n}\n\n/* Mute button hover state */\n.sf-video-container__mute-button:hover {\n transform: scale(1.1);\n}\n\n/* Show mute button on container hover */\n.sf-video-container:hover .sf-video-container__mute-button {\n opacity: 1;\n}\n\n/* CC button */\n.sf-video-container__cc-button {\n position: absolute;\n top: calc(8px + var(--sf-minimize-button-size) + 6px + var(--sf-mute-button-size) + 6px);\n right: 4px;\n width: var(--sf-cc-button-size);\n height: var(--sf-cc-button-size);\n background: none !important;\n border-radius: 0;\n padding: 0; /* Remove default button padding */\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: calc(var(--sf-font-size-md) + 2px);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n opacity: 0;\n}\n\n/* CC button background circle */\n.sf-video-container__cc-button::before {\n content: '';\n position: absolute;\n width: 80%;\n height: 80%;\n background-color: rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n z-index: -1;\n transition: all var(--sf-transition-normal);\n}\n\n.sf-video-container__cc-button svg {\n display: block;\n margin: auto;\n width: 60%;\n height: 60%;\n}\n\n/* CC button hover state */\n.sf-video-container__cc-button:hover {\n transform: scale(1.1);\n}\n\n/* Compact mode styling - circular border-radius for video container */\n.sf-player--compact .sf-video-container {\n border-radius: var(--sf-border-radius-circle);\n}\n\n/* Hide gradient overlay in compact mode (already handled in _player.css but kept for clarity) */\n.sf-player--compact .sf-video-container::after {\n display: none;\n}\n\n/* Hide mute and cc buttons in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-video-container__mute-button,\n.sf-player--autoplayBlocked .sf-video-container__cc-button,\n.sf-player--idleMode .sf-video-container__mute-button,\n.sf-player--idleMode .sf-video-container__cc-button {\n display: none !important;\n}\n\n/* Show mute and cc buttons on hover in playing/paused states */\n.sf-player--playing .sf-video-container:hover .sf-video-container__mute-button,\n.sf-player--playing .sf-video-container:hover .sf-video-container__cc-button,\n.sf-player--paused .sf-video-container:hover .sf-video-container__mute-button,\n.sf-player--paused .sf-video-container:hover .sf-video-container__cc-button {\n opacity: 1;\n} \n /* \n * Controls component styles for the Saltfish playlist Player\n * Following BEM naming convention\n */\n\n/* Main controls container */\n.sf-controls-container {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: transparent;\n z-index: var(--sf-z-index-controls);\n pointer-events: auto;\n}\n\n/* Play button */\n.sf-controls-container__play-button {\n background-color: rgba(0, 0, 0, 0.6);\n border: none;\n color: var(--sf-text-color);\n font-size: var(--sf-control-button-size);\n cursor: pointer;\n width: var(--sf-play-button-size);\n height: var(--sf-play-button-size);\n border-radius: var(--sf-border-radius-circle);\n display: flex;\n justify-content: center;\n align-items: center;\n transition: transform var(--sf-transition-normal), background-color var(--sf-transition-normal);\n padding-left: 4px; /* Optical centering for play icon */\n}\n\n/* Button hover state */\n.sf-controls-container__play-button:hover {\n background-color: rgba(0, 0, 0, 0.4);\n transform: scale(1.1);\n}\n\n/* Button container for interactive buttons */\n.sf-controls-container__buttons {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: var(--sf-spacing-md);\n}\n\n/* Interactive button */\n.sf-controls-container__interactive-button {\n background-color: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: white;\n border: none;\n border-radius: var(--sf-border-radius-md);\n padding: var(--sf-spacing-xs) var(--sf-spacing-md);\n font-size: var(--sf-font-size-sm);\n cursor: pointer;\n transition: background-color var(--sf-transition-normal), transform var(--sf-transition-fast);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n\n.sf-controls-container__interactive-button:hover {\n background-color: rgba(255, 255, 255, 0.3);\n transform: translateY(-2px);\n}\n\n/* \n * Choice buttons container and buttons - positioned inside player\n */\n\n/* Choice buttons container - positioned inside the player at the bottom */\n.sf-choice-buttons-container {\n position: absolute;\n bottom: var(--sf-spacing-xl);\n left: 50%;\n transform: translateX(-50%);\n width: calc(100% - var(--sf-spacing-lg));\n max-width: calc(100% - var(--sf-spacing-lg));\n z-index: calc(var(--sf-z-index-controls) + 1);\n gap: var(--sf-spacing-sm);\n pointer-events: auto;\n align-items: center;\n display: flex;\n flex-direction: column;\n /* Ensure container is fully transparent */\n background: transparent;\n border: none;\n outline: none;\n}\n\n/* Choice buttons container with scrolling for 5+ buttons */\n.sf-choice-buttons-container--scrollable {\n max-height: 176px; /* Show ~4 buttons with gaps (4 * 36px button + 4 * 8px gap) */\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: thin; /* Show thin scrollbar in Firefox */\n scrollbar-color: rgba(255, 255, 255, 0.2) transparent; /* More transparent Firefox scrollbar */\n scroll-behavior: smooth;\n /* Important: Use block display for scrollable container */\n display: block !important;\n}\n\n/* Style webkit scrollbar to be visible but subtle */\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar {\n width: 4px;\n}\n\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2); /* More transparent */\n border-radius: 2px;\n}\n\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.4); /* Still subtle on hover */\n}\n\n/* Removed fade gradient to keep container fully transparent */\n\n/* Choice button styles - solid rounded buttons matching the image */\n.sf-choice-button {\n width: 100%;\n max-width: none;\n background: rgba(0, 0, 0, 4);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: white;\n border: none;\n border-radius: 24px; /* More rounded for pill shape */\n padding: var(--sf-spacing-md) var(--sf-spacing-md);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: center;\n outline: none;\n font-family: inherit;\n margin-bottom: 0;\n position: relative;\n overflow: hidden;\n opacity: 0; /* Start hidden for animation */\n pointer-events: none;\n /* Animation will be triggered by JavaScript when video reaches 90% */\n}\n\n/* Add margin between buttons in scrollable container */\n.sf-choice-buttons-container--scrollable .sf-choice-button {\n margin-bottom: var(--sf-spacing-sm);\n}\n\n/* Remove margin from last button */\n.sf-choice-buttons-container--scrollable .sf-choice-button:last-child {\n margin-bottom: 0;\n}\n\n/* Hover state for buttons */\n.sf-choice-button:hover {\n background: rgba(0, 0, 0, 0.9);\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.8);\n}\n\n/* Active state for all buttons */\n.sf-choice-button:active {\n transform: translateY(0) scale(0.98);\n transition: all 0.1s ease;\n}\n\n/* Remove specific action type styling - use consistent dark buttons */\n.sf-choice-button--goto,\n.sf-choice-button--url,\n.sf-choice-button--next,\n.sf-choice-button--dom,\n.sf-choice-button--function {\n background: rgba(0, 0, 0, 0.4);\n border: none;\n}\n\n.sf-choice-button--goto:hover,\n.sf-choice-button--url:hover,\n.sf-choice-button--next:hover,\n.sf-choice-button--dom:hover,\n.sf-choice-button--function:hover {\n background: rgba(0, 0, 0, 0.9);\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n}\n\n/* Hide choice buttons in minimized state */\n.sf-player--minimized .sf-choice-buttons-container {\n display: none !important;\n}\n\n/* Hide choice buttons in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-choice-buttons-container,\n.sf-player--idleMode .sf-choice-buttons-container {\n display: none !important;\n}\n\n/* Smaller mobile screens - maintain same layout but with tighter spacing */\n@media (max-width: 480px) {\n .sf-choice-buttons-container {\n bottom: var(--sf-spacing-sm);\n width: calc(100% - var(--sf-spacing-md));\n max-width: calc(100% - var(--sf-spacing-md));\n gap: calc(var(--sf-spacing-xs) + 2px);\n }\n \n .sf-choice-button {\n padding: var(--sf-spacing-sm) var(--sf-spacing-sm);\n font-size: 11px;\n border-radius: 20px;\n }\n}\n\n/* Touch device specific adjustments */\n@media (pointer: coarse) {\n .sf-choice-buttons-container {\n gap: var(--sf-spacing-sm);\n }\n \n .sf-choice-button {\n min-height: 44px; /* Apple's recommended minimum touch target size */\n padding: var(--sf-spacing-md) var(--sf-spacing-md);\n }\n}\n\n/* Button fade-in animation */\n@keyframes buttonFadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Animation class that will be added by JavaScript at 90% video progress */\n.sf-choice-button.sf-show-button {\n animation: buttonFadeIn 0.3s ease-out forwards;\n pointer-events: auto;\n}\n\n/* Staggered animation delays for multiple buttons when shown */\n.sf-choice-button.sf-show-button:nth-child(1) {\n animation-delay: 0s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(2) {\n animation-delay: 0.15s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(3) {\n animation-delay: 0.3s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(4) {\n animation-delay: 0.45s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(5) {\n animation-delay: 0.6s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(6) {\n animation-delay: 0.75s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(7) {\n animation-delay: 0.9s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(8) {\n animation-delay: 1.05s;\n}\n\n/* Scroll indicator arrow */\n.sf-scroll-indicator {\n position: absolute;\n bottom: calc(var(--sf-spacing-xl) - 25px);\n left: 50%;\n transform: translateX(-50%);\n color: rgba(255, 255, 255, 0.6);\n font-size: 20px;\n pointer-events: none;\n z-index: calc(var(--sf-z-index-controls) + 2);\n transition: opacity 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0; /* Start hidden */\n}\n\n/* Show scroll indicator with animation - appears after buttons */\n.sf-scroll-indicator.sf-show-scroll-indicator {\n animation: scrollIndicatorFadeIn 0.4s ease-out 1.2s forwards, bounceArrow 1.5s ease-in-out 1.6s infinite;\n}\n\n/* Hide arrow when scrolled to bottom */\n.sf-scroll-indicator--hidden {\n opacity: 0;\n}\n\n/* Fade in animation for scroll indicator */\n@keyframes scrollIndicatorFadeIn {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n/* Bounce animation for the arrow */\n@keyframes bounceArrow {\n 0%, 100% {\n transform: translateX(-50%) translateY(0);\n }\n 50% {\n transform: translateX(-50%) translateY(5px);\n }\n}\n\n/* Hide scroll indicator in minimized state */\n.sf-player--minimized .sf-scroll-indicator {\n display: none !important;\n}\n\n/* Hide scroll indicator in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-scroll-indicator,\n.sf-player--idleMode .sf-scroll-indicator {\n display: none !important;\n} \n /* \n * Transcript component styles for the Saltfish Playlist Player\n * Following BEM naming convention\n */\n\n/* Transcript container */\n.sf-transcript {\n position: absolute;\n bottom: 40px; /* Above the progress bar */\n left: 0;\n right: 0;\n max-height: 200px;\n background: transparent;\n margin: 0 var(--sf-spacing-md);\n overflow: hidden;\n z-index: var(--sf-z-index-controls);\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.3s ease-out;\n pointer-events: none;\n}\n\n/* Visible state */\n.sf-transcript--visible {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n/* Transcript content */\n.sf-transcript__content {\n max-height: 180px;\n overflow: visible;\n padding: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 100%;\n text-align: center;\n}\n\n/* Webkit scrollbar styling */\n.sf-transcript__content::-webkit-scrollbar {\n width: 4px;\n}\n\n.sf-transcript__content::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sf-transcript__content::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n}\n\n.sf-transcript__content::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.5);\n}\n\n/* Word-by-word display container - progressive reveal style */\n.sf-transcript__word-container {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 0.04em; /* Much tighter gap to compensate for inverse scaling effect */\n min-height: 60px;\n padding: 0 var(--sf-spacing-md);\n flex-wrap: nowrap;\n overflow: hidden;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n text-align: center;\n transition: opacity 0.15s ease-in-out; /* Smooth fade during window transitions */\n}\n\n/* Hidden state for fade transitions */\n.sf-transcript__word-container--hidden {\n opacity: 0;\n}\n\n/* Individual word styling - base state (hidden by default) */\n.sf-transcript__word {\n color: rgba(255, 255, 255, 0.65);\n font-size: 20px; /* Increased from 18px to compensate for 0.893 scale (20 * 0.893 ≈ 18px) */\n font-weight: 500; /* Set to 500 from start to prevent pixel shift on activation */\n line-height: 1.3;\n white-space: nowrap;\n text-align: center;\n opacity: 0;\n transform: scale(0.893) translateY(0); /* Scaled down - active word will be normal size (1/1.12 ≈ 0.893) */\n transition: opacity 0.2s ease, color 0.2s ease, text-shadow 0.2s ease, transform 0.2s ease;\n padding-left: 0.12em; /* Consistent padding */\n padding-right: 0.12em;\n}\n\n/* Visible state - word has appeared */\n.sf-transcript__word--visible {\n opacity: 0.8;\n transform: scale(0.893) translateY(0); /* Keep scaled down */\n}\n\n/* Active word (currently speaking) - highlighted at normal size (inverse scale approach) */\n.sf-transcript__word--active {\n color: rgba(255, 255, 255, 1) !important;\n opacity: 1 !important;\n transform: scale(1) translateY(0); /* Normal size - appears 12% larger relative to scaled-down neighbors */\n text-shadow: 0 0 20px rgba(255, 255, 255, 0.3);\n /* font-weight removed - already 500 from base to prevent pixel shift */\n}\n\n/* Legacy segment styling (kept for compatibility) */\n.sf-transcript__segment {\n color: rgba(255, 255, 255);\n font-size: var(--sf-font-size-sm);\n line-height: 1.4;\n padding: var(--sf-spacing-xs) 0;\n cursor: pointer;\n transition: all 0.2s ease;\n padding-left: var(--sf-spacing-xs);\n padding-right: var(--sf-spacing-xs);\n}\n\n/* CC button styling removed - now handled via icon toggling */\n\n/* Mobile responsive styles */\n@media (max-width: 768px) {\n .sf-transcript {\n bottom: 35px; /* Positioned lower on mobile for better visibility */\n margin: 0 var(--sf-spacing-sm);\n max-height: 150px; /* Smaller on mobile */\n }\n\n .sf-transcript__content {\n max-height: 130px;\n padding: var(--sf-spacing-sm);\n }\n\n .sf-transcript__word-container {\n min-height: 50px;\n padding: 0 var(--sf-spacing-sm);\n gap: 0.2em; /* Tighter gap for mobile */\n }\n \n .sf-transcript__word {\n font-size: var(--sf-font-size-md);\n /* font-weight already 500 from base styles */\n }\n \n .sf-transcript__segment {\n font-size: var(--sf-font-size-xs);\n padding: var(--sf-spacing-xs) var(--sf-spacing-sm);\n }\n}\n\n/* Touch device optimizations */\n@media (pointer: coarse) {\n .sf-transcript__segment {\n padding: var(--sf-spacing-sm) var(--sf-spacing-xs);\n min-height: 44px; /* Larger touch target */\n display: flex;\n align-items: center;\n }\n}\n\n/* Hide transcript in minimized state */\n.sf-player--minimized .sf-transcript {\n display: none !important;\n}\n\n/* Hide transcript in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-transcript,\n.sf-player--idleMode .sf-transcript {\n display: none !important;\n}\n\n/* Animation for transcript appearance */\n@keyframes transcriptFadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes transcriptFadeOut {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(20px);\n }\n}\n /* \n * Error Display component styles for the Saltfish playlist Player\n * Clean and subtle full-widget error overlay\n */\n\n/* Error display overlay - covers full widget */\n.sf-error-display {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: calc(var(--sf-z-index-controls) + 30);\n border-radius: var(--sf-border-radius-lg);\n opacity: 0;\n transition: opacity var(--sf-transition-slow);\n pointer-events: auto;\n}\n\n/* Error display visible state */\n.sf-error-display--visible {\n opacity: 1;\n}\n\n/* Error content container */\n.sf-error-display__content {\n background-color: rgba(20, 20, 20, 0.9);\n border-radius: var(--sf-border-radius-md);\n padding: var(--sf-spacing-lg) var(--sf-spacing-xl);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.08);\n transform: translateY(8px);\n transition: transform var(--sf-transition-slow);\n max-width: 85%;\n text-align: center;\n}\n\n/* Error content visible animation */\n.sf-error-display--visible .sf-error-display__content {\n transform: translateY(0);\n}\n\n/* Error message */\n.sf-error-display__message {\n color: rgba(255, 255, 255, 0.95);\n font-size: var(--sf-font-size-md);\n line-height: 1.5;\n margin: 0;\n text-align: center;\n font-weight: 500;\n}\n\n/* Mobile responsive adjustments */\n@media (max-width: 768px) {\n .sf-error-display__content {\n padding: var(--sf-spacing-md) var(--sf-spacing-lg);\n max-width: 90%;\n }\n\n .sf-error-display__message {\n font-size: var(--sf-font-size-sm);\n }\n}\n\n/* Minimized player state adjustments */\n.sf-player--minimized .sf-error-display__content {\n padding: var(--sf-spacing-sm) var(--sf-spacing-md);\n max-width: 80%;\n}\n\n.sf-player--minimized .sf-error-display__message {\n font-size: var(--sf-font-size-sm);\n font-weight: 400;\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n .sf-error-display__content {\n background-color: rgba(0, 0, 0, 0.95);\n border: 2px solid rgba(255, 255, 255, 0.3);\n }\n\n .sf-error-display__message {\n color: rgba(255, 255, 255, 0.95);\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n .sf-error-display,\n .sf-error-display__content {\n transition: none;\n }\n}\n /**\n * Loading spinner styles\n */\n\n.sf-loading-spinner {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(2px);\n z-index: 100;\n border-radius: 12px;\n opacity: 1 !important; /* Always visible when shown, overrides parent opacity */\n}\n\n.sf-loading-spinner__content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n}\n\n.sf-loading-spinner__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #000000;\n opacity: 0.9;\n}\n\n.sf-loading-spinner__icon svg {\n width: 60px;\n height: 60px;\n /* Remove the rotation animation since we now have internal SVG animation */\n}\n\n.sf-loading-spinner__text {\n color: #333333;\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n opacity: 0.8;\n letter-spacing: 0.5px;\n}\n\n/* CSS keyframe animation removed - using SVG animateTransform instead */\n\n/* Responsive adjustments */\n@media (max-width: 480px) {\n .sf-loading-spinner__content {\n padding: 20px;\n gap: 10px;\n }\n \n .sf-loading-spinner__icon svg {\n width: 50px;\n height: 50px;\n }\n \n .sf-loading-spinner__text {\n font-size: 13px;\n }\n}\n /*\n * Cursor animation component styles for the Saltfish playlist Player\n * CSP-compliant: All styles use CSS classes and CSS custom properties instead of inline styles\n */\n\n/* Base cursor element */\n.sf-cursor {\n position: fixed;\n top: 0;\n left: 0;\n width: 36px;\n height: 36px;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n}\n\n.sf-cursor--visible {\n display: block;\n}\n\n/* Selection element */\n.sf-selection {\n position: fixed;\n pointer-events: none;\n display: none;\n z-index: 9999998;\n border: 2px solid var(--sf-selection-color, #ff7614);\n background: var(--sf-selection-bg-color, rgba(255, 118, 20, 0.1));\n border-radius: 4px;\n left: var(--sf-selection-left, 0);\n top: var(--sf-selection-top, 0);\n width: var(--sf-selection-width, 0);\n height: var(--sf-selection-height, 0);\n}\n\n.sf-selection--visible {\n display: block;\n}\n\n/* Flashlight overlay */\n.sf-flashlight-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 999997;\n display: none;\n background: var(--sf-flashlight-bg, radial-gradient(circle 150px at 50% 50%, transparent 0%, rgba(0, 0, 0, 0.4) 100%));\n clip-path: var(--sf-flashlight-clip, none);\n}\n\n.sf-flashlight-overlay--visible {\n display: block;\n}\n\n /**\n * Compact Label Styles\n * Label that appears next to the player when in compact first step mode\n * Position adapts based on player placement (left/right)\n */\n\n.sf-compact-label {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n\n /* Typography */\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n font-weight: 500;\n line-height: 1.4;\n color: #ffffff;\n\n /* Visual styling */\n background: rgba(0, 0, 0, 0.85);\n backdrop-filter: blur(10px);\n padding: 10px 16px;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3),\n 0 0 0 1px rgba(255, 255, 255, 0.1);\n\n /* Ensure it doesn't wrap */\n white-space: nowrap;\n\n /* Layering */\n z-index: 10;\n\n /* Pointer events - will be enabled via sf-compact-label--clickable class */\n pointer-events: none;\n user-select: none;\n\n /* Smooth transitions for hover effects */\n transition: transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\n box-shadow 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\n background 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n/* Clickable state - enables pointer events and cursor */\n.sf-compact-label--clickable {\n cursor: pointer;\n pointer-events: auto;\n}\n\n/* Position to the LEFT of player (when player is on the right side) */\n.sf-compact-label--left {\n right: calc(100% + 16px); /* 16px spacing from player edge */\n animation: sf-compact-label-enter-from-left 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Position to the RIGHT of player (when player is on the left side) */\n.sf-compact-label--right {\n left: calc(100% + 16px); /* 16px spacing from player edge */\n animation: sf-compact-label-enter-from-right 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Entrance animation from LEFT - slide in from left with fade */\n@keyframes sf-compact-label-enter-from-left {\n 0% {\n opacity: 0;\n transform: translateY(-50%) translateX(-20px);\n }\n 100% {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n }\n}\n\n/* Entrance animation from RIGHT - slide in from right with fade */\n@keyframes sf-compact-label-enter-from-right {\n 0% {\n opacity: 0;\n transform: translateY(-50%) translateX(20px);\n }\n 100% {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n }\n}\n\n/* Hover effect - only applies when label is clickable (pointer-events: auto) */\n.sf-compact-label--left:hover,\n.sf-compact-label--right:hover {\n background: rgba(0, 0, 0, 0.95);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4),\n 0 0 0 1px rgba(255, 255, 255, 0.2),\n 0 0 25px rgba(255, 255, 255, 0.08);\n}\n\n.sf-compact-label--left:hover {\n transform: translateY(-50%) translateX(-2px);\n}\n\n.sf-compact-label--right:hover {\n transform: translateY(-50%) translateX(2px);\n}\n\n/* Active/click state */\n.sf-compact-label--left:active,\n.sf-compact-label--right:active {\n transform: translateY(-50%) scale(0.98);\n}\n\n/* Mobile adjustments */\n@media (max-width: 768px) {\n .sf-compact-label {\n font-size: 12px;\n padding: 8px 12px;\n }\n\n .sf-compact-label--left {\n right: calc(100% + 12px); /* Slightly less spacing on mobile */\n }\n\n .sf-compact-label--right {\n left: calc(100% + 12px); /* Slightly less spacing on mobile */\n }\n}\n\n/* Very small screens - keep to side with tighter spacing */\n@media (max-width: 480px) {\n .sf-compact-label {\n /* Use most of the available screen width - on 390px wide screen this gives ~270px */\n max-width: calc(100vw - 90px - 20px - 8px - 10px); /* viewport - player - margin - spacing - small buffer */\n /* Keep nowrap - we have plenty of space on mobile screens */\n }\n\n .sf-compact-label--left {\n right: calc(100% + 8px); /* Reduce spacing slightly for mobile */\n }\n\n .sf-compact-label--right {\n left: calc(100% + 8px); /* Reduce spacing slightly for mobile */\n }\n}\n\n\n /* \n * Transitions and animations for Saltfish playlist Player\n */\n\n/* Fade in animation */\n@keyframes sf-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.sf-fade-in {\n animation: sf-fade-in 0.3s ease-in-out forwards;\n}\n\n/* Slide in from bottom animation */\n@keyframes sf-slide-in-bottom {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n\n.sf-slide-in-bottom {\n animation: sf-slide-in-bottom 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Slide in from right animation */\n@keyframes sf-slide-in-right {\n from { transform: translateX(100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n}\n\n.sf-slide-in-right {\n animation: sf-slide-in-right 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Scale in animation */\n@keyframes sf-scale-in {\n from { transform: scale(0.8); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n}\n\n.sf-scale-in {\n animation: sf-scale-in 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Scale out animation */\n@keyframes sf-scale-out {\n from { transform: scale(1); opacity: 1; }\n to { transform: scale(0.8); opacity: 0; }\n}\n\n.sf-scale-out {\n animation: sf-scale-out 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n} \n"}}class Ct{static isMobile(){return this.getDeviceInfo().isMobile}static isTablet(){return this.getDeviceInfo().isTablet}static isDesktop(){return this.getDeviceInfo().isDesktop}static isTouchDevice(){return this.getDeviceInfo().isTouchDevice}static getOrientation(){return this.getDeviceInfo().orientation}static getDeviceInfo(){if(this.cachedDeviceInfo)return this.cachedDeviceInfo.orientation=this.detectOrientation(),this.cachedDeviceInfo;const t="undefined"!=typeof navigator?navigator.userAgent:"",e=this.detectTouchSupport(),{width:n,height:i}=this.getScreenDimensions(),s=/iPad|Android(?!.*Mobile)|Tablet|tablet/i,r=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i.test(t)&&!s.test(t),a=s.test(t),o=this.getScreenSize(n,i),l="small"===o&&Math.min(n,i)<768,c=r||l&&e,d=a||"medium"===o&&!l&&e&&!c,h={isMobile:c,isTablet:d,isDesktop:!c&&!d,isTouchDevice:e,screenSize:o,orientation:this.detectOrientation(),userAgent:t};return this.cachedDeviceInfo=h,h}static detectTouchSupport(){return"undefined"!=typeof window&&("ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0)}static getScreenDimensions(){return"undefined"==typeof window?{width:1920,height:1080}:{width:window.innerWidth||document.documentElement.clientWidth||1920,height:window.innerHeight||document.documentElement.clientHeight||1080}}static getScreenSize(t,e){const n=Math.min(t,e);return n<768?"small":n<1024?"medium":"large"}static detectOrientation(){if("undefined"==typeof window)return"landscape";const{width:t,height:e}=this.getScreenDimensions();return e>t?"portrait":"landscape"}static clearCache(){this.cachedDeviceInfo=null}static onDeviceChange(t){if("undefined"==typeof window)return()=>{};const e=()=>{try{this.clearCache(),t(this.getDeviceInfo())}catch(t){console.warn("DeviceDetector: Error in device change handler:",t)}};return window.addEventListener("orientationchange",e),window.addEventListener("resize",e),()=>{window.removeEventListener("orientationchange",e),window.removeEventListener("resize",e)}}}e(Ct,"cachedDeviceInfo",null);const _t=Object.freeze(Object.defineProperty({__proto__:null,DeviceDetector:Ct,isDeviceCompatible:t=>{if(!t||"both"===t)return!0;const e=Ct.getDeviceInfo();return"mobile"===t?e.isMobile||e.isTablet:"desktop"===t&&e.isDesktop}},Symbol.toStringTag,{value:"Module"})),kt=class t{constructor(){e(this,"transcriptContainer",null),e(this,"transcriptContent",null),e(this,"ccButton",null),e(this,"isVisible",!0),e(this,"currentTranscript",null),e(this,"chunks",[]),e(this,"videoElement",null),e(this,"timeUpdateListener",null),e(this,"videoManager",null),e(this,"firstWordForceDisplayUntil",0),e(this,"isNewVideo",!1),e(this,"lastDisplayedChunkIndex",-1),e(this,"animationFrameId",null),e(this,"isAnimationLoopActive",!1),e(this,"currentWindowStartIndex",-1),e(this,"currentWindowEndIndex",-1)}setup(t,e,n){this.videoElement=t,this.ccButton=e,this.videoManager=n,this.ccButton.addEventListener("click",this.handleCCButtonClick.bind(this)),this.timeUpdateListener=this.handleTimeUpdate.bind(this),this.videoElement.addEventListener("timeupdate",this.timeUpdateListener)}updateVideoElement(t){this.videoElement&&this.timeUpdateListener&&this.videoElement.removeEventListener("timeupdate",this.timeUpdateListener),this.videoElement=t,this.videoElement&&this.timeUpdateListener&&this.videoElement.addEventListener("timeupdate",this.timeUpdateListener)}loadTranscript(e,n=!0){this.transcriptContent&&(this.transcriptContent.innerHTML=""),this.lastDisplayedChunkIndex=-1,this.currentWindowStartIndex=-1,this.currentWindowEndIndex=-1,this.currentTranscript=e,e?(this.createTranscriptUI(),this.chunks=e.chunks||[],this.isNewVideo=!0,this.firstWordForceDisplayUntil=Date.now()+500,this.setupWordDisplay(),null!==t.userCaptionPreference?(this.isVisible=t.userCaptionPreference,this.isVisible):(this.isVisible=n,this.isVisible),this.updateCCButtonState(!0),this.isVisible?this.showTranscript():this.hideTranscript(),this.chunks.length,this.isVisible):(this.updateCCButtonState(!1),this.hideTranscript())}toggleVisibility(){this.currentTranscript&&(this.isVisible=!this.isVisible,t.userCaptionPreference=this.isVisible,this.isVisible,this.isVisible?(this.showTranscript(),this.startAnimationLoop()):(this.hideTranscript(),this.stopAnimationLoop()),this.updateCCButtonState(!!this.currentTranscript),this.isVisible)}handleCCButtonClick(t){t.preventDefault(),t.stopPropagation(),this.toggleVisibility()}handleTimeUpdate(t){!this.isAnimationLoopActive&&this.isVisible&&this.chunks.length>0&&this.startAnimationLoop()}startAnimationLoop(){if(this.isAnimationLoopActive)return;this.isAnimationLoopActive=!0;const t=()=>{if(!this.currentTranscript||!this.isVisible||!this.videoElement||0===this.chunks.length)return void this.stopAnimationLoop();const e=this.videoElement.currentTime;let n=this.findActiveChunkIndex(e);const i=Date.now();this.isNewVideo&&i<this.firstWordForceDisplayUntil&&this.chunks.length>0?n=0:this.isNewVideo&&i>=this.firstWordForceDisplayUntil&&(this.isNewVideo=!1),this.updateIntelligentWordDisplay(n),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopAnimationLoop(){null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.isAnimationLoopActive=!1}findActiveChunkIndex(t){if(0===this.chunks.length)return-1;for(let e=0;e<this.chunks.length;e++){const n=this.chunks[e];if(t>=n.start&&t<=n.end)return e}if(t<this.chunks[0].start)return 0;if(t>this.chunks[this.chunks.length-1].end)return this.chunks.length-1;for(let e=0;e<this.chunks.length-1;e++)if(t>this.chunks[e].end&&t<this.chunks[e+1].start)return this.chunks[e+1].start-t<.1?e+1:t-this.chunks[e].end<.1?e:e+1;return-1}handleStateChange(t){if(this.currentTranscript,this.chunks.length,this.currentTranscript&&0!==this.chunks.length)return"waitingForInteraction"===t||"completedWaitingForInteraction"===t?(this.transcriptContent&&(this.transcriptContent.innerHTML=""),void this.stopAnimationLoop()):void(this.isVisible?(this.isVisible,this.showTranscript(),this.startAnimationLoop()):(this.isVisible,this.hideTranscript(),this.stopAnimationLoop()));this.stopAnimationLoop()}updateIntelligentWordDisplay(t){if(this.transcriptContent&&t!==this.lastDisplayedChunkIndex)return t>=0&&t<this.chunks.length&&this.chunks[t]?(t>=this.currentWindowStartIndex&&t<=this.currentWindowEndIndex&&-1!==this.currentWindowStartIndex?this.updateHighlightInWindow(t):this.createNewWindow(t),void(this.lastDisplayedChunkIndex=t)):(this.lastDisplayedChunkIndex=-1,void(this.transcriptContent.innerHTML=""))}updateHighlightInWindow(t){if(!this.transcriptContent)return;const e=this.transcriptContent.querySelectorAll(".sf-transcript__word"),n=t-this.currentWindowStartIndex;e.forEach(((t,e)=>{t.classList.remove("sf-transcript__word--active"),e<=n?t.classList.add("sf-transcript__word--visible"):t.classList.remove("sf-transcript__word--visible")})),e[n]&&e[n].classList.add("sf-transcript__word--active")}createNewWindow(t){if(!this.transcriptContent)return;const e=this.calculateWordWindow(t);this.currentWindowStartIndex=e.startIndex,this.currentWindowEndIndex=e.endIndex;const n=this.transcriptContent.querySelector(".sf-transcript__word-container"),i=()=>{const n=document.createElement("div");n.className="sf-transcript__word-container";const i=t-e.startIndex;for(let s=e.startIndex;s<=e.endIndex;s++){const r=this.chunks[s],a=document.createElement("span");let o="sf-transcript__word";s-e.startIndex<=i&&(o+=" sf-transcript__word--visible"),s===t&&(o+=" sf-transcript__word--active"),a.className=o,a.textContent=r.text,n.appendChild(a)}return n};if(n)n.classList.add("sf-transcript__word-container--hidden"),setTimeout((()=>{if(!this.transcriptContent)return;this.transcriptContent.innerHTML="";const t=i();t.classList.add("sf-transcript__word-container--hidden"),this.transcriptContent.appendChild(t),requestAnimationFrame((()=>{t.classList.remove("sf-transcript__word-container--hidden")}))}),150);else{const t=i();this.transcriptContent.appendChild(t)}}calculateWordWindow(t){if(t<0||t>=this.chunks.length)return{startIndex:-1,endIndex:-1};let e=t,n=t,i=this.chunks[t].text.length;const s=this.chunks[t].text.trim();if(s.endsWith(".")||s.endsWith("!")||s.endsWith("?"))return{startIndex:e,endIndex:n};for(;n-e+1<4&&n+1<this.chunks.length;){const t=this.chunks[n+1].text,e=Math.ceil(1.12*t.length);if(i+e>18)break;n++,i+=e;const s=t.trim();if(s.endsWith(".")||s.endsWith("!")||s.endsWith("?"))break}return{startIndex:e,endIndex:n}}createTranscriptUI(){var t;this.transcriptContainer&&this.transcriptContainer.parentNode&&(this.transcriptContainer.parentNode.removeChild(this.transcriptContainer),this.transcriptContainer=null,this.transcriptContent=null);const e=null==(t=this.videoElement)?void 0:t.closest(".sf-video-container");e&&(this.transcriptContainer=document.createElement("div"),this.transcriptContainer.className="sf-transcript",this.transcriptContainer.classList.add("sf-hidden"),this.transcriptContent=document.createElement("div"),this.transcriptContent.className="sf-transcript__content",this.transcriptContainer&&this.transcriptContent&&(this.transcriptContainer.appendChild(this.transcriptContent),e.appendChild(this.transcriptContainer)))}setupWordDisplay(){this.transcriptContent&&(this.transcriptContent.innerHTML="")}showTranscript(){this.transcriptContainer,this.transcriptContainer&&(this.transcriptContainer.classList.remove("sf-hidden"),this.transcriptContainer.classList.add("sf-transcript--visible"))}hideTranscript(){this.transcriptContainer,this.transcriptContainer&&(this.transcriptContainer.classList.add("sf-hidden"),this.transcriptContainer.classList.remove("sf-transcript--visible"))}updateCCButtonState(t){var e;this.ccButton&&(t?(this.ccButton.classList.remove("sf-hidden"),null==(e=this.videoManager)||e.updateCCButtonIcon(this.isVisible)):this.ccButton.classList.add("sf-hidden"))}reset(){this.stopAnimationLoop(),this.transcriptContent&&(this.transcriptContent.innerHTML=""),this.currentTranscript=null,this.chunks=[],this.isNewVideo=!1,this.firstWordForceDisplayUntil=0,this.lastDisplayedChunkIndex=-1,this.currentWindowStartIndex=-1,this.currentWindowEndIndex=-1,this.isVisible&&this.hideTranscript(),this.updateCCButtonState(!1),this.transcriptContainer=null,this.transcriptContent=null}static resetUserPreference(){t.userCaptionPreference=null}async destroy(){this.stopAnimationLoop(),this.timeUpdateListener&&this.videoElement&&this.videoElement.removeEventListener("timeupdate",this.timeUpdateListener),this.transcriptContainer&&this.transcriptContainer.parentNode&&this.transcriptContainer.parentNode.removeChild(this.transcriptContainer),this.transcriptContainer=null,this.transcriptContent=null,this.ccButton=null,this.videoElement=null,this.timeUpdateListener=null,this.currentTranscript=null,this.isVisible=!1}};e(kt,"userCaptionPreference",null);let Tt=kt;class At{constructor(t){e(this,"deviceInfo"),this.deviceInfo=t}updateDeviceInfo(t){this.deviceInfo=t}}class zt extends At{getVideoElementConfig(){return{playsInline:!0,muted:!0,controls:!1,preload:"metadata",additionalAttributes:{"webkit-playsinline":"true",playsinline:"true","x-webkit-airplay":"allow"},styles:{width:"100%",height:"100%",objectFit:"cover",backgroundColor:"white"}}}getControlsConfig(){return{buttonMinSize:{width:"44px",height:"44px"},useTouch:!0,progressUpdateInterval:500}}getAutoplayConfig(t){return{shouldStartMuted:!t,enableFallbackLoop:!0,fallbackTimeout:3e3,requiresUserInteraction:!0}}configureVideoElement(t){const e=this.getVideoElementConfig();t.playsInline=e.playsInline,t.muted=e.muted,t.controls=e.controls,t.preload=e.preload,Object.entries(e.additionalAttributes).forEach((([e,n])=>{try{t.setAttribute(e,n)}catch(t){console.warn(`MobilePlaybackHandler: Failed to set attribute ${e}:`,t)}}))}configureControlElement(t){}async handlePlayAttempt(t,e){const n=ct().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(e){return t.muted,await this.handleAutoplayFallback(t),!1}}async handleAutoplayFallback(t){t.muted=!0,t.loop=!0,t.playsInline=!0,t.setAttribute("playsinline","true"),t.setAttribute("webkit-playsinline","true");try{await t.play()}catch(t){console.error("MobilePlaybackHandler: All autoplay attempts failed")}}destroy(){}getProgressUpdateFrequency(t){return t?500:16}}class Lt extends At{getVideoElementConfig(){return{playsInline:!0,muted:!1,controls:!1,preload:"metadata",additionalAttributes:{},styles:{backgroundColor:"white"}}}getControlsConfig(){return{buttonMinSize:{width:"auto",height:"auto"},useTouch:!1,progressUpdateInterval:16}}getAutoplayConfig(t){return{shouldStartMuted:!1,enableFallbackLoop:!1,fallbackTimeout:5e3,requiresUserInteraction:!1}}configureVideoElement(t){const e=this.getVideoElementConfig();t.playsInline=e.playsInline,t.muted=e.muted,t.controls=e.controls,t.preload=e.preload}configureControlElement(t){}async handlePlayAttempt(t,e){const n=ct().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(e){return t.muted,await this.handleAutoplayFallback(t),!1}}async handleAutoplayFallback(t){t.muted=!0,t.loop=!0;try{await t.play()}catch(t){throw console.error("DesktopPlaybackHandler: All autoplay attempts failed"),new Error("Desktop autoplay completely blocked")}}getProgressUpdateFrequency(t){return 16}destroy(){}}function Vt(t=18){return`<svg width="${t}" height="${t}" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>`}class Ot{constructor(t,n,i){e(this,"container"),e(this,"controlsElement",null),e(this,"progressBar",null),e(this,"muteButton",null),e(this,"ccButton",null),e(this,"deviceHandler"),e(this,"callbacks"),e(this,"updateInterval",null),e(this,"animationFrameId",null),e(this,"lastTimeupdateEvent",0),e(this,"videoElement",null),e(this,"buttonsShownAt90Percent",!1),e(this,"handleDetailedTimeUpdate",(()=>{var t;this.lastTimeupdateEvent=Date.now(),this.progressBar&&!1===(null==(t=this.videoElement)?void 0:t.paused)&&this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear"),this.videoElement&&!this.buttonsShownAt90Percent&&this.videoElement.duration>0&&this.videoElement.currentTime/this.videoElement.duration>=.9&&(this.callbacks.on90PercentReached(),this.buttonsShownAt90Percent=!0)})),e(this,"handleSeeking",(()=>{this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.updateProgress())})),e(this,"handleSeeked",(()=>{this.progressBar&&this.videoElement&&(this.videoElement.paused||(this.updateProgress(),this.progressBar.offsetWidth,this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear")))})),e(this,"handleProgressBarClick",(t=>{const e=t.currentTarget;if(!this.videoElement||this.videoElement.duration<=0)return;const n=e.getBoundingClientRect(),i=(t.clientX-n.left)/n.width,s=this.videoElement.duration*i;this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width",100*i+"%")),this.callbacks.onSeek(s),t.preventDefault(),t.stopPropagation()})),this.container=t,this.deviceHandler=n,this.callbacks=i}create(t){this.videoElement=t,this.controlsElement=document.createElement("div"),this.controlsElement.className="sf-video-container__controls",this.container.appendChild(this.controlsElement),this.progressBar=document.createElement("div"),this.progressBar.className="sf-video-container__progress",this.controlsElement.appendChild(this.progressBar);const e=this.deviceHandler.getControlsConfig();e.useTouch&&this.controlsElement.addEventListener("touchend",this.handleProgressBarClick),this.controlsElement.addEventListener("click",this.handleProgressBarClick),this.muteButton=document.createElement("button"),this.muteButton.className="sf-video-container__mute-button",this.deviceHandler.configureControlElement(this.muteButton),this.muteButton.innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="none"/><path d="M15 9c0.8 0.8 1.5 1.9 1.5 3s-0.7 2.2-1.5 3" stroke="currentColor"/><path d="M19 7c1.6 1.6 2.5 3.8 2.5 6s-0.9 4.4-2.5 6" stroke="currentColor"/></svg>',e.useTouch&&this.muteButton.addEventListener("touchend",(t=>{t.preventDefault(),this.toggleMute()})),this.muteButton.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),this.toggleMute()})),this.container.appendChild(this.muteButton),this.updateMuteButtonIcon(),this.ccButton=document.createElement("button"),this.ccButton.className="sf-video-container__cc-button",this.deviceHandler.configureControlElement(this.ccButton),this.updateCCButtonIcon(!1),e.useTouch&&this.ccButton.addEventListener("touchend",(t=>{t.preventDefault()})),this.ccButton.addEventListener("click",(t=>{t.preventDefault()})),this.container.appendChild(this.ccButton),this.attachProgressListeners(t)}attachProgressListeners(t){t&&(t.addEventListener("seeking",this.handleSeeking),t.addEventListener("seeked",this.handleSeeked),t.addEventListener("timeupdate",this.handleDetailedTimeUpdate))}detachProgressListeners(t){t&&(t.removeEventListener("seeking",this.handleSeeking),t.removeEventListener("seeked",this.handleSeeked),t.removeEventListener("timeupdate",this.handleDetailedTimeUpdate))}updateVideoElement(t){this.detachProgressListeners(this.videoElement),this.videoElement=t,this.attachProgressListeners(t)}reset(){this.stopProgressTracking(),this.buttonsShownAt90Percent=!1,this.lastTimeupdateEvent=0,this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width","0%"))}reset90PercentTrigger(){this.buttonsShownAt90Percent=!1}destroy(){this.stopProgressTracking(),this.detachProgressListeners(this.videoElement),this.controlsElement&&(this.deviceHandler.getControlsConfig().useTouch&&this.controlsElement.removeEventListener("touchend",this.handleProgressBarClick),this.controlsElement.removeEventListener("click",this.handleProgressBarClick)),this.controlsElement=null,this.progressBar=null,this.muteButton=null,this.ccButton=null,this.videoElement=null}startProgressTracking(){if(this.stopProgressTracking(),!this.videoElement)return;const t=this.videoElement.loop&&this.videoElement.muted,e=this.deviceHandler.getProgressUpdateFrequency(t);if(e>=16){const t=()=>{!this.videoElement||this.videoElement.paused||this.videoElement.ended||this.updateProgress(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}else{const t=()=>{null===this.updateInterval||!this.videoElement||this.videoElement.paused||this.videoElement.ended||(this.updateProgress(),this.updateInterval=window.setTimeout(t,e))};this.updateInterval=window.setTimeout(t,e)}}stopProgressTracking(){null!==this.updateInterval&&(window.clearInterval(this.updateInterval),this.updateInterval=null),null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}updateProgressImmediate(t,e){if(!this.progressBar||e<=0)return;const n=t/e*100;this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width",`${n}%`)}updateProgress(){if(!this.progressBar||!this.videoElement)return;const t=this.videoElement.currentTime||0,e=this.videoElement.duration||0;if(e>0){const n=t/e*100,i="none"!==this.progressBar.style.getPropertyValue("--sf-progress-transition"),s=Date.now()-this.lastTimeupdateEvent;this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width",`${n}%`),this.progressBar.offsetWidth,this.videoElement.ended?this.progressBar.style.setProperty("--sf-progress-transition","width 0.2s ease-out"):!this.videoElement.paused&&!this.videoElement.seeking&&i&&s<500&&this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear")}}setMuted(t){ct().setMuted(t),this.updateMuteButtonIcon()}toggleMute(){const t=!ct().isMuted;this.setMuted(t),this.callbacks.onMuteToggle()}getMuted(){return ct().isMuted}updateMuteButtonIcon(){if(!this.muteButton)return;const t=ct().isMuted;this.muteButton.innerHTML=t?'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm101.66-61.3a8,8,0,0,1-11.32,11.32L216,139.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L204.69,128l-18.35-18.34a8,8,0,0,1,11.32-11.32L216,116.69l18.34-18.35a8,8,0,0,1,11.32,11.32L227.31,128Z"/></svg>':'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z"/></svg>'}updateCCButtonIcon(t){this.ccButton&&(this.ccButton.innerHTML=t?'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"/></svg>':'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"/><line x1="48" y1="48" x2="208" y2="208" stroke="currentColor" stroke-width="16" stroke-linecap="round"/></svg>')}showProgressBar(){if(this.controlsElement){const t=this.controlsElement.closest(".sf-player");null==t||t.classList.contains("sf-player--minimized"),this.controlsElement.classList.remove("sf-hidden")}this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width","0%"),this.progressBar.offsetWidth,this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear"))}hideProgressBar(){this.controlsElement&&this.controlsElement.classList.add("sf-hidden")}showMuteButton(){this.muteButton&&this.muteButton.classList.remove("sf-hidden")}hideMuteButton(){this.muteButton&&this.muteButton.classList.add("sf-hidden")}getCCButton(){return this.ccButton}}class Dt{constructor(){e(this,"audioContext",null),e(this,"analyser",null),e(this,"sourceVideo1",null),e(this,"sourceVideo2",null),e(this,"activeSource",null),e(this,"videoElement1",null),e(this,"videoElement2",null),e(this,"dataArray",null),e(this,"animationId",null),e(this,"isInitialized",!1),e(this,"useFallbackMode",!1),e(this,"isPaused",!1),e(this,"fftSize",2048),e(this,"barCount",12),e(this,"smoothingTimeConstant",.75),e(this,"fallbackTime",0),e(this,"zeroDataFrameCount",0),e(this,"maxZeroFramesBeforeFallback",60)}initialize(t){try{if(!this.isInitialized){const t=window.AudioContext||window.webkitAudioContext;this.audioContext=new t,this.analyser=this.audioContext.createAnalyser(),this.analyser.fftSize=this.fftSize,this.analyser.smoothingTimeConstant=this.smoothingTimeConstant;const e=this.analyser.frequencyBinCount;this.dataArray=new Uint8Array(e),this.analyser.connect(this.audioContext.destination),this.isInitialized=!0,this.useFallbackMode=!1,this.zeroDataFrameCount=0}if(this.videoElement1===t)return this.resumeAudioContext(),void this.switchToSource(this.sourceVideo1);if(this.videoElement2===t)return this.resumeAudioContext(),void this.switchToSource(this.sourceVideo2);this.resumeAudioContext();const e=this.audioContext.createMediaElementSource(t);this.videoElement1?this.videoElement2?console.warn("AudioVisualizationManager: More than 2 video elements detected - this should not happen with dual video system"):(this.videoElement2=t,this.sourceVideo2=e,this.switchToSource(e)):(this.videoElement1=t,this.sourceVideo1=e,this.switchToSource(e)),this.zeroDataFrameCount=0}catch(t){console.warn("AudioVisualizationManager: Web Audio API failed, using fallback animation",t),this.isInitialized=!0,this.useFallbackMode=!0}}switchToSource(t){this.activeSource&&this.activeSource!==t&&this.activeSource.disconnect(),t.connect(this.analyser),this.activeSource=t}getBarHeights(){if(this.isPaused)return this.getFlatBarHeights();if(this.useFallbackMode||!this.analyser||!this.dataArray)return this.getFallbackBarHeights();this.analyser.getByteFrequencyData(this.dataArray);const t=this.dataArray.some((t=>t>0));if(!t)return this.zeroDataFrameCount++,this.zeroDataFrameCount>=this.maxZeroFramesBeforeFallback&&(this.useFallbackMode||(console.warn("AudioVisualizationManager: Detected CORS blocking audio analysis after",this.zeroDataFrameCount,"frames, switching to fallback animation"),this.useFallbackMode=!0)),this.getFallbackBarHeights();this.zeroDataFrameCount=0,this.useFallbackMode&&t&&(this.useFallbackMode=!1);const e=Math.floor(this.barCount/2),n=[],i=this.dataArray.length,s=Math.floor(i/this.barCount);for(let t=0;t<e;t++){let e=0;const r=t*s,a=r+s;for(let t=r;t<a&&t<i;t++)e+=this.dataArray[t];const o=e/s/255;n.push(o)}const r=[...n].reverse();return r.pop(),r.concat(n)}getFallbackBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let n=0;n<t;n++)e.push(0);const n=[...e].reverse();return n.pop(),n.concat(e)}getFlatBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let n=0;n<t;n++)e.push(.1);const n=[...e].reverse();return n.pop(),n.concat(e)}getAverageAmplitude(){if(this.useFallbackMode||!this.analyser||!this.dataArray)return 0;this.analyser.getByteFrequencyData(this.dataArray);let t=0;for(let e=0;e<this.dataArray.length;e++)t+=this.dataArray[e];const e=t/this.dataArray.length/255;return 0===e?0:e}startVisualization(t){if(!this.isInitialized)return void console.warn("AudioVisualizationManager: Cannot start visualization - not initialized");null!==this.animationId&&this.stopVisualization(),this.audioContext&&"suspended"===this.audioContext.state&&this.audioContext.resume(),this.fallbackTime=0,this.zeroDataFrameCount=0;const e=()=>{this.fallbackTime+=16;const n=this.getBarHeights(),i=this.getAverageAmplitude();t(n,i),this.animationId=requestAnimationFrame(e)};e()}stopVisualization(){null!==this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}pause(){this.isPaused=!0}resume(){this.isPaused=!1}resumeAudioContext(){this.audioContext&&"suspended"===this.audioContext.state&&this.audioContext.resume().catch((t=>{console.warn("AudioVisualizationManager: Failed to resume AudioContext",t)}))}resetFallbackMode(){this.useFallbackMode&&(this.useFallbackMode=!1,this.zeroDataFrameCount=0)}getIsInitialized(){return this.isInitialized}reset(){if(this.stopVisualization(),this.sourceVideo1)try{this.sourceVideo1.disconnect()}catch(t){}if(this.sourceVideo2)try{this.sourceVideo2.disconnect()}catch(t){}this.videoElement1=null,this.videoElement2=null,this.sourceVideo1=null,this.sourceVideo2=null,this.activeSource=null,this.useFallbackMode=!1,this.isPaused=!1,this.fallbackTime=0,this.zeroDataFrameCount=0}cleanup(){this.stopVisualization(),this.sourceVideo1&&this.sourceVideo1.disconnect(),this.sourceVideo2&&this.sourceVideo2.disconnect(),this.analyser&&this.analyser.disconnect(),this.audioContext&&"closed"!==this.audioContext.state&&this.audioContext.close(),this.audioContext=null,this.analyser=null,this.sourceVideo1=null,this.sourceVideo2=null,this.activeSource=null,this.videoElement1=null,this.videoElement2=null,this.dataArray=null,this.isInitialized=!1,this.useFallbackMode=!1,this.isPaused=!1,this.fallbackTime=0,this.zeroDataFrameCount=0}destroy(){this.cleanup()}}class Ft{constructor(){e(this,"currentVideo",null),e(this,"nextVideo",null),e(this,"activeVideoIndex",0),e(this,"container",null),e(this,"controls",null),e(this,"transcriptManager"),e(this,"preloadedVideos",new Map),e(this,"audioFallbackOverlay",null),e(this,"audioVisualizationManager"),e(this,"soundbarElement",null),e(this,"currentVideoUrl",""),e(this,"nextVideoUrl",""),e(this,"playbackPositions",new Map),e(this,"completionPolicy","auto"),e(this,"videoEndedCallback",null),e(this,"deviceHandler"),e(this,"deviceChangeCleanup",null),e(this,"hasUserInteracted",!1),e(this,"autoplayFallbackTimeout",null),e(this,"handleVideoEnded",(t=>{const e=t.target,n=this.getActiveVideo();if(e!==n)return;const i=ct();"autoplayBlocked"!==i.currentState&&"idleMode"!==i.currentState?(this.controls&&n&&this.controls.updateProgressImmediate(n.duration,n.duration),n&&n.classList.add("sf-video-container__video--blurred"),"auto"===this.completionPolicy?this.handleAutoVideoEnded():this.handleManualVideoEnded()):i.currentState})),e(this,"handleTimeUpdate",(t=>{const e=t.target;e===this.getActiveVideo()&&Math.floor(e.currentTime)})),e(this,"handleVideoError",(t=>{const e=t.target;e===this.getActiveVideo()&&console.error("VideoManager: Video error",e.error)})),e(this,"handleAutoVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()})),e(this,"handleManualVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()}));const t=Ct.getDeviceInfo();this.deviceHandler=function(t){return t.isMobile?new zt(t):new Lt(t)}(t),this.transcriptManager=new Tt,this.audioVisualizationManager=new Dt,this.deviceChangeCleanup=Ct.onDeviceChange((t=>{this.deviceHandler.updateDeviceInfo(t)}))}getDeviceInfo(){return Ct.getDeviceInfo()}isMobileDevice(){return this.getDeviceInfo().isMobile}create(t){this.container=document.createElement("div"),this.container.className="sf-video-container",t.appendChild(this.container),this.currentVideo=document.createElement("video"),this.currentVideo.className="sf-video-container__video sf-video-container__video--current",this.currentVideo.crossOrigin="anonymous",this.deviceHandler.configureVideoElement(this.currentVideo),this.container.appendChild(this.currentVideo),this.nextVideo=document.createElement("video"),this.nextVideo.className="sf-video-container__video sf-video-container__video--next sf-hidden",this.nextVideo.crossOrigin="anonymous",this.deviceHandler.configureVideoElement(this.nextVideo),this.container.appendChild(this.nextVideo),ct().isMuted&&(this.currentVideo.muted=!0,this.nextVideo.muted=!0);const e={onSeek:t=>this.seek(t),onMuteToggle:()=>{var t;const e=(null==(t=this.controls)?void 0:t.getMuted())??!1;this.currentVideo&&(this.currentVideo.muted=e),this.nextVideo&&(this.nextVideo.muted=e),!e&&this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resetFallbackMode()},on90PercentReached:()=>{if(this.container){const t=new CustomEvent("video90PercentReached",{bubbles:!0,detail:{timestamp:Date.now()}});this.container.dispatchEvent(t)}}};if(this.controls=new Ot(this.container,this.deviceHandler,e),this.controls.create(this.currentVideo),this.addEventListeners(),this.currentVideo&&this.controls){const t=this.controls.getCCButton();t&&this.transcriptManager.setup(this.currentVideo,t,this)}}getActiveVideo(){return 0===this.activeVideoIndex?this.currentVideo:this.nextVideo}getInactiveVideo(){return 0===this.activeVideoIndex?this.nextVideo:this.currentVideo}forEachVideo(t){for(const e of[this.currentVideo,this.nextVideo])e&&t(e)}applyStoreMuteState(t){t.muted=ct().isMuted}clearAutoplayFallbackTimeout(){null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null)}swapVideos(){const t=this.getActiveVideo(),e=this.getInactiveVideo();t&&e&&(t.pause(),this.applyStoreMuteState(e),t.classList.add("sf-hidden"),e.classList.remove("sf-hidden"),this.activeVideoIndex=0===this.activeVideoIndex?1:0,this.currentVideoUrl=this.nextVideoUrl,this.nextVideoUrl="")}async loadVideo(t){var e;const n=this.getActiveVideo();if(n){if(!t||""===t.trim())throw new Error("Cannot load video: No video URL provided for this step");this.controls&&this.controls.reset90PercentTrigger(),this.applyStoreMuteState(n);try{this.controls&&this.controls.reset();const i=(null==(e=ct().playlistOptions)?void 0:e.persistence)??!0;if(this.currentVideoUrl===t&&n.src&&(n.src===t||n.src.endsWith(t))){if(i){const e=this.playbackPositions.get(t);void 0!==e&&e>0&&Math.abs(n.currentTime-e)>.5&&(n.currentTime=e)}return}if(i&&this.currentVideoUrl&&n.currentTime>0&&this.playbackPositions.set(this.currentVideoUrl,n.currentTime),this.getInactiveVideo()&&this.nextVideoUrl===t){this.swapVideos();const t=this.getActiveVideo();return t&&(this.transcriptManager.updateVideoElement(t),this.controls&&this.controls.updateVideoElement(t)),void await new Promise((t=>{const e=this.getActiveVideo();if(!e)return t();if(e.readyState>=3)t();else{const n=()=>{e.removeEventListener("canplay",n),t()};e.addEventListener("canplay",n)}}))}this.currentVideoUrl=t;const s=this.preloadedVideos.get(t);if(s){const e=URL.createObjectURL(s);n.src=e,this.preloadedVideos.delete(t)}else n.src=t;n.load(),await new Promise(((e,s)=>{if(!n)return e(void 0);let r;const a=()=>{if(n){if(clearTimeout(r),i){const e=this.playbackPositions.get(t);if(void 0!==e&&e>0){const t=Math.min(e,n.duration-.5);n.currentTime=t}}else n.currentTime=0;this.transcriptManager.updateVideoElement(n),this.controls&&this.controls.updateVideoElement(n),n.removeEventListener("loadeddata",a),n.removeEventListener("error",o),e(void 0)}},o=e=>{clearTimeout(r);const i=e.target,l=null==i?void 0:i.error;console.error("VideoManager: Video load error:",l),n.removeEventListener("loadeddata",a),n.removeEventListener("error",o);const c=new Error(`Video load failed: ${(null==l?void 0:l.message)||"Unknown error"}`);c.videoUrl=t,c.mediaErrorCode=(null==l?void 0:l.code)||null,c.mediaErrorMessage=(null==l?void 0:l.message)||null,c.failureReason="media_error",s(c)};r=window.setTimeout((()=>{console.error("VideoManager: Video load timeout after 10 seconds"),n.removeEventListener("loadeddata",a),n.removeEventListener("error",o);const e=new Error("Video load timeout");e.videoUrl=t,e.mediaErrorCode=null,e.mediaErrorMessage=null,e.failureReason="timeout",s(e)}),1e4),n.addEventListener("loadeddata",a),n.addEventListener("error",o)}))}catch(e){if(console.error("VideoManager: Failed to load video:",e),e&&"object"==typeof e&&"videoUrl"in e)throw e;const n=new Error("Failed to load video");throw n.videoUrl=t,n.mediaErrorCode=null,n.mediaErrorMessage=null,n.failureReason="load_error",n}}}preloadNextVideo(t){if(!t||this.preloadedVideos.has(t))return;if(this.currentVideoUrl===t)return;if(this.nextVideoUrl===t)return;const e=this.getInactiveVideo();e?(this.nextVideoUrl=t,e.src=t,e.load(),e.preload="auto",this.applyStoreMuteState(e)):fetch(t).then((t=>{if(!t.ok)throw new Error(`Failed to fetch video: ${t.statusText}`);return t.blob()})).then((e=>{this.preloadedVideos.set(t,e)})).catch((e=>{console.error(`VideoManager: Error preloading video ${t}:`,e)}))}play(){var t;const e=this.getActiveVideo();if(!e)return void console.error("VideoManager: No active video element found");e.classList.remove("sf-video-container__video--blurred"),e.ended&&(e.currentTime=0);const n=ct();if(((null==(t=n.playlistOptions)?void 0:t.persistence)??1)&&this.currentVideoUrl){const t=this.playbackPositions.get(this.currentVideoUrl);t&&Math.abs(e.currentTime-t)>.5&&(e.currentTime=t)}if(e.loop=!1,this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resumeAudioContext(),!e.paused)return this.controls&&this.controls.startProgressTracking(),void(this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resume());this.deviceHandler.handlePlayAttempt(e,this.hasUserInteracted).then((t=>{e&&(t?(this.controls&&this.controls.startProgressTracking(),this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resume()):(n.setAutoplayFallback(),this.isMobileDevice()&&(e.playsInline=!0,e.setAttribute("playsinline","true"),e.setAttribute("webkit-playsinline","true"),setTimeout((()=>{e.paused&&e.play().catch((()=>{}))}),200))))})).catch((()=>{console.warn("VideoManager: Autoplay handler threw error - browser has strict autoplay policy"),ct().setAutoplayFallback()}))}pause(){const t=this.getActiveVideo();t&&(t.paused||(t.muted=!0,this.controls&&this.controls.updateProgressImmediate(t.currentTime,t.duration),t.pause(),this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.pause(),this.controls&&this.controls.stopProgressTracking()))}seek(t){const e=this.getActiveVideo();e&&(this.controls&&e.duration>0&&this.controls.updateProgressImmediate(t,e.duration),e.currentTime=t)}getCurrentTime(){const t=this.getActiveVideo();return t?t.currentTime:0}getDuration(){const t=this.getActiveVideo();return t?t.duration:0}getVideoElement(){return this.getActiveVideo()}reset(){this.controls&&this.controls.reset(),this.preloadedVideos.clear(),this.playbackPositions.clear(),this.currentVideoUrl="",this.nextVideoUrl="",this.activeVideoIndex=0,this.hasUserInteracted=!1,this.clearAutoplayFallbackTimeout(),this.completionPolicy="auto",this.videoEndedCallback=null,this.transcriptManager.reset(),this.hideAudioFallbackOverlay();const t=this.audioVisualizationManager.getIsInitialized();t&&this.audioVisualizationManager.reset(),this.currentVideo&&(t||(this.currentVideo.src=""),this.currentVideo.currentTime=0,this.currentVideo.pause()),this.nextVideo&&(t||(this.nextVideo.src=""),this.nextVideo.currentTime=0,this.nextVideo.pause())}async destroy(){this.removeEventListeners(),this.controls&&(this.controls.destroy(),this.controls=null),this.transcriptManager.destroy(),this.hideAudioFallbackOverlay(),this.clearAutoplayFallbackTimeout(),this.deviceChangeCleanup&&(this.deviceChangeCleanup(),this.deviceChangeCleanup=null),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.currentVideo=null,this.nextVideo=null,this.container=null,this.currentVideoUrl="",this.nextVideoUrl="",this.videoEndedCallback=null}addEventListeners(){this.forEachVideo((t=>{t.addEventListener("ended",this.handleVideoEnded),t.addEventListener("error",this.handleVideoError)}))}removeEventListeners(){this.forEachVideo((t=>{t.removeEventListener("ended",this.handleVideoEnded),t.removeEventListener("error",this.handleVideoError)}))}setMuted(t){this.currentVideo&&(this.currentVideo.muted=t),this.nextVideo&&(this.nextVideo.muted=t),this.controls&&this.controls.setMuted(t),!t&&this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resetFallbackMode()}updateCCButtonIcon(t){this.controls&&this.controls.updateCCButtonIcon(t)}isMuted(){var t;return(null==(t=this.controls)?void 0:t.getMuted())??!0}showProgressBar(){this.controls&&this.controls.showProgressBar()}hideProgressBar(){this.controls&&this.controls.hideProgressBar()}showMuteButton(){this.controls&&this.controls.showMuteButton()}hideMuteButton(){this.controls&&this.controls.hideMuteButton()}setCompletionPolicy(t,e){this.completionPolicy=t,this.videoEndedCallback=e||null,this.updateVideoEndedHandler()}updateVideoEndedHandler(){}markUserInteraction(){this.hasUserInteracted||(this.hasUserInteracted=!0,this.autoplayFallbackTimeout,this.clearAutoplayFallbackTimeout())}hasUserInteractedWith(){return this.hasUserInteracted}resetUserInteraction(){this.hasUserInteracted=!1,this.clearAutoplayFallbackTimeout()}handleAutoplayFallbackClick(t){this.markUserInteraction(),t.muted=!1,t.loop=!1,t.currentTime=0}loadTranscript(t,e=!0){this.transcriptManager.loadTranscript(t,e)}createSoundbar(){const t=document.createElement("div");t.className="sf-audio-soundbar";for(let e=0;e<11;e++){const n=document.createElement("div");n.className="sf-audio-soundbar__bar",n.dataset.barIndex=e.toString(),t.appendChild(n)}return t}showAudioFallbackOverlay(t,e){if(this.container){if(t&&(this.container.style.setProperty("--sf-audio-poster-url",`url('${t}')`),this.container.classList.add("sf-video-container--audio-fallback")),!this.audioFallbackOverlay){if(this.audioFallbackOverlay=document.createElement("div"),e){this.audioFallbackOverlay.className="sf-audio-fallback-overlay sf-audio-fallback-overlay--avatar";const t=document.createElement("img");t.className="sf-audio-fallback-overlay__avatar",t.src=e,t.alt="Speaker avatar";const n=document.createElement("div");n.className="sf-audio-fallback-overlay__dim",this.audioFallbackOverlay.appendChild(t),this.audioFallbackOverlay.appendChild(n)}else this.audioFallbackOverlay.className="sf-audio-fallback-overlay sf-audio-fallback-overlay--soundbar-only";this.soundbarElement=this.createSoundbar(),this.audioFallbackOverlay.appendChild(this.soundbarElement),this.container.appendChild(this.audioFallbackOverlay)}}else console.warn("VideoManager: Cannot show audio fallback overlay - container not available")}startAudioVisualization(){if(!this.soundbarElement)return;const t=this.getActiveVideo();if(t)try{this.audioVisualizationManager.initialize(t),this.audioVisualizationManager.startVisualization(((t,e)=>{this.soundbarElement&&this.soundbarElement.querySelectorAll(".sf-audio-soundbar__bar").forEach(((e,n)=>{const i=t[n]||0,s=e,r=Math.max(10,100*i);s.style.setProperty("--sf-bar-height",`${r}%`);const a=180+Math.abs(n-5)/5*120;s.style.setProperty("--sf-bar-color",`hsla(${a}, 70%, 60%, 1)`)}))}))}catch(t){console.error("VideoManager: Failed to initialize audio visualization",t)}}initializeAudioForVideo(){const t=this.getActiveVideo();if(t)try{this.audioVisualizationManager.initialize(t)}catch(t){console.error("VideoManager: Failed to initialize audio for video",t)}}hideAudioFallbackOverlay(){this.container&&(this.audioVisualizationManager.stopVisualization(),this.container.style.removeProperty("--sf-audio-poster-url"),this.container.classList.remove("sf-video-container--audio-fallback"),this.audioFallbackOverlay&&this.audioFallbackOverlay.parentNode&&(this.audioFallbackOverlay.parentNode.removeChild(this.audioFallbackOverlay),this.audioFallbackOverlay=null),this.soundbarElement=null)}}const Ut={tolerance:.3,minSize:1};function Bt(t){return t.trim().replace(/\s+/g," ")}function Nt(t,e){return t.tagName.toUpperCase()===e.tagName.toUpperCase()&&Bt(t.textContent||"")===Bt(e.textContent)}function Rt(t,e){const n=t.getBoundingClientRect();return 0===n.width||0===n.height?"zero size":n.width<e.minSize||n.height<e.minSize?`too small (${n.width.toFixed(0)}x${n.height.toFixed(0)})`:null}function Ht(t,e){const n=t.getBoundingClientRect();return(Math.min(n.width,e.width)/Math.max(n.width,e.width)+Math.min(n.height,e.height)/Math.max(n.height,e.height))/2*100}function $t(t,e,n,i=Ut){const s=document.querySelectorAll(t);if(0===s.length)return null;if(e){const t=function(t,e,n){const i=[];for(const s of t)Rt(s,n)||Nt(s,e)&&i.push(s);return 0===i.length?(e.tagName,e.textContent.substring(0,50),e.textContent.length,null):(i.length,i[0])}(s,e,i);if(t)return t;if(!n)return null}if(n)return function(t,e,n,i){const s=100*(1-i.tolerance),r=[];for(const t of e){const e=Rt(t,i);if(e){r.push({element:t,score:-1,rejection:e});continue}const a=Ht(t,n);if(a<s){const e=t.getBoundingClientRect();r.push({element:t,score:a,rejection:`size mismatch: expected ~${n.width.toFixed(0)}x${n.height.toFixed(0)}, got ${e.width.toFixed(0)}x${e.height.toFixed(0)}`})}else r.push({element:t,score:a})}r.length,n.width.toFixed(0),n.height.toFixed(0);for(let t=0;t<r.length;t++){const e=r[t],n=e.element.getBoundingClientRect();e.rejection?e.rejection:e.score.toFixed(0),n.width.toFixed(0),n.height.toFixed(0)}const a=r.filter((t=>!t.rejection));return 0===a.length?null:(a.sort(((t,e)=>e.score-t.score)),a[0].score.toFixed(0),a[0].element)}(0,s,n,i);for(const t of s)if(!Rt(t,i))return t;return s[0]}function Yt(t,e,n,i=Ut){if(Rt(t,i))return!1;if(e&&Nt(t,e))return!0;if(n){const e=100*(1-i.tolerance);return Ht(t,n)>=e}return!0}function Xt(t,e,n,i,s){const r=function(t,e,n){const i=document.querySelectorAll(t);return 0===i.length?"no_elements":e?Array.from(i).some((t=>t.tagName.toUpperCase()===e.tagName.toUpperCase()))?"text_mismatch":"tag_mismatch":n?"size_mismatch":"no_elements"}(n,i,s);(async()=>{try{const i={playlistId:t,stepId:e,failureReason:r,selector:n},s=await async function(){const t=await async function(){try{return(await import("https://storage.saltfish.ai/libs/rrweb-snapshot-2.0.0-alpha.18.js")).snapshot(document)}catch(t){return console.warn("Failed to capture DOM snapshot:",t),null}}();if(!t)return null;try{return JSON.stringify(t)}catch(t){return console.warn("Failed to serialize DOM snapshot:",t),null}}();s&&(i.domSnapshot=s),await fetch("https://player.saltfish.ai/element-errors",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)})}catch(t){console.warn("Failed to report element error:",t)}})()}function jt(t){const e=document.createElement("canvas");e.width=1,e.height=1;const n=e.getContext("2d");if(!n)return null;n.fillStyle=t,n.fillRect(0,0,1,1);const[i,s,r]=n.getImageData(0,0,1,1).data;return{r:i,g:s,b:r}}class Wt{constructor(){e(this,"cursor",null),e(this,"animationFrameId",null),e(this,"animationStartTime",null),e(this,"currentAnimation",null),e(this,"flashlightOverlay",null),e(this,"startX",null),e(this,"startY",null),e(this,"targetX",null),e(this,"targetY",null),e(this,"shouldShowCursor",!1),e(this,"lastCursorX",50),e(this,"lastCursorY",50),e(this,"isFirstAnimation",!0),e(this,"currentTargetElement",null),e(this,"boundScrollHandler",null),e(this,"scrollRafId",null),e(this,"scrollUpdatePending",!1),e(this,"scrollableParents",[]),e(this,"parentScrollHandlers",new Map),e(this,"selectionElement",null),e(this,"isSelectionMode",!1),e(this,"selectionPadding",4),e(this,"labelElement",null),e(this,"labelText",null),e(this,"dragStartX",null),e(this,"dragStartY",null),e(this,"dragEndX",null),e(this,"dragEndY",null),e(this,"dragPhase","move-to-start"),e(this,"dragAnimationStartTime",null),e(this,"TARGET_SPEED",350),e(this,"MIN_ANIMATION_DURATION",600),e(this,"MAX_ANIMATION_DURATION",2e3),e(this,"animationDuration",800),e(this,"totalDistance",0),e(this,"controlPointX",null),e(this,"controlPointY",null),e(this,"targetMutationObserver",null),e(this,"POINTER_HORIZONTAL_OFFSET",16),e(this,"POINTER_VERTICAL_OFFSET",16),e(this,"SELECTION_HORIZONTAL_OFFSET",8),e(this,"SELECTION_VERTICAL_OFFSET",8),e(this,"animationUtils",{validateAnimationState:()=>!this.isAutoplayBlocked()||(this.stopAnimation(),!1),calculateEasedProgress:(t,e)=>{const n=e>0?t/e:1,i=Math.min(n,1);return.5-.5*Math.cos(i*Math.PI)},calculateBezierPoint:(t,e,n,i)=>{const s=1-t;return{x:Math.pow(s,2)*e.x+2*s*t*n.x+Math.pow(t,2)*i.x,y:Math.pow(s,2)*e.y+2*s*t*n.y+Math.pow(t,2)*i.y}},hasSignificantPositionChange:(t,e,n=10)=>{const i=Math.abs(e.x-t.x),s=Math.abs(e.y-t.y);return i>n||s>n}})}getPaddingFromStyles(t){return"number"==typeof(null==t?void 0:t.padding)?t.padding:(null==t?void 0:t.padding)?parseInt(t.padding,10):this.selectionPadding}calculateDistance(t,e,n,i){return Math.sqrt(Math.pow(n-t,2)+Math.pow(i-e,2))}calculateAnimationDuration(t){const e=t/(this.TARGET_SPEED/1e3);return Math.min(Math.max(e,this.MIN_ANIMATION_DURATION),this.MAX_ANIMATION_DURATION)}getCurrentCursorPosition(){return{x:this.lastCursorX,y:this.lastCursorY}}canShowCursor(){return this.shouldShowCursor&&!this.isAutoplayBlocked()}waitForScrollComplete(t,e,n=1e3){let i=null;const s=()=>{null!==i&&clearTimeout(i),i=window.setTimeout((()=>{t.removeEventListener("scroll",s),e()}),100)};t.addEventListener("scroll",s),setTimeout((()=>{t.removeEventListener("scroll",s),null!==i&&clearTimeout(i),e()}),n)}waitForElement(t,e,n,i){this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null);let s=0,r=null,a=!1;const o=()=>{var e;if(a)return;a=!0;const s=ot.getState(),r=null==(e=s.manifest)?void 0:e.id,o=s.currentStepId;r&&o&&Xt(r,o,t,n,i)},l=()=>{this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null),null!==r&&(clearInterval(r),r=null)},c=async()=>(s++,s>10?(console.warn(`CursorManager: Stopped waiting for element '${t}' after 10 attempts`),o(),l(),null):this.findElementAndScrollIntoView(t,n,i));this.targetMutationObserver=new MutationObserver((async()=>{if(this.isAutoplayBlocked())return void l();const t=await c();t&&(l(),e(t))})),this.targetMutationObserver.observe(document.body,{childList:!0,subtree:!0}),r=setInterval((()=>{if(!this.targetMutationObserver||this.isAutoplayBlocked())return void l();if(s++,s>10)return console.warn(`CursorManager: Stopped waiting for element '${t}' after 10 attempts`),o(),void l();const r=this.findElement(t,n,i);r&&(l(),e(r))}),1e3)}findScrollableParents(t){const e=[];let n=t.parentElement;for(;n&&n!==document.body;){const t=window.getComputedStyle(n),i=t.overflow,s=t.overflowX,r=t.overflowY;"scroll"!==i&&"auto"!==i&&"scroll"!==s&&"auto"!==s&&"scroll"!==r&&"auto"!==r||(n.scrollHeight>n.clientHeight||n.scrollWidth>n.clientWidth)&&e.push(n),n=n.parentElement}return e}addScrollListenersToParents(t){this.removeScrollListenersFromParents(),this.scrollableParents=this.findScrollableParents(t),this.scrollableParents.forEach((t=>{const e=this.handleScroll.bind(this);this.parentScrollHandlers.set(t,e),t.addEventListener("scroll",e,{passive:!0})}))}removeScrollListenersFromParents(){this.parentScrollHandlers.forEach(((t,e)=>{e.removeEventListener("scroll",t)})),this.parentScrollHandlers.clear(),this.scrollableParents=[]}findElement(t,e,n){if(e||n){return $t(t,e,n)||null}const i=document.querySelectorAll(t);if(0===i.length)return null;if(1===i.length)return i[0];for(const t of i)if(this.isElementInViewport(t))return t.getBoundingClientRect(),t;const s=window.innerWidth/2,r=window.innerHeight/2;let a=i[0],o=1/0;for(const t of i){const e=t.getBoundingClientRect(),n=e.left+e.width/2,i=e.top+e.height/2,l=Math.sqrt(Math.pow(n-s,2)+Math.pow(i-r,2));l<o&&(o=l,a=t)}return a.getBoundingClientRect(),a}isElementInViewport(t){const e=t.getBoundingClientRect(),n=window.innerHeight||document.documentElement.clientHeight,i=window.innerWidth||document.documentElement.clientWidth;if(!(e.top>=0&&e.bottom<=n&&e.left>=0&&e.right<=i))return!1;const s=this.findScrollableParents(t);for(const t of s){const n=t.getBoundingClientRect();if(!(e.top>=n.top&&e.bottom<=n.bottom&&e.left>=n.left&&e.right<=n.right))return!1}return!0}async scrollElementIntoView(t){return new Promise((e=>{const n=this.findScrollableParents(t),i=t.getBoundingClientRect(),s=window.innerHeight||document.documentElement.clientHeight,r=i.height>s?"start":"center";0===n.length?(t.scrollIntoView({behavior:"smooth",block:r,inline:"center"}),this.waitForScrollComplete(window,e)):this.scrollParentContainersToShowElement(t,n).then((()=>{this.isElementInViewport(t)||t.scrollIntoView({behavior:"smooth",block:r,inline:"center"}),setTimeout((()=>{e()}),200)}))}))}async scrollParentContainersToShowElement(t,e){return new Promise((n=>{let i=0;const s=e.length;if(0===s)return void n();const r=()=>{i++,i>=s&&n()};e.forEach((e=>{const n=t.getBoundingClientRect(),i=e.getBoundingClientRect(),s=e.scrollTop,a=e.scrollLeft;let o;o=n.height>i.height?s+(n.top-i.top):s+(n.top-i.top)-i.height/2+n.height/2;const l=a+(n.left-i.left)-i.width/2+n.width/2;e.scrollTo({top:Math.max(0,o),left:Math.max(0,l),behavior:"smooth"}),this.waitForScrollComplete(e,r,800)}))}))}async findElementAndScrollIntoView(t,e,n){const i=this.findElement(t,e,n);return i?(this.isElementInViewport(i)||await this.scrollElementIntoView(i),i):null}cleanupExistingElements(){document.querySelectorAll(".sf-cursor").forEach((t=>t.remove())),document.querySelectorAll(".sf-cursor-label").forEach((t=>t.remove())),document.querySelectorAll(".sf-selection").forEach((t=>t.remove())),document.querySelectorAll(".sf-flashlight-overlay").forEach((t=>t.remove())),this.cursor=null,this.labelElement=null,this.selectionElement=null,this.flashlightOverlay=null}create(){this.cleanupExistingElements(),this.injectCursorStyles(),this.cursor=document.createElement("div"),this.cursor.className="sf-cursor",this.cursor.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none"><defs><filter id="cursor-shadow" x="-50%" y="-50%" width="200%" height="200%"><feDropShadow dx="0" dy="1" stdDeviation="1.2" flood-color="rgba(0, 0, 0, 0.22)"/></filter></defs><path d="M3.5 3.5L10.5 20.5L13.3 13.3L20.5 10.5L3.5 3.5Z" fill="#ff7614" stroke="white" stroke-width="0.7" stroke-linejoin="round" stroke-linecap="round" filter="url(#cursor-shadow)"/></svg>',this.labelElement=document.createElement("div"),this.labelElement.className="sf-cursor-label",this.selectionElement=document.createElement("div"),this.selectionElement.className="sf-selection",document.body.appendChild(this.cursor),document.body.appendChild(this.labelElement),document.body.appendChild(this.selectionElement),this.flashlightOverlay=document.createElement("div"),this.flashlightOverlay.className="sf-flashlight-overlay",document.body.appendChild(this.flashlightOverlay),this.boundScrollHandler=this.handleScroll.bind(this),window.addEventListener("scroll",this.boundScrollHandler,{passive:!0}),this.lastCursorX=window.innerWidth-50,this.lastCursorY=window.innerHeight-50}injectCursorStyles(){const t="\n .sf-cursor {\n position: fixed;\n top: 0;\n left: 0;\n width: 40px;\n height: 40px;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n /* Defensive styles to prevent host page CSS interference */\n margin: 0;\n padding: 0;\n border: 0;\n box-sizing: content-box;\n line-height: 0;\n font-size: 0;\n vertical-align: baseline;\n overflow: visible;\n }\n\n .sf-cursor--visible {\n display: block;\n }\n\n .sf-cursor svg {\n display: block;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n .sf-selection {\n position: fixed;\n pointer-events: none;\n display: none;\n z-index: 9999998;\n top: 0;\n left: 0;\n border: 2px solid var(--sf-selection-color, #ff7614);\n background: var(--sf-selection-bg-color, rgba(255, 118, 20, 0));\n border-radius: 4px;\n width: var(--sf-selection-width, 0);\n height: var(--sf-selection-height, 0);\n transform: var(--sf-selection-transform, translate(0, 0));\n will-change: transform;\n box-sizing: border-box;\n }\n\n .sf-selection--visible {\n display: block;\n }\n\n .sf-flashlight-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 9999997;\n display: none;\n background: var(--sf-flashlight-bg, radial-gradient(circle 150px at 50% 50%, transparent 0%, rgba(0, 0, 0, 0.4) 100%));\n clip-path: var(--sf-flashlight-clip, none);\n }\n\n .sf-flashlight-overlay--visible {\n display: block;\n }\n\n .sf-cursor-label {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-label-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n font-size: 13px;\n font-weight: 500;\n color: var(--sf-cursor-label-text, #fff);\n background: var(--sf-cursor-label-bg, #ff7614);\n padding: 4px 10px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n white-space: nowrap;\n margin: 0;\n border: 0;\n box-sizing: border-box;\n line-height: 1.4;\n }\n\n .sf-cursor-label--visible {\n display: block;\n }\n ";try{const e=new CSSStyleSheet;e.replaceSync(t),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e]}catch(e){const n=document.createElement("style");n.textContent=t,document.head.appendChild(n)}}handleScroll(){!this.isAutoplayBlocked()&&this.shouldShowCursor&&this.currentTargetElement&&(null!==this.animationFrameId||this.scrollUpdatePending||(this.scrollUpdatePending=!0,this.scrollRafId=requestAnimationFrame((()=>{this.updateCursorPositionOnScroll(),this.scrollUpdatePending=!1,this.scrollRafId=null}))))}updateCursorPositionOnScroll(){var t,e;if(!this.currentTargetElement)return;const n=this.currentTargetElement.getBoundingClientRect();let i,s;if(this.isSelectionMode){const e=this.getPaddingFromStyles(null==(t=this.currentAnimation)?void 0:t.selectionStyles);i=n.right+e+this.SELECTION_HORIZONTAL_OFFSET,s=n.bottom+e+this.SELECTION_VERTICAL_OFFSET}else i=n.left+n.width/2+this.POINTER_HORIZONTAL_OFFSET,s=n.top+n.height/2+this.POINTER_VERTICAL_OFFSET;if(this.show(i,s),this.lastCursorX=i,this.lastCursorY=s,this.selectionElement&&this.isSelectionMode){const t=this.getPaddingFromStyles(null==(e=this.currentAnimation)?void 0:e.selectionStyles),i=Math.floor(n.left-t),s=Math.floor(n.top-t),r=Math.ceil(n.width+2*t),a=Math.ceil(n.height+2*t);this.selectionElement.style.setProperty("--sf-selection-transform",`translate(${i}px, ${s}px)`),this.selectionElement.style.setProperty("--sf-selection-width",`${r}px`),this.selectionElement.style.setProperty("--sf-selection-height",`${a}px`),this.dragStartX=i,this.dragStartY=s,this.dragEndX=i+r,this.dragEndY=s+a,this.updateFlashlightWithCutout(i,s,r,a)}}isAutoplayBlocked(){return"autoplayBlocked"===ot.getState().currentState}setShouldShowCursor(t){if(this.isAutoplayBlocked())return this.shouldShowCursor=!1,void this.hideCursorElements();this.shouldShowCursor=t,t?this.isFirstAnimation||this.show(this.lastCursorX,this.lastCursorY):this.hideCursorElements()}show(t,e){this.canShowCursor()&&(this.lastCursorX=t,this.lastCursorY=e,this.cursor&&(this.cursor.classList.add("sf-cursor--visible"),this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`)),this.labelElement&&this.labelText&&(this.labelElement.classList.add("sf-cursor-label--visible"),this.labelElement.style.setProperty("--sf-cursor-label-transform",`translate(${t+24}px, ${e+8}px)`)),this.flashlightOverlay&&(this.flashlightOverlay.classList.add("sf-flashlight-overlay--visible"),this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${t}px ${e}px, transparent 0%, rgba(0, 0, 0, 0.4) 100%)`)))}hideCursorElements(){this.cursor&&this.cursor.classList.remove("sf-cursor--visible"),this.labelElement&&this.labelElement.classList.remove("sf-cursor-label--visible"),this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),this.flashlightOverlay&&(this.flashlightOverlay.classList.remove("sf-flashlight-overlay--visible"),this.resetFlashlightOverlay())}resetFlashlightOverlay(){if(!this.flashlightOverlay)return;this.flashlightOverlay.style.setProperty("--sf-flashlight-clip","none");const t=this.lastCursorX,e=this.lastCursorY;this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${t}px ${e}px, transparent 0%, rgba(0, 0, 0, 0.4) 100%)`)}async animate(t){if(this.isAutoplayBlocked())return;if(this.stopAnimation(),this.removeScrollListenersFromParents(),this.currentTargetElement=null,this.isSelectionMode=!1,this.resetFlashlightOverlay(),this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),!(null==t?void 0:t.targetSelector))return void console.warn("CursorManager: No targetSelector provided in animation");if(await new Promise((t=>setTimeout(t,500))),this.isAutoplayBlocked())return;const e=await this.findElementAndScrollIntoView(t.targetSelector,t.expectedElement,t.expectedSize);if(!e)return console.warn("CursorManager: Target element not found in animate:",t.targetSelector),this.setShouldShowCursor(!1),this.hideCursorElements(),void this.waitForElement(t.targetSelector,(()=>this.animate(t)),t.expectedElement,t.expectedSize);this.setShouldShowCursor(!0),this.currentTargetElement=e,this.addScrollListenersToParents(e);const n=e.getBoundingClientRect();this.isFirstAnimation?(this.startX=window.innerWidth-50,this.startY=window.innerHeight-50,this.isFirstAnimation=!1):(this.startX=this.lastCursorX,this.startY=this.lastCursorY);const i={...t,mode:t.mode||"selection"};if(this.isSelectionMode="selection"===i.mode,this.isSelectionMode)return void this.handleSelectionMode(i,n);this.targetX=n.left+n.width/2+this.POINTER_HORIZONTAL_OFFSET,this.targetY=n.top+n.height/2+this.POINTER_VERTICAL_OFFSET,this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),null!==this.targetX&&null!==this.targetY&&null!==this.startX&&null!==this.startY?(this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance)):(this.totalDistance=100,this.animationDuration=this.MIN_ANIMATION_DURATION),this.calculateControlPoint(),this.currentAnimation={...i};const s=null!==this.startX?this.startX:0,r=null!==this.startY?this.startY:0;this.show(s,r),this.animationStartTime=performance.now(),this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this))}handleSelectionMode(t,e){const n=this.getPaddingFromStyles(t.selectionStyles);this.dragStartX=Math.floor(e.left-n),this.dragStartY=Math.floor(e.top-n),this.dragEndX=Math.ceil(e.right+n),this.dragEndY=Math.ceil(e.bottom+n),this.dragPhase="move-to-start",this.targetX=this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.targetY=this.dragStartY+this.SELECTION_VERTICAL_OFFSET,null!==this.targetX&&null!==this.targetY&&null!==this.startX&&null!==this.startY?(this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance)):(this.totalDistance=100,this.animationDuration=this.MIN_ANIMATION_DURATION),this.selectionElement&&(t.selectionStyles&&(t.selectionStyles.borderColor&&this.selectionElement.style.setProperty("--sf-selection-border-color",t.selectionStyles.borderColor),t.selectionStyles.borderWidth&&this.selectionElement.style.setProperty("--sf-selection-border-width",t.selectionStyles.borderWidth),t.selectionStyles.borderRadius&&this.selectionElement.style.setProperty("--sf-selection-border-radius",t.selectionStyles.borderRadius)),this.selectionElement.classList.remove("sf-selection--visible")),this.calculateControlPoint(),this.currentAnimation={...t};const i=null!==this.startX?this.startX:0,s=null!==this.startY?this.startY:0;this.show(i,s),this.animationStartTime=performance.now(),this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this))}updateDragCoordinatesFromElement(){var t;if(!this.currentTargetElement)return;const e=this.currentTargetElement.getBoundingClientRect(),n=this.getPaddingFromStyles(null==(t=this.currentAnimation)?void 0:t.selectionStyles);this.dragStartX=Math.floor(e.left-n),this.dragStartY=Math.floor(e.top-n),this.dragEndX=Math.ceil(e.right+n),this.dragEndY=Math.ceil(e.bottom+n)}updateSelectionRectangle(t,e){if(!this.selectionElement)return;const n=Math.ceil(Math.abs(t-this.SELECTION_HORIZONTAL_OFFSET-this.dragStartX)),i=Math.ceil(Math.abs(e-this.SELECTION_VERTICAL_OFFSET-this.dragStartY)),s=Math.floor(Math.min(this.dragStartX,t-this.SELECTION_HORIZONTAL_OFFSET)),r=Math.floor(Math.min(this.dragStartY,e-this.SELECTION_VERTICAL_OFFSET));this.selectionElement.style.setProperty("--sf-selection-transform",`translate(${s}px, ${r}px)`),this.selectionElement.style.setProperty("--sf-selection-width",`${n}px`),this.selectionElement.style.setProperty("--sf-selection-height",`${i}px`),this.selectionElement.classList.add("sf-selection--visible"),this.updateFlashlightWithCutout(s,r,n,i)}validatePointerState(){return null!==this.animationStartTime&&null!==this.currentAnimation&&null!==this.startX&&null!==this.startY&&null!==this.targetX&&null!==this.targetY&&null!==this.controlPointX&&null!==this.controlPointY}validateSelectionState(){return!(!this.animationStartTime||!this.currentAnimation)&&("move-to-start"===this.dragPhase?null!==this.startX&&null!==this.startY&&null!==this.targetX&&null!==this.targetY&&null!==this.controlPointX&&null!==this.controlPointY:"dragging"!==this.dragPhase||null!==this.dragAnimationStartTime&&null!==this.dragStartX&&null!==this.dragStartY&&null!==this.dragEndX&&null!==this.dragEndY)}completePointerAnimation(){this.show(this.targetX,this.targetY),this.lastCursorX=this.targetX,this.lastCursorY=this.targetY,this.click(),setTimeout((()=>{this.stopAnimation()}),400)}completeMoveToStartPhase(){this.show(this.targetX,this.targetY),this.lastCursorX=this.targetX,this.lastCursorY=this.targetY,this.dragPhase="dragging",this.dragAnimationStartTime=performance.now();const t=this.calculateDistance(this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.dragStartY+this.SELECTION_VERTICAL_OFFSET,this.dragEndX+this.SELECTION_HORIZONTAL_OFFSET,this.dragEndY+this.SELECTION_VERTICAL_OFFSET);if(this.animationDuration=this.calculateAnimationDuration(t),this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%) scale(0.9)`),this.cursor.style.setProperty("--sf-cursor-opacity","0.9")}this.selectionElement&&(this.selectionElement.style.setProperty("--sf-selection-transform",`translate(${this.dragStartX}px, ${this.dragStartY}px)`),this.selectionElement.style.setProperty("--sf-selection-width","0px"),this.selectionElement.style.setProperty("--sf-selection-height","0px"),this.selectionElement.classList.add("sf-selection--visible"))}completeDraggingPhase(){if(this.dragPhase="release",this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`),this.cursor.style.setProperty("--sf-cursor-opacity","1")}null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStartTime=null,this.dragAnimationStartTime=null}handleMoveToStartPhase(t){if(this.currentTargetElement){this.updateDragCoordinatesFromElement();const e={x:this.targetX,y:this.targetY};if(this.targetX=this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.targetY=this.dragStartY+this.SELECTION_VERTICAL_OFFSET,this.animationUtils.hasSignificantPositionChange(e,{x:this.targetX,y:this.targetY})){const e=this.getCurrentCursorPosition();this.startX=e.x,this.startY=e.y,this.calculateControlPoint(),this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance),this.animationStartTime=t}}const e=t-this.animationStartTime;if(e>=this.animationDuration)return void this.completeMoveToStartPhase();const n=this.animationUtils.calculateEasedProgress(e,this.animationDuration),i=this.animationUtils.calculateBezierPoint(n,{x:this.startX,y:this.startY},{x:this.controlPointX,y:this.controlPointY},{x:this.targetX,y:this.targetY});this.show(i.x,i.y)}handleDraggingPhase(t){this.currentTargetElement&&this.updateDragCoordinatesFromElement();const e=t-this.dragAnimationStartTime,n=Math.min(e/this.animationDuration,1),i=.5-.5*Math.cos(n*Math.PI),s=this.dragStartX+(this.dragEndX-this.dragStartX)*i+this.SELECTION_HORIZONTAL_OFFSET,r=this.dragStartY+(this.dragEndY-this.dragStartY)*i+this.SELECTION_VERTICAL_OFFSET;this.show(s,r),this.updateSelectionRectangle(s,r),n>=1&&this.completeDraggingPhase()}handlePointerAnimation(t){if(!this.validatePointerState())return console.warn("CursorManager: Animation frame missing essential data"),void this.stopAnimation();const e=t-this.animationStartTime;if(this.currentTargetElement){const e=this.currentTargetElement.getBoundingClientRect(),n={x:this.targetX,y:this.targetY};if(this.targetX=e.left+e.width/2+this.POINTER_HORIZONTAL_OFFSET,this.targetY=e.top+e.height/2+this.POINTER_VERTICAL_OFFSET,this.animationUtils.hasSignificantPositionChange(n,{x:this.targetX,y:this.targetY})){const e=this.getCurrentCursorPosition();this.startX=e.x,this.startY=e.y,this.calculateControlPoint(),this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance),this.animationStartTime=t}}if(e>=this.animationDuration)return void this.completePointerAnimation();const n=this.animationUtils.calculateEasedProgress(e,this.animationDuration),i=this.animationUtils.calculateBezierPoint(n,{x:this.startX,y:this.startY},{x:this.controlPointX,y:this.controlPointY},{x:this.targetX,y:this.targetY});this.show(i.x,i.y),this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this))}handleSelectionAnimation(t){if(this.validateSelectionState()){switch(this.dragPhase){case"move-to-start":this.handleMoveToStartPhase(t);break;case"dragging":this.handleDraggingPhase(t)}"release"!==this.dragPhase&&(this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this)))}else this.stopAnimation()}unifiedAnimationFrame(t){this.animationUtils.validateAnimationState()&&(this.isSelectionMode?this.handleSelectionAnimation(t):this.handlePointerAnimation(t))}updateFlashlightWithCutout(t,e,n,i){if(!this.flashlightOverlay)return;const s=window.innerWidth,r=window.innerHeight,a=`path(evenodd, "M 0 0 L ${s} 0 L ${s} ${r} L 0 ${r} Z M ${t+4} ${e} L ${t+n-4} ${e} A 4 4 0 0 1 ${t+n} ${e+4} L ${t+n} ${e+i-4} A 4 4 0 0 1 ${t+n-4} ${e+i} L ${t+4} ${e+i} A 4 4 0 0 1 ${t} ${e+i-4} L ${t} ${e+4} A 4 4 0 0 1 ${t+4} ${e} Z")`;this.flashlightOverlay.style.setProperty("--sf-flashlight-clip",a);const o=this.lastCursorX,l=this.lastCursorY;this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${o}px ${l}px, transparent 0%, rgba(0, 0, 0, 0.4) 100%)`)}calculateControlPoint(){if(!(this.startX&&this.startY&&this.targetX&&this.targetY))return void console.warn("CursorManager: Missing start or target position for control point calculation",{startX:this.startX,startY:this.startY,targetX:this.targetX,targetY:this.targetY});const t=(this.startX+this.targetX)/2,e=(this.startY+this.targetY)/2,n=Math.sqrt(Math.pow(this.targetX-this.startX,2)+Math.pow(this.targetY-this.startY,2));this.totalDistance=n;const i=.2*n,s=(Math.random()-.5)*i*2,r=this.targetX-this.startX,a=-(this.targetY-this.startY),o=r,l=Math.sqrt(a*a+o*o);if(0===l)this.controlPointX=t+5,this.controlPointY=e+5;else{const n=a/l,i=o/l;this.controlPointX=t+n*s,this.controlPointY=e+i*s}}async moveToElement(t,e,n){if(!this.canShowCursor())return;if(this.stopAnimation(),this.removeScrollListenersFromParents(),this.currentTargetElement=null,this.isSelectionMode=!1,this.resetFlashlightOverlay(),this.isAutoplayBlocked())return;const i=await this.findElementAndScrollIntoView(t);if(!i)return console.warn("CursorManager: Target element not found:",t),this.setShouldShowCursor(!1),this.hideCursorElements(),void this.waitForElement(t,(()=>this.moveToElement(t,e,n)));this.currentTargetElement=i,this.addScrollListenersToParents(i);const s={targetSelector:t,mode:e||"selection",selectionStyles:n};this.animate(s)}click(){if(this.canShowCursor()&&this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%) scale(0.8)`),this.cursor.style.setProperty("--sf-cursor-opacity","0.8"),setTimeout((()=>{if(this.cursor){if(!this.canShowCursor())return void this.hideCursorElements();this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`),this.cursor.style.setProperty("--sf-cursor-opacity","1")}}),300)}}stopAnimation(){if(null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStartTime=null,this.currentAnimation=null,this.controlPointX=null,this.controlPointY=null,this.dragPhase="move-to-start",this.dragAnimationStartTime=null,this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`),this.cursor.style.setProperty("--sf-cursor-opacity","1")}this.resetFlashlightOverlay(),this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible")}resetFirstAnimation(){this.isFirstAnimation=!0}reset(){this.stopAnimation(),this.currentAnimation=null,this.animationStartTime=null,this.startX=null,this.startY=null,this.targetX=null,this.targetY=null,this.currentTargetElement=null,this.isFirstAnimation=!0,this.shouldShowCursor=!1,this.cursor&&this.cursor.classList.remove("sf-cursor--visible"),this.isSelectionMode=!1,this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),this.dragStartX=null,this.dragStartY=null,this.dragEndX=null,this.dragEndY=null,this.dragPhase="move-to-start",this.dragAnimationStartTime=null,null!==this.scrollRafId&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null),this.scrollUpdatePending=!1,this.removeScrollListenersFromParents(),this.scrollableParents=[]}async destroy(){this.stopAnimation(),this.boundScrollHandler&&(window.removeEventListener("scroll",this.boundScrollHandler),this.boundScrollHandler=null),this.removeScrollListenersFromParents(),null!==this.scrollRafId&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null),this.scrollUpdatePending=!1,this.cursor&&this.cursor.parentNode&&(this.cursor.remove(),this.cursor=null),this.labelElement&&this.labelElement.parentNode&&(this.labelElement.remove(),this.labelElement=null),this.labelText=null,this.selectionElement&&this.selectionElement.parentNode&&(this.selectionElement.remove(),this.selectionElement=null),this.flashlightOverlay&&this.flashlightOverlay.parentNode&&(this.flashlightOverlay.remove(),this.flashlightOverlay=null),this.isFirstAnimation=!0,this.shouldShowCursor=!1,this.currentTargetElement=null,this.isSelectionMode=!1,this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null),document.documentElement.style.removeProperty("--sf-cursor-x"),document.documentElement.style.removeProperty("--sf-cursor-y")}setColor(t){if(this.cursor){const e=this.cursor.querySelector("svg");if(e){const n=e.querySelector("path");n&&n.setAttribute("fill",t)}}this.selectionElement&&(this.selectionElement.style.setProperty("--sf-selection-color",t),this.selectionElement.style.setProperty("--sf-selection-bg-color",function(t){const e=jt(t);return e?`rgba(${e.r}, ${e.g}, ${e.b}, 0)`:t}(t))),this.labelElement&&(this.labelElement.style.setProperty("--sf-cursor-label-bg",t),this.labelElement.style.setProperty("--sf-cursor-label-text",function(t){const e=jt(t);return e&&(299*e.r+587*e.g+114*e.b)/1e3>150?"#333":"#fff"}(t)))}setLabel(t){var e;this.labelText=t,this.labelElement&&(t?(this.labelElement.textContent=t,(null==(e=this.cursor)?void 0:e.classList.contains("sf-cursor--visible"))&&this.labelElement.classList.add("sf-cursor-label--visible")):(this.labelElement.textContent="",this.labelElement.classList.remove("sf-cursor-label--visible")))}}const qt=["utm_source","utm_medium","utm_campaign","utm_term","utm_content","utm_id","gclid","gclsrc","gad_source","dclid","gbraid","wbraid","fbclid","msclkid","li_fat_id","twclid","ttclid","ref","_ga","_gl"];function Zt(t){if(!t)return t;try{let e;e=t.startsWith("/")||!t.includes("://")?new URL(t,window.location.origin):new URL(t);const n=function(){const t=new Map;try{const e=new URL(window.location.href);for(const n of qt){const i=e.searchParams.get(n);null!==i&&t.set(n,i)}t.size>0&&(t.size,Array.from(t.keys()).join(", "))}catch(t){}return t}();if(0===n.size)return t;let i=0;for(const[t,s]of n)e.searchParams.has(t)||(e.searchParams.set(t,s),i++);return i>0?e.toString():t}catch(e){return t}}class Gt{constructor(){e(this,"container",null),e(this,"buttons",[]),e(this,"buttonContainer",null),e(this,"scrollIndicator",null),e(this,"storeUnsubscribe",null),e(this,"storageManager",rt.getInstance()),e(this,"handleVideo90PercentReached",(t=>{this.showButtonsAt90Percent()}))}create(t){this.container=t,this.storeUnsubscribe=lt.subscribe(((t,e)=>{t.isMinimized!==(null==e?void 0:e.isMinimized)&&this.updateButtonPositions()})),t.addEventListener("video90PercentReached",this.handleVideo90PercentReached)}createButtons(t){if(!this.container)return;this.clearButtons(),this.buttonContainer=document.createElement("div");const e=t.length>4;let n="sf-choice-buttons-container";e&&(n+=" sf-choice-buttons-container--scrollable"),this.buttonContainer.className=n,t.length,this.updateCenterPlayButtonPosition(t.length),this.container.appendChild(this.buttonContainer),e&&(this.scrollIndicator=document.createElement("div"),this.scrollIndicator.className="sf-scroll-indicator",this.scrollIndicator.innerHTML='\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <path d="M8 12l-4-4h8l-4 4z"/>\n </svg>\n ',this.container.appendChild(this.scrollIndicator)),t.forEach((t=>{const e=document.createElement("button");e.textContent=t.text,e.dataset.buttonId=t.id,e.className=`sf-choice-button sf-choice-button--${t.action.type}`,t.style&&Object.entries(t.style).forEach((([t,n])=>{e.style.setProperty(`--custom-${t}`,String(n))})),e.addEventListener("click",(async e=>{await this.handleButtonClick(e,t)})),this.buttonContainer&&(this.buttonContainer.appendChild(e),this.buttons.push(e),t.id)})),e&&this.buttonContainer&&this.setupScrollIndicator(this.buttonContainer),ct().isMinimized&&this.buttonContainer.classList.add("sf-hidden")}showButtonsAt90Percent(){this.buttons.length>0&&(this.buttons.forEach(((t,e)=>{t.classList.add("sf-show-button")})),this.scrollIndicator&&this.scrollIndicator.classList.add("sf-show-scroll-indicator"))}setupScrollIndicator(t){this.scrollIndicator&&t.addEventListener("scroll",(()=>{this.scrollIndicator&&(t.scrollHeight-t.scrollTop-t.clientHeight<10?this.scrollIndicator.classList.add("sf-scroll-indicator--hidden"):this.scrollIndicator.classList.remove("sf-scroll-indicator--hidden"))}))}updateCenterPlayButtonPosition(t){if(!this.container)return;const e=this.container.querySelector(".sf-player__center-play-button");if(e)if(t>0){let n;n=t>4?176:36*t+8*(t-1),e.style.setProperty("--sf-button-container-height",`${n}px`),e.classList.add("sf-player__center-play-button--with-buttons")}else e.style.removeProperty("--sf-button-container-height"),e.classList.remove("sf-player__center-play-button--with-buttons")}clearButtons(){this.updateCenterPlayButtonPosition(0),this.buttons.forEach((t=>{t.parentElement&&t.parentElement.removeChild(t)})),this.buttonContainer&&this.buttonContainer.parentElement&&this.buttonContainer.parentElement.removeChild(this.buttonContainer),this.scrollIndicator&&this.scrollIndicator.parentElement&&this.scrollIndicator.parentElement.removeChild(this.scrollIndicator),this.buttons=[],this.buttonContainer=null,this.scrollIndicator=null}updateButtonPositions(){if(this.buttonContainer&&0!==this.buttons.length)return ct().isMinimized?(this.buttonContainer.classList.add("sf-hidden"),void(this.scrollIndicator&&this.scrollIndicator.classList.add("sf-hidden"))):(this.buttonContainer.classList.remove("sf-hidden"),void(this.scrollIndicator&&this.scrollIndicator.classList.remove("sf-hidden")))}async handleButtonClick(t,e){var n,i,s,r,a,o;e.id,t.preventDefault(),t.stopPropagation();const l=ct();switch(e.action.type){case"next":l.play();break;case"goto":if(e.action.url){e.action.target,e.action.url,await this.flushAnalytics();const t=ct();if(t.manifest){lt.setState((t=>{t.currentStepId=e.action.target,t.manifest&&(t.progress[t.manifest.id]={...t.progress[t.manifest.id],lastStepId:e.action.target,lastProgressAt:Date.now(),lastVisited:(new Date).toISOString()})}));try{if(e.action.target,(null==(n=t.config)?void 0:n.token)&&(null==(i=t.user)?void 0:i.id)&&!(null==(s=t.user)?void 0:s.__isAnonymous)){const n=`https://player.saltfish.ai/clients/${t.config.token}/users/${t.user.id}/playlists/${t.manifest.id}`,i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:"in_progress",currentStepId:e.action.target})});i.ok?e.action.target:(i.statusText,i.status)}}catch(t){console.error("InteractionManager: Full error:",t)}if((null==(r=t.playlistOptions)?void 0:r.persistence)??1){const n=null==(a=t.user)?void 0:a.id,i=ct();if(this.storageManager.setProgress(i.progress,n),e.action.target,null==(o=t.user)?void 0:o.__isAnonymous){const n=this.storageManager.getAnonymousUserData();n&&(n.watchedPlaylists=n.watchedPlaylists||{},n.watchedPlaylists[t.manifest.id]={status:"in_progress",currentStepId:e.action.target,timestamp:Date.now(),lastProgressAt:Date.now()},this.storageManager.setAnonymousUserData(n),e.action.target)}}}const l=Zt(e.action.url);window.location.href=l}else e.action.target,l.goToStep(e.action.target);break;case"url":e.action.target,await this.flushAnalytics(),"completedWaitingForInteraction"===l.currentState?(l.completePlaylist(),await new Promise((t=>setTimeout(t,gt)))):(l.goToStep("completed"),await new Promise((t=>setTimeout(t,gt))));const t=Zt(e.action.target);window.open(t,"_blank");const{SaltfishPlayer:c}=await Promise.resolve().then((()=>ye)),d=c.getInstance();d&&d.destroy();break;case"playlist":e.action.target;try{await this.flushAnalytics(),l.completePlaylist(),await new Promise((t=>setTimeout(t,gt)));const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ye)),n=t.getInstance();n&&(e.action.target,await n.startPlaylist(e.action.target))}catch(t){console.error(`InteractionManager: Error starting playlist "${e.action.target}":`,t),e.action.target}break;default:e.action.type}if(l.manifest){const t={buttonId:e.id,actionType:e.action.type,actionTarget:e.action.target};JSON.stringify(t)}}async flushAnalytics(){try{const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ye)),e=t.getInstance(),n=e;if(e&&n.analyticsManager){const t=n.analyticsManager;"function"==typeof t.flush&&await t.flush()}}catch(t){}}reset(){this.clearButtons(),this.buttonContainer=null,this.scrollIndicator=null,this.container&&this.container.removeEventListener("video90PercentReached",this.handleVideo90PercentReached)}destroy(){this.storeUnsubscribe&&(this.storeUnsubscribe(),this.storeUnsubscribe=null),this.container&&this.container.removeEventListener("video90PercentReached",this.handleVideo90PercentReached),this.clearButtons(),this.container=null}}class Kt{constructor(t){e(this,"eventManager",null),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}}class Jt extends Kt{constructor(t){super(t),e(this,"config",null),e(this,"user",null),e(this,"eventQueue",[]),e(this,"isSending",!1),e(this,"flushInterval",null),e(this,"sessionId",null),e(this,"analyticsEnabled",!0),e(this,"boundVisibilityHandler",null)}subscribeToEvents(){this.eventManager&&(this.eventManager.on("playerPaused",(t=>{const e=ct(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerPaused",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("playerResumed",(t=>{const e=ct(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerResumed",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("stepStarted",(t=>{t.step.id,this.trackStepStarted(t.playlist.id,t.step.id)})),this.eventManager.on("stepEnded",(t=>{t.step.id,this.trackStepComplete(t.playlist.id,t.step.id)})),this.eventManager.on("playlistEnded",(t=>{t.playlist.id,this.trackPlaylistComplete(t.playlist.id)})),this.eventManager.on("error",(t=>{t.playlistId&&this.trackError(t.playlistId,t.error,t.stepId,t.errorType,t.videoUrl,t.mediaErrorCode,t.mediaErrorMessage,t.failureReason)})),this.eventManager.on("playerMinimized",(t=>{const e=ct(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerMinimized",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("playerMaximized",(t=>{const e=ct(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerMaximized",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("bubbleShown",(t=>{t.playlist.id;const e=this.getRunId();e&&this.trackEvent({type:"bubbleShown",playlistId:t.playlist.id,runId:e,timestamp:Date.now()})})),this.eventManager.on("playlistStarted",(t=>{t.playlist.id,this.trackPlaylistStart(t.playlist.id)})))}initialize(t,e){this.config=t,this.analyticsEnabled=!1!==t.enableAnalytics,e&&(this.sessionId=e),this.analyticsEnabled&&(this.flushInterval=window.setInterval((()=>{this.flushEvents()}),3e4),this.boundVisibilityHandler=this.handleVisibilityChange.bind(this),document.addEventListener("visibilitychange",this.boundVisibilityHandler))}setUser(t){this.user=t}trackPlaylistStart(t){if(!this.analyticsEnabled)return;const e=this.getRunId();e&&this.trackEvent({type:"playlistStart",playlistId:t,runId:e,timestamp:Date.now()})}trackPlaylistComplete(t){if(!this.analyticsEnabled)return;const e=this.getRunId();e&&this.trackEvent({type:"playlistComplete",playlistId:t,runId:e,timestamp:Date.now()})}trackStepStarted(t,e){if(!this.analyticsEnabled)return;const n=this.getRunId();n&&this.trackEvent({type:"stepStarted",playlistId:t,stepId:e,runId:n,timestamp:Date.now()})}trackStepComplete(t,e){if(!this.analyticsEnabled)return;const n=this.getRunId();n&&this.trackEvent({type:"stepComplete",playlistId:t,stepId:e,runId:n,timestamp:Date.now()})}trackInteraction(t,e,n){if(!this.analyticsEnabled)return;const i=this.getRunId();i&&this.trackEvent({type:"interaction",playlistId:t,stepId:e,runId:i,timestamp:Date.now(),data:n})}trackError(t,e,n,i,s,r,a,o){if(!this.analyticsEnabled)return;const l=this.getRunId();l&&this.trackEvent({type:"error",playlistId:t,stepId:n,runId:l,timestamp:Date.now(),data:{message:e.message,stack:e.stack,errorType:i||"unknown",videoUrl:s||null,mediaErrorCode:r||null,mediaErrorMessage:a||null,failureReason:o||"unknown"}})}trackEvent(t){this.analyticsEnabled&&(this.eventQueue.push(t),this.eventQueue.length>=10&&this.flushEvents())}async flush(){await this.flushEvents()}async flushEvents(){if(!this.isSending&&0!==this.eventQueue.length&&this.config&&this.analyticsEnabled){this.isSending=!0;try{const t=[...this.eventQueue];this.eventQueue=[];const e={token:this.config.token,sessionId:this.sessionId,user:this.user,events:t},n=await fetch("https://player.saltfish.ai/analytics",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!n.ok)throw this.eventQueue=[...t,...this.eventQueue],new Error(`Failed to send analytics events: ${n.statusText}`)}catch(t){console.error("Failed to send analytics events:",t)}finally{this.isSending=!1}}}handleVisibilityChange(){"hidden"===document.visibilityState&&this.flushWithBeacon()}flushWithBeacon(){if(0===this.eventQueue.length||!this.config||!this.analyticsEnabled)return;const t=[...this.eventQueue];this.eventQueue=[];const e={token:this.config.token,sessionId:this.sessionId,user:this.user,events:t};try{fetch("https://player.saltfish.ai/analytics",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0})}catch(e){console.warn("AnalyticsManager: fetch keepalive failed, events returned to queue"),this.eventQueue=[...t,...this.eventQueue]}}destroy(){this.analyticsEnabled&&this.flushEvents(),null!==this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),this.boundVisibilityHandler&&(document.removeEventListener("visibilitychange",this.boundVisibilityHandler),this.boundVisibilityHandler=null),this.eventManager&&(this.eventManager=null),this.config=null,this.user=null,this.eventQueue=[],this.sessionId=null,this.analyticsEnabled=!0}getRunId(){try{return fe.getInstance().getRunId()}catch(t){return null}}}class Qt{constructor(t){e(this,"sessionId"),e(this,"currentRunId",null),e(this,"storageManager"),this.storageManager=t||rt.getInstance(),this.sessionId=this.getOrCreateSession(),this.sessionId}getOrCreateSession(){if("undefined"==typeof window)return this.generateUniqueId();const t=this.storageManager.getSession();if(t&&Date.now()-t.lastActivity<18e5)return t.sessionId,this.updateSessionActivity(t.sessionId),t.sessionId;const e=this.generateUniqueId();return this.updateSessionActivity(e),e}updateSessionActivity(t){if("undefined"==typeof window)return;const e={sessionId:t,lastActivity:Date.now()};this.storageManager.setSession(e)}generateUniqueId(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(t){const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}))}getSessionId(){return this.updateSessionActivity(this.sessionId),this.sessionId}startNewRun(){return this.currentRunId=this.generateUniqueId(),this.currentRunId,this.updateSessionActivity(this.sessionId),this.currentRunId}getCurrentRunId(){return this.currentRunId}endCurrentRun(){this.currentRunId&&(this.currentRunId,this.currentRunId=null)}expireSession(){"undefined"!=typeof window&&(this.storageManager.clearSession(),this.sessionId),this.sessionId=this.generateUniqueId(),this.updateSessionActivity(this.sessionId),this.currentRunId=null,this.sessionId}destroy(){this.updateSessionActivity(this.sessionId),this.endCurrentRun()}}class te{constructor(){e(this,"activeTransitions",new Map),e(this,"waitingForInteraction",!1),e(this,"isStateMachineValidating",!1),e(this,"triggerManager",null),e(this,"beforeUnloadHandler",null),e(this,"originalPushState",null),e(this,"originalReplaceState",null),e(this,"handleURLChange",(()=>{if(this.isStateMachineValidating)return;this.triggerManager&&this.triggerManager.clearTriggeredForNonMatchingUrls();const t=Array.from(this.activeTransitions.entries()).filter((([t,e])=>{var n;return"url-path"===(null==(n=e.data)?void 0:n.type)}));let e=!1;if(t.length>0)for(const[n,i]of t)if(i.data&&this.isURLPathMatch(i.data.pattern)){e=!0;break}if(e||this.validateCurrentStepUrl()){if(this.triggerManager&&this.triggerManager.evaluateAllTriggers(),e)for(const[e,n]of t){if(!n.data)continue;const{pattern:t,nextStepId:e}=n.data;if(this.isURLPathMatch(t)){rt.getInstance().clearPendingNavigation(),this.triggerTransition(e);break}}}else this.triggerManager&&this.triggerManager.evaluateAllTriggers()})),window.addEventListener("popstate",this.handleURLChange),this.monitorHistoryChanges()}setTriggerManager(t){this.triggerManager=t}monitorHistoryChanges(){this.originalPushState=history.pushState,this.originalReplaceState=history.replaceState,history.pushState=(...t)=>{this.originalPushState.apply(history,t),this.handleURLChange()},history.replaceState=(...t)=>{this.originalReplaceState.apply(history,t),this.handleURLChange()}}setupTransitions(t,e=!1,n=!1){this.cleanupTransitions(),t.id,t.transitions.forEach((t=>{switch(t.type){case"dom-click":this.setupDOMClickTransition(t);break;case"timeout":n||this.setupTimeoutTransition(t,e);break;case"url-path":this.setupURLPathTransition(t);break;case"dom-element-visible":this.setupDOMElementVisibleTransition(t);break;default:t.type}}))}setupDOMClickTransition(t){if(!t.target)return;const e=t.target,n=t.nextStep,i=`dom-click-${e}-${Date.now()}`,s=new Map;let r=null;const a=t=>{0!==t.length&&(t.length,t.forEach((t=>{if(s.has(t))return;const e=async t=>{const e=t.target;this.willCauseHardRefresh(e)?(t.preventDefault(),t.stopImmediatePropagation(),await this.triggerTransitionWithProgress(n)&&this.reDispatchClick(t)):this.triggerTransition(n)};s.set(t,e),t.addEventListener("click",e,{capture:!0})})))},o=t.expectedElement||t.expectedSize?function(t,e,n,i=Ut){const s=document.querySelectorAll(t);if(0===s.length)return[];if(e){const t=function(t,e,n){const i=[];for(const s of t)Rt(s,n)||Nt(s,e)&&i.push(s);return i.length>0?i.length:e.tagName,i}(s,e,i);if(t.length>0)return t;if(!n)return[]}if(n){const t=100*(1-i.tolerance),e=[];for(const r of s)Rt(r,i)||Ht(r,n)>=t&&e.push(r);return e.length>0&&e.length,e}const r=[];for(const t of s)Rt(t,i)||r.push(t);return r.length>0?r:Array.from(s)}(e,t.expectedElement,t.expectedSize):Array.from(document.querySelectorAll(e));a(o),r=new MutationObserver((n=>{for(const i of n)"childList"===i.type&&i.addedNodes.forEach((n=>{if(n.nodeType===Node.ELEMENT_NODE){const i=n;i.matches(e)&&(!t.expectedElement&&!t.expectedSize||Yt(i,t.expectedElement,t.expectedSize))&&a([i]);const s=i.querySelectorAll(e);if(s.length>0){const e=t.expectedElement||t.expectedSize?Array.from(s).filter((e=>Yt(e,t.expectedElement,t.expectedSize))):Array.from(s);e.length>0&&(e.length,a(e))}}}))})),r.observe(document.body,{childList:!0,subtree:!0}),this.activeTransitions.set(i,{handlers:s,cleanup:()=>{s.forEach(((t,e)=>{e.removeEventListener("click",t,{capture:!0})})),s.clear(),r&&(r.disconnect(),r=null)},data:{type:"dom-click",pattern:e,nextStepId:n}})}setupTimeoutTransition(t,e){const n=t.nextStep,i=t.timeout||0,s=`timeout-${i}-${Date.now()}`;let r=null;e?this.triggerTransition(n):r=window.setTimeout((()=>{this.triggerTransition(n)}),i),this.activeTransitions.set(s,{handlers:new Map,cleanup:()=>{null!==r&&(clearTimeout(r),r=null)},data:{type:"timeout",pattern:"",nextStepId:n}})}setupURLPathTransition(t){if(!t.target)return;const e=t.target,n=t.nextStep;if(this.savePendingNavigation(e,n),this.setupBeforeUnloadHandler(e,n),this.isURLPathMatch(e)){this.triggerTransition(n);const t=5;let e=0;const i=()=>{if(e>=t)return;e++;const s=ct();"waitingForInteraction"===s.currentState||"playing"===s.currentState?(s.currentState,this.triggerTransition(n)):e<t&&(s.currentState,setTimeout(i,500))};setTimeout(i,500)}const i=`url-path-${Date.now()}`,s=window.setInterval((()=>{this.isURLPathMatch(e)&&(clearInterval(s),rt.getInstance().clearPendingNavigation(),this.triggerTransition(n))}),5e3);this.activeTransitions.set(i,{handlers:new Map,cleanup:()=>{clearInterval(s)},data:{type:"url-path",pattern:e,nextStepId:n}})}savePendingNavigation(t,e){const n=ct();n.manifest&&rt.getInstance().setPendingNavigation({playlistId:n.manifest.id,nextStepId:e,urlPattern:t,timestamp:Date.now()})}setupBeforeUnloadHandler(t,e){this.removeBeforeUnloadHandler(),this.beforeUnloadHandler=()=>{this.savePendingNavigation(t,e)},window.addEventListener("beforeunload",this.beforeUnloadHandler)}removeBeforeUnloadHandler(){this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null)}isURLPathMatch(t){if(!t)return!1;const e=mt(window.location.href),n=window.location.pathname,i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*"),s=new RegExp(i),r=s.test(e),a=s.test(n);return r||a}handleUrlRequirementFailure(t,e){e.pattern,e.matchType,this.cleanupTransitions();const n=window._saltfishPlayer;n&&"function"==typeof n.closePlaylist?n.closePlaylist():n&&"function"==typeof n.destroy&&n.destroy()}validateCurrentStepUrl(){const t=ct(),e=t.manifest,n=t.currentStepId;if(!e||!n)return!0;const i=e.steps.find((t=>t.id===n));if(!i||!i.urlRequirement)return!0;const s=ft(i.urlRequirement);return s||this.handleUrlRequirementFailure(n,i.urlRequirement),s}triggerTransition(t){var e;const n=ct(),i=n.currentState;n.currentStepId;const s=n.isMinimized;"playing"!==i&&"waitingForInteraction"!==i||s||(this.cleanupTransitions(),n.goToStep?n.goToStep(t):null==(e=n.goToStep)||e.call(n,t))}async triggerTransitionWithProgress(t){const e=ct(),n=e.currentState;e.currentStepId;const i=e.isMinimized;if("playing"!==n&&"waitingForInteraction"!==n)return!1;if(i)return!1;try{return this.triggerTransition(t),await new Promise((t=>setTimeout(t,gt))),!0}catch(t){return!1}}cleanupTransitions(){this.activeTransitions.forEach((t=>{t.cleanup()})),this.activeTransitions.clear(),this.waitingForInteraction=!1,this.removeBeforeUnloadHandler()}setWaitingForInteraction(t){this.waitingForInteraction=t}isWaitingForInteraction(){return this.waitingForInteraction}reset(){this.cleanupTransitions()}startStateMachineValidation(){this.isStateMachineValidating=!0}endStateMachineValidation(){this.isStateMachineValidating=!1}destroy(){this.cleanupTransitions(),window.removeEventListener("popstate",this.handleURLChange),this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=null),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=null)}setupDOMElementVisibleTransition(t){if(!t.target)return;const e=t.target,n=t.nextStep,i=`dom-visible-${e}-${Date.now()}`;let s=null,r=null,a=null,o=null;const l=t=>{s||(a=t,s=new IntersectionObserver((t=>{t.forEach((t=>{var e;if(t.isIntersecting,t.intersectionRatio.toFixed(2),t.target.outerHTML.substring(0,100),t.isIntersecting&&t.target===a){const s=window.getComputedStyle(t.target);if("0"===s.opacity||"none"===s.display||"visible"!==s.visibility||"none"===s.pointerEvents)return;this.triggerTransition(n),null==(e=this.activeTransitions.get(i))||e.cleanup(),this.activeTransitions.delete(i)}else if(t.target===a){const e=t.target.getBoundingClientRect();e.top.toFixed(0),e.left.toFixed(0),e.bottom.toFixed(0),e.right.toFixed(0),e.width.toFixed(0),e.height.toFixed(0)}}))}),{root:null,rootMargin:"0px",threshold:0}),s.observe(t),r&&(r.disconnect(),r=null))},c=t.expectedElement||t.expectedSize?$t(e,t.expectedElement,t.expectedSize):document.querySelector(e);c?l(c):(r=new MutationObserver((n=>{for(const i of n)if("childList"===i.type&&i.addedNodes.forEach((n=>{if(n.nodeType===Node.ELEMENT_NODE){const i=n;if(i.matches(e)&&(!t.expectedElement&&!t.expectedSize||Yt(i,t.expectedElement,t.expectedSize)))return void l(i);const s=t.expectedElement||t.expectedSize?$t(e,t.expectedElement,t.expectedSize):i.querySelector(e);if(s)return void l(s)}})),!r)break})),r.observe(document.body,{childList:!0,subtree:!0}),o=window.setInterval((()=>{if(!r)return void(o&&clearInterval(o));const n=t.expectedElement||t.expectedSize?$t(e,t.expectedElement,t.expectedSize):document.querySelector(e);n&&n.offsetWidth>0&&n.offsetHeight>0&&(o&&clearInterval(o),o=null,l(n))}),1e3)),this.activeTransitions.set(i,{handlers:new Map,cleanup:()=>{s&&(s.disconnect(),s=null),r&&(r.disconnect(),r=null),o&&(clearInterval(o),o=null),a=null},data:{type:"dom-element-visible",pattern:e,nextStepId:n}})}reDispatchClick(t){const e=t.target;if(e&&e instanceof HTMLElement)try{setTimeout((()=>{e.tagName,e.id&&e.id,e.className&&e.className.split(" ").join(".");const n=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window,button:t.button||0,buttons:t.buttons||1,clientX:t.clientX||0,clientY:t.clientY||0,ctrlKey:t.ctrlKey||!1,shiftKey:t.shiftKey||!1,altKey:t.altKey||!1,metaKey:t.metaKey||!1});e.dispatchEvent(n)}),10)}catch(t){}}willCauseHardRefresh(t){try{if("A"===t.tagName&&t.hasAttribute("href")){const e=t.getAttribute("href");if(!e)return!1;const n=new URL(e,window.location.href),i=new URL(window.location.href);if(n.origin!==i.origin)return n.origin,i.origin,!0;const s=t.getAttribute("target");return!(!s||"_self"===s)||("mailto:"===n.protocol||"tel:"===n.protocol||"sms:"===n.protocol||"javascript:"===n.protocol)&&(n.protocol,!0)}const e=t.closest("form");if(e&&e.hasAttribute("action")){const t=e.getAttribute("action");if(t&&"#"!==t&&""!==t)return!1}return t.tagName,!1}catch(t){return!1}}}class ee{constructor(){e(this,"triggeredPlaylists",[]),e(this,"triggeredPlaylistsSet",new Set),e(this,"isMonitoring",!1),e(this,"elementClickedListeners",new Map),e(this,"clickedElements",new Set),e(this,"elementVisibleObservers",new Map),e(this,"visibleElements",new Set)}registerTriggers(t){this.triggeredPlaylists=t.filter((t=>(t.hasTriggers??t.autoStart??!1)&&t.triggers)),this.triggeredPlaylists.length,this.triggeredPlaylists.forEach((t=>{var e,n,i,s;t.id,null==(e=t.triggers)||e.url,null==(n=t.triggers)||n.elementClicked,null==(i=t.triggers)||i.elementVisible,null==(s=t.triggers)||s.maxVisits})),this.setupElementClickListeners(),this.setupElementVisibleObservers()}startMonitoring(){this.isMonitoring||(this.isMonitoring=!0,this.evaluateAllTriggers())}stopMonitoring(){this.isMonitoring=!1}evaluateAllTriggers(){if(this.isMonitoring&&0!==this.triggeredPlaylists.length)for(const t of this.triggeredPlaylists)if(this.evaluatePlaylistTrigger(t)){t.id;break}}evaluatePlaylistTrigger(t){if(!t.triggers)return!1;const{triggers:e}=t,n=t.id;if(this.triggeredPlaylistsSet.has(n))return!1;if(!ct().user)return!1;const i=[],s=this.getWatchedPlaylists(),r=this.evaluateMaxVisitsCondition(e.maxVisits,n,s);i.push(r);const a=this.evaluateURLCondition(e);i.push(a),e.url;const o=this.evaluatePlaylistSeenCondition(e.playlistSeen,s);i.push(o),JSON.stringify(e.playlistSeen);const l=this.evaluatePlaylistNotSeenCondition(e.playlistNotSeen,s);i.push(l),JSON.stringify(e.playlistNotSeen);const c=this.evaluateElementClickCondition(e.elementClicked);i.push(c),e.elementClicked;const d=this.evaluateElementVisibleCondition(e.elementVisible);i.push(d),e.elementVisible;const h=this.evaluateUserAttributesCondition(e.userAttributes);i.push(h),JSON.stringify(e.userAttributes);const u=this.applyOperators(i,e.operators);return(e.operators||["AND"]).join(", "),!!u&&(this.triggerPlaylist(n),!0)}getWatchedPlaylists(){var t,e;const n=ct();if((null==(t=n.userData)?void 0:t.watchedPlaylists)&&Object.keys(n.userData.watchedPlaylists).length>0)return n.userData.watchedPlaylists;const i=rt.getInstance().getProgress(null==(e=n.user)?void 0:e.id);if(!i)return{};const s={};for(const t of Object.keys(i))s[t]={status:"in_progress",timestamp:Date.now()};return JSON.stringify(Object.keys(s)),s}evaluateMaxVisitsCondition(t,e,n){if(null===t)return!0;const i=n&&n[e];return((null==i?void 0:i.visitCount)??("completed"===(null==i?void 0:i.status)||"dismissed"===(null==i?void 0:i.status)?1:0))+("in_progress"===(null==i?void 0:i.status)?1:0)<t}normalizeUrl(t){return t.endsWith("/")&&t.lastIndexOf("/")>t.indexOf("://")+2?t.slice(0,-1):t}evaluateURLCondition(t){let e=t.url;if(!e)return!0;const n=this.normalizeUrl(mt(window.location.href.split("#")[0])),i=window.location.pathname;if("regex"===t.urlMatchType)try{const t=new RegExp(e),s=t.test(n),r=t.test(i);return s||r}catch(t){return!1}"contains"!==t.urlMatchType||e.includes("*")||(e="*"+e+"*");const s=e.includes("*");s||t.urlMatchType&&"exact"!==t.urlMatchType&&"contains"!==t.urlMatchType||(e=this.normalizeUrl(e));let r=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*");s||(r="^"+r+"$");const a=new RegExp(r),o=a.test(n),l=a.test(i);return t.url,t.urlMatchType,o||l}evaluatePlaylistSeenCondition(t,e){if(!t||0===t.length)return!0;if(!e)return!1;for(const n of t){const t=e[n];if(!t||"completed"!==t.status)return!1}return!0}evaluatePlaylistNotSeenCondition(t,e){if(!t||0===t.length)return!0;if(!e)return!0;for(const n of t){const t=e[n];if(t&&("completed"===t.status||"in_progress"===t.status))return!1}return!0}evaluateElementClickCondition(t){return!t||this.clickedElements.has(t)}evaluateElementVisibleCondition(t){return!t||this.visibleElements.has(t)}evaluateUserAttributesCondition(t){if(!t||0===t.length)return!0;const e=ct().user;if(!e)return!1;for(const n of t){const{attributeKey:t,attributeType:i,operator:s,value:r}=n,a=e[t];if(null==a)return!1;if(!this.compareValues(a,r,i,s))return!1}return!0}compareValues(t,e,n,i){try{switch(n){case"string":{const n=String(t),s=e;return this.applyOperator(n,s,i)}case"boolean":{const n="boolean"==typeof t?t:"true"===String(t).toLowerCase(),s="true"===e.toLowerCase();return"equals"===i?n===s:"notEquals"===i&&n!==s}case"int":{const n="number"==typeof t?t:parseFloat(String(t)),s=parseFloat(e);return!isNaN(n)&&!isNaN(s)&&this.applyOperator(n,s,i)}case"date":{const n=t instanceof Date?t:new Date(String(t)),s=new Date(e);return!isNaN(n.getTime())&&!isNaN(s.getTime())&&this.applyOperator(n.getTime(),s.getTime(),i)}default:return!1}}catch(t){return!1}}applyOperator(t,e,n){switch(n){case"equals":return t===e;case"notEquals":return t!==e;case"greaterThan":return t>e;case"lessThan":return t<e;default:return!1}}setupElementClickListeners(){this.clearElementClickListeners(),this.triggeredPlaylists.forEach((t=>{var e;(null==(e=t.triggers)?void 0:e.elementClicked)&&this.setupElementClickListener(t.id,t.triggers.elementClicked,t.triggers.elementClickedExpectedElement,t.triggers.elementClickedExpectedSize)}))}setupElementClickListener(t,e,n,i){try{const s=n||i?$t(e,n,i):document.querySelector(e);if(!s)return;if(!this.triggeredPlaylists.find((e=>e.id===t)))return;const r=t=>{t.preventDefault(),t.stopPropagation(),this.clickedElements.add(e),this.evaluateAllTriggers()};s.addEventListener("click",r);const a=`${t}-${e}`;this.elementClickedListeners.set(a,{element:s,listener:r,selector:e})}catch(t){}}clearElementClickListeners(){this.elementClickedListeners.forEach((({element:t,listener:e})=>{try{t.removeEventListener("click",e)}catch(t){console.error("TriggerManager: Error removing element click listener:",t)}})),this.elementClickedListeners.clear()}setupElementVisibleObservers(){this.clearElementVisibleObservers(),this.triggeredPlaylists.forEach((t=>{var e;(null==(e=t.triggers)?void 0:e.elementVisible)&&this.setupElementVisibleObserver(t.id,t.triggers.elementVisible,t.triggers.elementVisibleExpectedElement,t.triggers.elementVisibleExpectedSize)}))}setupElementVisibleObserver(t,e,n,i){try{const s=`${t}-${e}`;if(this.elementVisibleObservers.has(s))return;const r=t=>{const n=new IntersectionObserver((t=>{t.forEach((t=>{if(t.isIntersecting,t.intersectionRatio.toFixed(2),t.isIntersecting){const n=window.getComputedStyle(t.target);if("0"===n.opacity||"none"===n.display||"visible"!==n.visibility||"none"===n.pointerEvents)return;this.visibleElements.add(e),this.evaluateAllTriggers()}else this.visibleElements.has(e)&&this.visibleElements.delete(e)}))}),{root:null,rootMargin:"0px",threshold:0});n.observe(t);const i=this.elementVisibleObservers.get(s);i?(i.mutationObserver&&i.mutationObserver.disconnect(),this.elementVisibleObservers.set(s,{observer:n,mutationObserver:null,selector:e})):this.elementVisibleObservers.set(s,{observer:n,mutationObserver:null,selector:e})},a=n||i?$t(e,n,i):document.querySelector(e);if(a)r(a);else{const t=new MutationObserver((t=>{for(const s of t)"childList"===s.type&&s.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const s=t;if(s.matches(e))(!n&&!i||Yt(s,n,i))&&r(s);else{const t=n||i?$t(e,n,i):s.querySelector(e);t&&r(t)}}}))}));t.observe(document.body,{childList:!0,subtree:!0}),this.elementVisibleObservers.set(s,{observer:null,mutationObserver:t,selector:e})}}catch(t){}}clearElementVisibleObservers(){this.elementVisibleObservers.forEach((({observer:t,mutationObserver:e})=>{try{t&&t.disconnect(),e&&e.disconnect()}catch(t){console.error("TriggerManager: Error removing element visibility observer:",t)}})),this.elementVisibleObservers.clear()}applyOperators(t,e){return 0!==t.length&&(1===t.length?t[0]:e&&0!==e.length&&e.includes("OR")?t.some((t=>t)):t.every((t=>t)))}async triggerPlaylist(t){this.triggeredPlaylistsSet.add(t);try{const e=window._saltfishPlayer;e&&"function"==typeof e.startPlaylist&&await e.startPlaylist(t,{_triggeredByTriggerManager:!0})}catch(e){this.triggeredPlaylistsSet.delete(t)}}clearTriggeredForNonMatchingUrls(){var t;if(0===this.triggeredPlaylistsSet.size)return;const e=Array.from(this.triggeredPlaylistsSet);e.length,e.map((t=>t.substring(0,8))).join(", ");for(const n of e){const e=this.triggeredPlaylists.find((t=>t.id===n));(null==(t=null==e?void 0:e.triggers)?void 0:t.url)?this.evaluateURLCondition(e.triggers)?n.substring(0,8):this.triggeredPlaylistsSet.delete(n):n.substring(0,8)}}resetTriggeredPlaylists(){this.triggeredPlaylistsSet.clear()}getTriggeredPlaylists(){return Array.from(this.triggeredPlaylistsSet)}markPlaylistAsTriggered(t){this.triggeredPlaylistsSet.has(t)||this.triggeredPlaylistsSet.add(t)}destroy(){this.stopMonitoring(),this.clearElementClickListeners(),this.clearElementVisibleObservers(),this.triggeredPlaylists=[],this.triggeredPlaylistsSet.clear(),this.clickedElements.clear(),this.visibleElements.clear()}}class ne extends Kt{constructor(t){super(t)}subscribeToEvents(){this.eventManager&&this.eventManager.on("playlistStarted",(t=>{this.trackTestParticipation(t.playlist.id)}))}initializeTests(t){ct().setABTests(t)}assignUserToTests(t,e,n){var i,s,r,a;const o=ct(),l=o.abTests||[],c={...e};for(const e of l){const r=e.testType||"percentage";if("linked"===r)continue;if("userList"!==r&&c[e.id])continue;let a=!1;a="userList"===r?!(!0===(null==(s=null==(i=o.user)?void 0:i.userData)?void 0:s.__isAnonymous))&&!0===(null==n?void 0:n[e.id]):this.isUserInTest(t,e),c[e.id]={testId:e.id,assigned:a,assignedAt:Date.now()},e.name}for(const e of l){if("linked"!==(e.testType||"percentage"))continue;const i=l.find((t=>t.id===e.linkedTestId));if(!i){e.linkedTestId,e.name,c[e.id]={testId:e.id,assigned:!1,assignedAt:Date.now()};continue}let s=!1;const d=i.testType||"percentage";"percentage"===d?s=this.isUserInTestWithParentId(t,i.id,i.percentage||0):"userList"===d&&(s=!(!0===(null==(a=null==(r=o.user)?void 0:r.userData)?void 0:a.__isAnonymous))&&!0===(null==n?void 0:n[i.id])),c[e.id]={testId:e.id,assigned:s,assignedAt:Date.now()},e.name,i.name}return o.setABTestAssignments(c),c}isUserInTest(t,e){if(!e.percentage)return!1;const n=`${t}_${e.id}`;let i=0;for(let t=0;t<n.length;t++)i=(i<<5)-i+n.charCodeAt(t),i|=0;return Math.abs(i)%100<e.percentage}isUserInTestWithParentId(t,e,n){if(!n)return!1;const i=`${t}_${e}`;let s=0;for(let t=0;t<i.length;t++)s=(s<<5)-s+i.charCodeAt(t),s|=0;return Math.abs(s)%100<n}getFilteredPlaylists(t){const e=ct(),n=e.abTests||[],i=e.abTestAssignments||{};if(0===n.length)return t;const s=new Set;for(const t of n){const e=i[t.id];e&&e.assigned||(s.add(t.playlistId),t.playlistId,t.name)}const r=t.filter((t=>!s.has(t.id)));return t.length,r.length,r}trackTestParticipation(t){var e;const n=ct(),i=n.abTests||[],s=n.abTestAssignments||{},r=i.find((e=>e.playlistId===t));if(!r)return;const a=s[r.id];a&&a.assigned&&(r.testType,r.name,this.eventManager&&this.eventManager.trigger("abTestParticipation",{testId:r.id,testName:r.name,testType:r.testType||"percentage",playlistId:t,userId:null==(e=n.user)?void 0:e.id,timestamp:Date.now()}))}getAssignmentsForBackend(){return ct().abTestAssignments||{}}isPlaylistAvailable(t){const e=ct(),n=e.abTests||[],i=e.abTestAssignments||{},s=n.find((e=>e.playlistId===t));if(!s)return!0;const r=i[s.id];return r&&r.assigned}getActiveTestInfo(){const t=ct(),e=t.abTests||[],n=t.abTestAssignments||{};return e.map((t=>{var e;return{testId:t.id,testName:t.name,testType:t.testType||"percentage",assigned:(null==(e=n[t.id])?void 0:e.assigned)||!1}}))}}class ie{constructor(){e(this,"listeners",new Map)}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){const n=this.listeners.get(t);return!!n&&n.delete(e)}trigger(t,e){const n=this.listeners.get(t);n&&0!==n.size&&("timestamp"in e||(e.timestamp=Date.now()),n.forEach((n=>{try{n(e)}catch(e){console.error(`Error in ${t} event handler:`,e)}})))}removeAllListeners(){this.listeners.clear()}getListenerCount(t){const e=this.listeners.get(t);return e?e.size:0}}class se{async loadManifest(t){const{manifestPath:e,playlistOptions:n,savedProgress:i}=t;try{const t=await this.fetchManifest(e);this.validateManifest(t);const s=this.determineStartStep(t,n,i);return t.id,{manifest:t,startStepId:s}}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw q("[PlaylistLoader] Failed to load manifest:",t),new Error(`Unable to load playlist manifest: ${e}`)}}async fetchManifest(t){try{const e=await fetch(t);if(e.status,e.statusText,!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);return await e.json()}catch(e){throw q("[PlaylistLoader] Fetch/parse failed:",e),q("[PlaylistLoader] Manifest path:",t),new Error(`Failed to fetch manifest from "${t}": ${e instanceof Error?e.message:"Unknown error"}`)}}validateManifest(t){if(!t)throw new Error("Manifest is null or undefined");if("object"!=typeof t)throw new Error("Manifest must be an object");const e=t,n=["id","startStep","steps"];for(const t of n)if(!(t in e))throw new Error(`Manifest missing required field: ${t}`);if(!Array.isArray(e.steps))throw new Error("Manifest steps must be an array");const i=e.steps;if(0===i.length)throw new Error("Manifest must contain at least one step");if(!i.some((t=>"object"==typeof t&&null!==t&&"id"in t&&t.id===e.startStep)))throw new Error(`Start step '${e.startStep}' not found in steps array`);for(const t of i){if("object"!=typeof t||null===t)throw new Error("Each step must be an object");const e=t;if(!e.id)throw new Error("Each step must have an id");if(!e.transitions||!Array.isArray(e.transitions))throw new Error(`Step '${e.id}' must have transitions array`)}}determineStartStep(t,e,n){const i=e.persistence??t.isPersistent??!0,s=t.id,r=!0===e._triggeredByTriggerManager;let a=t.startStep;const o=this.checkPendingNavigation(t);if(o)return o.nextStepId,o.nextStepId;if(e.startNodeId)t.steps.find((t=>t.id===e.startNodeId))?(e.startNodeId,a=e.startNodeId):e.startNodeId;else if(r)a=t.startStep;else if(i&&n&&n[s]){const e=n[s];if("completed"===e.status)a=t.startStep;else{const{isValid:n,ageMs:i}=ht(e);if(n){const n=e.currentStepId||e.lastStepId;n&&t.steps.find((t=>t.id===n))&&(a=n)}else a=t.startStep}}return a}checkPendingNavigation(t){const e=rt.getInstance(),n=e.getPendingNavigation();if(!n)return null;if(n.playlistId!==t.id)return n.playlistId,null;const i=Date.now()-n.timestamp;return i>6e4?(e.clearPendingNavigation(),null):this.isURLPathMatch(n.urlPattern)?t.steps.find((t=>t.id===n.nextStepId))?(n.nextStepId,Math.round(i/1e3),e.clearPendingNavigation(),n):(n.nextStepId,e.clearPendingNavigation(),null):(n.urlPattern,e.clearPendingNavigation(),null)}isURLPathMatch(t){if(!t)return!1;const e=window.location.href,n=window.location.pathname,i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*"),s=new RegExp(i);return s.test(e)||s.test(n)}}class re extends Kt{constructor(t,n){super(t),e(this,"playlistLoader"),e(this,"storageManager"),this.playlistLoader=new se,this.storageManager=n||rt.getInstance()}subscribeToEvents(){this.eventManager&&(this.eventManager.on("playlistStarted",(t=>{t.playlist.id,this.updateWatchedPlaylistStatus(t.playlist.id,"in_progress")})),this.eventManager.on("playlistEnded",(t=>{t.playlist.id,this.updateWatchedPlaylistStatus(t.playlist.id,"completed").catch((e=>{console.error(`PlaylistManager: Error in updateWatchedPlaylistStatus for playlist ${t.playlist.id}:`,e)}))})),this.eventManager.on("playlistDismissed",(t=>{t.playlist.id,this.updateWatchedPlaylistStatus(t.playlist.id,"dismissed")})),this.eventManager.on("stepStarted",(t=>{t.step.id,this.updateWatchedPlaylistStatus(t.playlist.id,"in_progress",t.step.id)})))}async updateWatchedPlaylistStatus(t,e,n){var i,s,r,a,o;const l=ct();l.updateWatchedPlaylist(t,e,n);const c=null==(s=null==(i=l.userData)?void 0:i.watchedPlaylists)?void 0:s[t];if(!(null==(r=null==l?void 0:l.config)?void 0:r.token)||!(null==(a=null==l?void 0:l.user)?void 0:a.id)||(null==(o=null==l?void 0:l.user)?void 0:o.__isAnonymous))return void(c&&this.persistAnonymousWatchedPlaylist(t,c));const d=`https://player.saltfish.ai/clients/${l.config.token}/users/${l.user.id}/playlists/${t}`;try{const t=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:e,currentStepId:(null==c?void 0:c.currentStepId)??null})});if(!t.ok)throw new Error(`Failed to update watched playlist status: ${t.statusText} (${t.status})`)}catch(e){console.error(`PlaylistManager: Error updating watched playlist status for ${t}:`,e)}}persistAnonymousWatchedPlaylist(t,e){if("undefined"==typeof window)return;const n=this.storageManager.getAnonymousUserData()||{userId:"anonymous",userData:{},watchedPlaylists:{},timestamp:Date.now()};n.watchedPlaylists||(n.watchedPlaylists={}),n.watchedPlaylists[t]=e,n.timestamp=Date.now(),this.storageManager.setAnonymousUserData(n),e.status}async load(t,e){var n;try{const i=ct();if(!i)throw new Error("Store not available");const s=(null==(n=i.userData)?void 0:n.watchedPlaylists)||i.progress,r=await this.playlistLoader.loadManifest({manifestPath:t,playlistOptions:e,savedProgress:s}),{manifest:a,startStepId:o}=r,l=a.steps.find((t=>t.id===o));i.setManifest(a,o),l&&i.sendStateMachineEvent({type:"MANIFEST_LOADED",step:l})}catch(t){const e=ct(),n=t instanceof Error?t:new Error("Unknown error loading manifest");e?e.setError(n):console.error("[PlaylistManager] Cannot set error: Store not available",n)}}destroy(){this.eventManager&&(this.eventManager=null)}}class ae{constructor(t){e(this,"button"),e(this,"playerElement"),this.playerElement=t,this.button=document.createElement("button"),this.button.className="sf-player__minimize-button",this.button.innerHTML=Vt(20),this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(ct().isMinimized)}handleClick(){const t=ct(),e=!t.isMinimized;e?t.minimize():t.maximize(),e?this.minimize():this.maximize()}minimize(){this.button.innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'}maximize(){this.button.innerHTML=Vt(20)}updateVisibility(t){t?this.button.classList.add("sf-hidden"):this.button.classList.remove("sf-hidden")}destroy(){this.button.removeEventListener("click",this.handleClick.bind(this)),this.button.remove()}}class oe{constructor(t,n){e(this,"playButton"),e(this,"container"),e(this,"videoManager",null),this.container=t,this.videoManager=n||null,this.createButton()}createButton(){this.playButton=document.createElement("button"),this.playButton.className="sf-controls-container__play-button",this.playButton.innerHTML='<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 5v14l11-7z" fill="currentColor"/></svg>',this.playButton.addEventListener("click",this.handlePlayClick.bind(this)),this.container.appendChild(this.playButton)}handlePlayClick(t){t&&t.stopPropagation();const e=ct();if("autoplayBlocked"===e.currentState)if(this.videoManager){this.videoManager.markUserInteraction(),this.videoManager.setMuted(!1);const t=this.videoManager.getVideoElement();t&&(t.loop=!1,t.currentTime=0)}else{const t=this.playButton.closest(".sf-player");if(t){const e=t.querySelector(".sf-video-container__video");e&&(e.muted=!1,e.loop=!1,e.currentTime=0)}}else this.videoManager?this.videoManager.markUserInteraction():console.warn("PlayPauseButton: VideoManager not available, falling back to store play");"paused"!==e.currentState&&"waitingForInteraction"!==e.currentState&&"autoplayBlocked"!==e.currentState||e.play()}destroy(){this.playButton.removeEventListener("click",this.handlePlayClick.bind(this)),this.playButton.remove()}}class le{constructor(t){e(this,"button"),e(this,"playerElement"),this.playerElement=t,this.button=document.createElement("button"),this.button.className="sf-player__exit-button",this.button.innerHTML='<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>',this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(ct().isMinimized)}handleClick(t){t.stopPropagation(),ct().sendStateMachineEvent({type:"EXIT"})}updateVisibility(t){t?this.button.classList.remove("sf-hidden"):this.button.classList.add("sf-hidden")}destroy(){this.button.removeEventListener("click",this.handleClick.bind(this)),this.button.remove()}}class ce{constructor(t,n={}){e(this,"errorOverlay"),e(this,"container"),e(this,"options"),e(this,"isVisible",!1),this.container=t,this.options=n,this.createErrorDisplay()}createErrorDisplay(){this.errorOverlay=document.createElement("div"),this.errorOverlay.className="sf-error-display",this.errorOverlay.classList.add("sf-hidden");const t=document.createElement("div");t.className="sf-error-display__content";const e=document.createElement("p");e.className=it,e.textContent=this.options.message||"Unable to load content",t.appendChild(e),this.errorOverlay.appendChild(t),this.container.appendChild(this.errorOverlay)}show(t){t&&this.updateOptions(t),this.errorOverlay.classList.remove("sf-hidden"),this.isVisible=!0,requestAnimationFrame((()=>{this.errorOverlay.classList.add(nt)}))}hide(){this.isVisible&&(this.errorOverlay.classList.remove(nt),setTimeout((()=>{this.errorOverlay.classList.add("sf-hidden"),this.isVisible=!1}),300))}updateOptions(t){if(this.options={...this.options,...t},void 0!==t.message){const e=this.errorOverlay.querySelector(`.${it}`);e&&(e.textContent=t.message||"Unable to load content")}}static getErrorMessage(t,e){const n=(t instanceof Error?t.message:t).toLowerCase();return"video"===e||n.includes("video")||n.includes("cannot load video")?n.includes("no video url")||n.includes("video url provided")?"This step doesn't have a video to play":"Unable to load video content":"network"===e||n.includes("network")||n.includes("fetch")?"Connection issue detected":"playlist"===e||n.includes("playlist")?"Unable to load playlist":"initialization"===e||n.includes("token")||n.includes("initialize")?"Setup issue detected":"Unable to load content"}isShowing(){return this.isVisible}destroy(){this.errorOverlay&&this.errorOverlay.remove()}}class de{constructor(t){e(this,"container"),e(this,"spinnerElement",null),this.container=t}show(){this.spinnerElement?this.spinnerElement.classList.remove("sf-hidden"):(this.spinnerElement=document.createElement("div"),this.spinnerElement.className="sf-loading-spinner",this.spinnerElement.innerHTML='\n <div class="sf-loading-spinner__content">\n <div class="sf-loading-spinner__icon"><svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><g transform="translate(10, 10) scale(0.656)"><g clip-path="url(#saltfish-clip)"><path d="M61.0002 30.1906C61.0002 46.8644 47.4834 60.3812 30.8097 60.3812C14.136 60.3812 27.1659 46.8644 27.1659 30.1906C27.1659 13.5168 14.136 0 30.8097 0C47.4834 0 61.0002 13.5168 61.0002 30.1906Z" fill="black" fill-opacity="0.9"/><path d="M24.13 29.8618C24.13 40.3565 15.6978 48.8642 5.29602 48.8642C-5.10576 48.8642 3.02294 40.3565 3.02294 29.8618C3.02294 19.3671 -5.10576 10.8594 5.29602 10.8594C15.6978 10.8594 24.13 19.3671 24.13 29.8618Z" fill="black" fill-opacity="0.9"/></g><defs><clipPath id="saltfish-clip"><rect width="61" height="61" fill="white"/></clipPath></defs></g><circle cx="30" cy="30" r="28" stroke="black" stroke-width="2" fill="none" stroke-linecap="round" stroke-dasharray="8 6" stroke-opacity="0.3"><animateTransform attributeName="transform" type="rotate" values="0 30 30;360 30 30" dur="2s" repeatCount="indefinite"/></circle></svg></div>\n <div class="sf-loading-spinner__text">Loading playlist...</div>\n </div>\n ',this.container.appendChild(this.spinnerElement))}hide(){this.spinnerElement&&this.spinnerElement.classList.add("sf-hidden")}updateMessage(t){if(this.spinnerElement){const e=this.spinnerElement.querySelector(".sf-loading-spinner__text");e&&(e.textContent=t)}}destroy(){this.spinnerElement&&(this.spinnerElement.remove(),this.spinnerElement=null)}}class he{constructor(t){e(this,"shadowDOMManager"),e(this,"playerRoot",null),e(this,"playerElement",null),e(this,"minimizeButton",null),e(this,"exitButton",null),e(this,"playPauseButton",null),e(this,"errorDisplay",null),e(this,"loadingSpinner",null),e(this,"compactLabel",null),e(this,"playbackButtonsVisible",!1),e(this,"playButton",null),e(this,"centerPlayButton",null),e(this,"videoManager",null),e(this,"storeUnsubscribe",null),this.shadowDOMManager=t}createPlayerUI(t,e,n){if(this.videoManager=t,this.playerElement&&this.reset(),!this.playerRoot&&(this.shadowDOMManager.create(),this.playerRoot=this.shadowDOMManager.getRootElement(),!this.playerRoot))return void console.error("Failed to create player root element");this.playerElement=this.createPlayerElement(this.playerRoot),this.minimizeButton=new ae(this.playerElement),this.exitButton=new le(this.playerElement),t.create(this.playerElement);const i=this.createControlsContainer(this.playerElement);this.playPauseButton=new oe(i,t),this.createSaltfishLogo(this.playerElement),this.setupVideoContainerClickHandler(),e.create(),n.create(this.playerElement),this.initializeButtonManagement();const s=ct();this.handleMinimizeStateChange(s.isMinimized)}setupVideoContainerClickHandler(){var t;const e=null==(t=this.playerElement)?void 0:t.querySelector(".sf-video-container");e&&e.addEventListener("click",(t=>{var e;const n=ct();if(n.isMinimized)return t.stopPropagation(),void this.handleMinimizeClick();const i=t.target;if("BUTTON"===i.tagName||i.closest("button")||i.closest(".sf-controls-container"))return;const s=null==(e=this.playerElement)?void 0:e.classList.contains("sf-player--compact");"playing"===n.currentState?n.pause():!s||"idleMode"!==n.currentState&&"autoplayBlocked"!==n.currentState&&"paused"!==n.currentState||(this.handleAutoplayFallbackInteraction("compact bubble click"),n.play())}))}updatePosition(){var t;if(!this.playerRoot||!this.playerElement)return void console.warn("UIManager: updatePosition called but playerRoot or playerElement is null",{playerRoot:!!this.playerRoot,playerElement:!!this.playerElement});const e=ct();let n=(null==(t=e.playlistOptions)?void 0:t.position)||"bottom-right";if(e.currentStepId&&e.manifest){const t=e.manifest.steps.find((t=>t.id===e.currentStepId));(null==t?void 0:t.position)&&(n=t.position)}"bottom-left"!==n&&"bottom-right"!==n&&(console.warn(`UIManager: Invalid position "${n}", defaulting to bottom-right`),n="bottom-right"),this.playerRoot.classList.remove("sf-player-root--bottom-left","sf-player-root--bottom-right"),"bottom-left"===n?this.playerRoot.classList.add("sf-player-root--bottom-left"):this.playerRoot.classList.add("sf-player-root--bottom-right"),e.isMinimized?this.playerElement.classList.add(et):this.playerElement.classList.remove(et)}handleMinimizeClick(){if(!this.playerElement)return;const t=ct(),e=!t.isMinimized;e?t.minimize():t.maximize(),e?this.minimizeButton.minimize():this.minimizeButton.maximize()}handleMinimizeStateChange(t){this.exitButton&&this.exitButton.updateVisibility(t),this.minimizeButton&&this.minimizeButton.updateVisibility(t)}getPlayerElement(){return this.playerElement}getPlayerRoot(){return this.playerRoot}showError(t,e,n){if(!this.playerElement)return void console.warn("UIManager: Cannot show error display - player element not available");const i=ce.getErrorMessage(t,e);this.errorDisplay||(this.errorDisplay=new ce(this.playerElement,{message:i,...n})),this.errorDisplay.show({message:i,...n})}hideError(){this.errorDisplay&&this.errorDisplay.hide()}isErrorDisplayVisible(){var t;return(null==(t=this.errorDisplay)?void 0:t.isShowing())||!1}showLoading(t){this.playerElement?(this.loadingSpinner||(this.loadingSpinner=new de(this.playerElement)),this.loadingSpinner.show(),t&&this.loadingSpinner.updateMessage(t)):console.warn("UIManager: Cannot show loading spinner - player element not available")}hideLoading(){this.loadingSpinner&&this.loadingSpinner.hide()}updateLoadingMessage(t){this.loadingSpinner&&this.loadingSpinner.updateMessage(t)}showPlayer(){this.playerElement&&this.playerElement.classList.add("sf-player--visible")}createPlayerElement(t){const e=document.createElement("div");return e.className="sf-player",t.appendChild(e),e}createControlsContainer(t){const e=document.createElement("div");return e.className="sf-controls-container",t.appendChild(e),e}createSaltfishLogo(t){var e;if(!1===(null==(e=ct().config)?void 0:e.showLogo))return;const n=document.createElement("div");n.className="sf-player__logo",n.innerHTML='\n <svg viewBox="0 0 41 15" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M8.42034 7.49991C8.42034 9.67502 6.65707 11.4383 4.48196 11.4383C2.30685 11.4383 4.00664 9.67502 4.00664 7.49991C4.00664 5.3248 2.30685 3.56152 4.48196 3.56152C6.65707 3.56152 8.42034 5.3248 8.42034 7.49991Z" fill="white"/>\n <path d="M3.53097 7.43198C3.53097 8.96956 2.29707 10.216 0.774969 10.216C-0.747128 10.216 0.442349 8.96956 0.442349 7.43198C0.442349 5.8944 -0.747128 4.64795 0.774969 4.64795C2.29707 4.64795 3.53097 5.8944 3.53097 7.43198Z" fill="white"/>\n <path d="M15.0603 10.628C13.8603 10.628 12.9803 9.892 12.9803 8.372L13.6043 8.292C13.6043 9.492 14.1803 10.044 15.0603 10.044C15.8603 10.044 16.3243 9.612 16.3243 8.972C16.3243 8.252 15.8363 7.988 15.0603 7.788C13.7003 7.436 13.2523 6.996 13.2523 6.196C13.2523 5.396 13.9403 4.772 14.9803 4.772C16.0203 4.772 16.6923 5.396 16.6923 6.436L16.0683 6.516C16.0683 5.796 15.6203 5.356 14.9803 5.356C14.3403 5.356 13.8763 5.636 13.8763 6.196C13.8763 6.756 14.2843 7.004 15.0603 7.204C16.3723 7.548 16.9483 8.012 16.9483 8.972C16.9483 9.932 16.2603 10.628 15.0603 10.628ZM19.182 10.628C18.542 10.628 17.83 10.228 17.83 9.428C17.83 8.548 18.462 8.212 19.494 8.076C19.966 8.012 20.638 7.956 20.414 7.38C20.27 7.004 19.734 6.956 19.494 6.956C18.854 6.956 18.534 7.236 18.534 7.716L17.91 7.636C17.91 6.756 18.774 6.372 19.494 6.372C20.214 6.372 21.022 6.692 21.022 7.652V10.5H20.438V9.7C20.262 10.22 19.798 10.628 19.182 10.628ZM18.454 9.46C18.454 9.78 18.782 10.044 19.182 10.044C19.822 10.044 20.438 9.596 20.438 8.476V8.26C20.286 8.476 19.91 8.596 19.374 8.66C18.742 8.748 18.454 9.06 18.454 9.46ZM22.3044 10.5V4.82H22.9284V10.5H22.3044ZM25.6789 10.5C24.9909 10.5 24.6469 10.204 24.6469 9.508V7.084H23.9669V6.5H24.6469V5.292L25.1909 5.212V6.5H26.2309V7.084H25.1909V9.34C25.1909 9.836 25.3829 9.916 25.7749 9.916H26.2309V10.5H25.6789ZM27.7094 6.052C27.7094 5.116 28.0934 4.82 28.7814 4.82H29.3334V5.404H28.8774C28.4454 5.404 28.2934 5.484 28.2934 6.22V6.5H29.3334V7.084H28.2934V10.5H27.7094V7.084H27.0294V6.5H27.7094V6.052ZM30.2805 10.5V6.5H30.9045V10.5H30.2805ZM30.2165 5.86V5.108H30.9685V5.86H30.2165ZM33.7678 10.628C32.8078 10.628 32.0078 10.06 32.0078 9.02L32.5918 8.94C32.5918 9.66 33.2078 10.044 33.7678 10.044C34.3278 10.044 34.7678 9.86 34.7678 9.38C34.7678 8.9 34.4558 8.772 33.9998 8.708L33.2958 8.612C32.6638 8.524 32.2318 8.092 32.2318 7.532C32.2318 6.812 32.8478 6.372 33.7278 6.372C34.6078 6.372 35.1678 6.892 35.1678 7.612L34.5838 7.692C34.5838 7.212 34.2878 6.956 33.7278 6.956C33.2478 6.956 32.8558 7.132 32.8558 7.532C32.8558 7.852 33.0718 7.996 33.5438 8.068L34.1518 8.156C34.8558 8.26 35.3918 8.66 35.3918 9.38C35.3918 10.1 34.7278 10.628 33.7678 10.628ZM38.9252 7.868C38.9252 7.148 38.5812 6.956 38.1012 6.956C37.6212 6.956 36.9812 7.276 36.9812 8.636V10.5H36.3572V4.9H36.9812V7.364C37.1092 6.812 37.5652 6.372 38.3012 6.372C39.1812 6.372 39.5492 6.988 39.5492 7.868V10.5H38.9252V7.868Z" fill="white"/>\n </svg>\n ',t.appendChild(n),n.addEventListener("click",(t=>{var e;t.stopPropagation();const n=ct();"playing"===n.currentState&&n.pause();const i=null==(e=n.config)?void 0:e.token;i?window.open(`https://www.saltfish.ai/?utm_source=player&utm_medium=logo&clientId=${i}`,"_blank"):(console.warn("UIManager: No token available, falling back to saltfish.ai homepage"),window.open("https://www.saltfish.ai/?utm_source=player&utm_medium=logo","_blank"))}))}initializeButtonManagement(){this.playerElement&&this.videoManager?(this.storeUnsubscribe=lt.subscribe((t=>{this.updatePlayPauseButton(t.currentState)})),this.playButton=this.playerElement.querySelector(".sf-controls-container__play-button"),this.centerPlayButton=this.playerElement.querySelector(".sf-player__center-play-button"),this.centerPlayButton||this.createCenterPlayButton(),this.playButton||console.error("UIManager: Failed to find play button during initialization"),this.centerPlayButton):console.error("UIManager: Cannot initialize button management - missing player element or video manager")}displayPlaybackButtons(t){this.playbackButtonsVisible!==t&&(this.playbackButtonsVisible=t)}updatePlayPauseButton(t){this.playButton&&this.playButton.classList.add("sf-hidden"),!this.centerPlayButton&&this.playerElement&&(this.centerPlayButton=this.playerElement.querySelector(".sf-player__center-play-button"),this.centerPlayButton||this.createCenterPlayButton()),this.centerPlayButton&&("playing"===t||"completed"===t?(this.centerPlayButton.classList.remove("sf-player__center-play-button--visible"),this.centerPlayButton.classList.remove("sf-player__center-play-button--prominent")):(this.centerPlayButton.classList.add("sf-player__center-play-button--visible"),"autoplayBlocked"===t||"idleMode"===t?this.centerPlayButton.classList.add("sf-player__center-play-button--prominent"):this.centerPlayButton.classList.remove("sf-player__center-play-button--prominent")))}handleAutoplayFallbackInteraction(t){var e;const n=ct();if("autoplayBlocked"===n.currentState||"idleMode"===n.currentState)if(n.currentState,this.videoManager){this.videoManager.markUserInteraction(),this.videoManager.setMuted(!1);const t=this.videoManager.getVideoElement();t&&(t.loop=!1,t.currentTime=0)}else{const t=null==(e=this.playerElement)?void 0:e.querySelector(".sf-video-container__video");t&&(t.muted=!1,t.loop=!1,t.currentTime=0)}else this.videoManager&&this.videoManager.markUserInteraction()}createCenterPlayButton(){this.playerElement&&(this.centerPlayButton=document.createElement("button"),this.centerPlayButton.className="sf-player__center-play-button",this.centerPlayButton.innerHTML='\n <svg class="sf-player__center-play-button__play-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M8 5v14l11-7z" fill="currentColor"/>\n </svg>\n <svg class="sf-player__center-play-button__pause-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z" fill="currentColor"/>\n </svg>\n <svg class="sf-player__center-play-button__replay-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z" fill="currentColor"/>\n </svg>\n ',this.playerElement.appendChild(this.centerPlayButton),this.centerPlayButton.addEventListener("click",(t=>{t.stopPropagation(),t.preventDefault();const e=ct();this.handleAutoplayFallbackInteraction("center play button"),"paused"===e.currentState||"waitingForInteraction"===e.currentState||"completedWaitingForInteraction"===e.currentState||"autoplayBlocked"===e.currentState||"idleMode"===e.currentState||"error"===e.currentState?e.play():"playing"===e.currentState&&e.pause()})))}showCompactLabel(t){var e;if(!this.playerRoot||!t)return;this.hideCompactLabel();const n=ct();let i=(null==(e=n.playlistOptions)?void 0:e.position)||"bottom-right";if(n.currentStepId&&n.manifest){const t=n.manifest.steps.find((t=>t.id===n.currentStepId));(null==t?void 0:t.position)&&(i=t.position)}const s="bottom-right"===i?"sf-compact-label--left":"sf-compact-label--right";this.compactLabel=document.createElement("div"),this.compactLabel.className=`sf-compact-label ${s}`,this.compactLabel.textContent=t,this.compactLabel.classList.add("sf-compact-label--clickable"),this.compactLabel.addEventListener("click",(t=>{t.stopPropagation(),t.preventDefault();const e=ct();this.handleAutoplayFallbackInteraction("compact label"),"paused"!==e.currentState&&"waitingForInteraction"!==e.currentState&&"completedWaitingForInteraction"!==e.currentState&&"autoplayBlocked"!==e.currentState&&"idleMode"!==e.currentState&&"error"!==e.currentState||e.play()})),this.playerRoot.appendChild(this.compactLabel)}hideCompactLabel(){this.compactLabel&&this.compactLabel.parentNode&&(this.compactLabel.parentNode.removeChild(this.compactLabel),this.compactLabel=null)}reset(){this.minimizeButton&&(this.minimizeButton.destroy(),this.minimizeButton=null),this.exitButton&&(this.exitButton.destroy(),this.exitButton=null),this.playPauseButton&&(this.playPauseButton.destroy(),this.playPauseButton=null),this.errorDisplay&&(this.errorDisplay.destroy(),this.errorDisplay=null),this.loadingSpinner&&(this.loadingSpinner.destroy(),this.loadingSpinner=null),this.hideCompactLabel(),this.playerElement&&this.playerElement.parentNode&&this.playerElement.parentNode.removeChild(this.playerElement),this.playerRoot=null,this.playerElement=null}enablePlayButtonProminent(){this.centerPlayButton&&this.centerPlayButton.classList.add("sf-player__center-play-button--prominent")}disablePlayButtonProminent(){this.centerPlayButton&&this.centerPlayButton.classList.remove("sf-player__center-play-button--prominent")}destroy(){this.minimizeButton&&(this.minimizeButton.destroy(),this.minimizeButton=null),this.exitButton&&(this.exitButton.destroy(),this.exitButton=null),this.playPauseButton&&(this.playPauseButton.destroy(),this.playPauseButton=null),this.errorDisplay&&(this.errorDisplay.destroy(),this.errorDisplay=null),this.loadingSpinner&&(this.loadingSpinner.destroy(),this.loadingSpinner=null),this.storeUnsubscribe&&(this.storeUnsubscribe(),this.storeUnsubscribe=null),this.playbackButtonsVisible=!1,this.playButton=null,this.centerPlayButton=null,this.videoManager=null,this.shadowDOMManager.remove(),this.playerRoot=null,this.playerElement=null}}const ue=class t{constructor(t){e(this,"currentStepId",null),e(this,"stepTimeoutId",null),e(this,"destroyCallback",null),this.destroyCallback=t}update(t){const{currentStepId:e,currentState:n}=t;if(this.currentStepId,"playing"!==n&&"waitingForInteraction"!==n&&"paused"!==n&&"autoplayBlocked"!==n)return this.stepTimeoutId,void this.clearStepTimeout();const i=e!==this.currentStepId,s=null===this.stepTimeoutId;(i||s)&&(i&&this.currentStepId,this.setStepTimeout(e))}setStepTimeout(e){this.clearStepTimeout(),e&&(this.currentStepId=e,this.stepTimeoutId=window.setTimeout((()=>{this.destroyPlayer()}),t.STEP_TIMEOUT_MS))}clearStepTimeout(){null!==this.stepTimeoutId&&(this.currentStepId,window.clearTimeout(this.stepTimeoutId),this.stepTimeoutId=null)}setDestroyCallback(t){this.destroyCallback=t}destroyPlayer(){if(this.destroyCallback)try{this.destroyCallback()}catch(t){}}reset(){this.clearStepTimeout(),this.currentStepId=null}destroy(){this.clearStepTimeout(),this.currentStepId=null,this.destroyCallback=null}};e(ue,"STEP_TIMEOUT_MS",12e4);let pe=ue;class ge{createManagers(){const t=rt.getInstance(),e=new Qt(t),n=new Pt,i=new Ft,s=new ie,r=new Jt(s),a=new re(s,t),o=new ne(s),l=new Wt,c=new Gt,d=new te,h=new ee,u=new pe((()=>{}));return d.setTriggerManager(h),{shadowDOMManager:n,videoManager:i,cursorManager:l,interactionManager:c,analyticsManager:r,sessionManager:e,transitionManager:d,triggerManager:h,abTestManager:o,eventManager:s,playlistManager:a,stepTimeoutManager:u,uiManager:new he(n),storageManager:t}}resetManagers(t){try{t.videoManager.reset&&t.videoManager.reset(),t.cursorManager.reset&&t.cursorManager.reset(),t.interactionManager.reset&&t.interactionManager.reset(),t.transitionManager.reset&&t.transitionManager.reset(),t.uiManager.reset&&t.uiManager.reset(),t.stepTimeoutManager.reset&&t.stepTimeoutManager.reset()}catch(t){console.error("ManagerFactory: Error resetting managers:",t)}}destroyManagers(t){try{t.transitionManager.destroy(),t.triggerManager.destroy(),t.videoManager.destroy(),t.cursorManager.destroy(),t.interactionManager.destroy(),t.analyticsManager.destroy(),t.sessionManager.destroy(),t.playlistManager.destroy(),t.stepTimeoutManager.destroy(),t.uiManager.destroy()}catch(t){console.error("ManagerFactory: Error destroying managers:",t)}}}const me=class t{constructor(){if(e(this,"playerInitializationService"),e(this,"userManagementService"),e(this,"playlistOrchestrator"),e(this,"stateMachineActionHandler"),e(this,"managerOrchestrator"),e(this,"managerFactory"),e(this,"isInitialized",!1),e(this,"initializationPromise",null),t.instance)throw new Error("SaltfishPlayer is a singleton. Use getInstance()");this.managerFactory=new ge;const n=this.managerFactory.createManagers();this.playerInitializationService=new yt(n),this.userManagementService=new bt(n),this.playlistOrchestrator=new St(n),this.stateMachineActionHandler=new Mt(n),this.managerOrchestrator=new It(n),this.userManagementService.setPlayerInitializationService(this.playerInitializationService),this.playerInitializationService.setUserManagementService(this.userManagementService),this.playerInitializationService.setPlaylistOrchestrator(this.playlistOrchestrator),this.playlistOrchestrator.setUserManagementService(this.userManagementService),this.playlistOrchestrator.setManagerOrchestrator(this.managerOrchestrator),this.playlistOrchestrator.setPlayerInitializationService(this.playerInitializationService),this.playlistOrchestrator.setStateMachineActionHandler(this.stateMachineActionHandler),this.stateMachineActionHandler.setDestroyCallback((()=>this.destroy())),n.stepTimeoutManager.setDestroyCallback((()=>this.destroy())),lt.subscribe((()=>this.managerOrchestrator.handleStoreChanges())),this.stateMachineActionHandler.registerStateMachineActions()}static getInstance(){return t.instance||(t.instance=new t),t.instance}getSessionId(){return this.managerOrchestrator.getManagers().sessionManager.getSessionId()}getRunId(){return this.managerOrchestrator.getManagers().sessionManager.getCurrentRunId()}async initialize(t){if(!this.isInitialized)return this.initializationPromise||(this.initializationPromise=(async()=>{try{await this.playerInitializationService.initialize(t),this.isInitialized=!0,this.managerOrchestrator.setInitialized(!0),"undefined"!=typeof window&&(window._saltfishPlayer=this,window._cursorManager=this.getManagers().cursorManager)}catch(t){throw this.initializationPromise=null,t}})()),this.initializationPromise;console.warn("Saltfish playlist Player is already initialized")}async identifyUser(t,e){this.initializationPromise&&await this.initializationPromise,this.userManagementService.identifyUser(t,e)}async identifyAnonymous(t){this.initializationPromise&&await this.initializationPromise,await this.userManagementService.identifyAnonymous(t)}async startPlaylist(t,e){await this.playlistOrchestrator.startPlaylist(t,e)}resetPlaylist(){this.playlistOrchestrator.resetPlaylist()}closePlaylist(){this.managerOrchestrator.cleanupPlaylist(),lt.getState().resetForNewPlaylist()}destroy(){if(this.isInitialized)try{this.managerOrchestrator.destroyAll(),this.isInitialized=!1}catch(t){console.error("SaltfishPlayer: Error during destruction:",t),this.isInitialized=!1}else console.warn("Saltfish playlist Player is not initialized")}on(t,e){this.managerOrchestrator.getManagers().eventManager.on(t,e)}off(t,e){return this.managerOrchestrator.getManagers().eventManager.off(t,e)}get videoManager(){return this.managerOrchestrator.getManagers().videoManager}getManagers(){return this.managerOrchestrator.getManagers()}getServices(){return{playerInitializationService:this.playerInitializationService,userManagementService:this.userManagementService,playlistOrchestrator:this.playlistOrchestrator,stateMachineActionHandler:this.stateMachineActionHandler,managerOrchestrator:this.managerOrchestrator}}};e(me,"instance",null);let fe=me;const ye=Object.freeze(Object.defineProperty({__proto__:null,SaltfishPlayer:fe},Symbol.toStringTag,{value:"Module"})),ve=function(){const t=fe.getInstance();let e=!1,n=!1,i=null;const s=[],r={init:r=>{if(n)return j("Saltfish already initialized"),Promise.resolve();if(e&&i)return i;const a={enableAnalytics:!0,..."string"==typeof r?{token:r}:r};return j(`Saltfish initialized: analytics=${a.enableAnalytics}`),e=!0,i=t.initialize(a).then((()=>(n=!0,e=!1,(async()=>{if(0!==s.length)for(;s.length>0;){const t=s.shift();if(t)try{await t()}catch(t){q("Error executing queued command:",t)}}})()))).catch((t=>{throw e=!1,t("Saltfish initialization failed:",t),t})),i},identify:(i,r)=>{n||!e?t.identifyUser(i,r):s.push((async()=>{t.identifyUser(i,r)}))},identifyAnonymous:i=>{n||!e?t.identifyAnonymous(i):s.push((async()=>{t.identifyAnonymous(i)}))},startPlaylist:(r,a)=>!n&&e?new Promise(((e,n)=>{s.push((async()=>{try{await t.startPlaylist(r,a),e()}catch(t){n(t)}})),i&&i.catch(n)})):t.startPlaylist(r,a),on:(e,n)=>{t.on(e,n)},off:(e,n)=>t.off(e,n),resetPlaylist:()=>{n||e?n||!e?t.resetPlaylist():s.push((async()=>{t.resetPlaylist()})):W("Cannot reset playlist - Saltfish not initialized")},destroy:()=>{n||e?(e||(n=!1,e=!1,i=null,s.length=0),t.destroy(),n=!1,e=!1,i=null):W("Cannot destroy - Saltfish not initialized")},getSessionId:()=>t.getSessionId(),getRunId:()=>t.getRunId(),version:()=>"0.3.91"};return r.__dev__={getDeviceInfo:()=>Ct.getDeviceInfo()},r}();if("undefined"!=typeof window&&"undefined"!=typeof document&&!document.querySelector('meta[name="saltfish-player-loaded"]')){const t=document.createElement("meta");t.name="saltfish-player-loaded",t.content="true",document.head.appendChild(t)}return"undefined"!=typeof window&&(window.saltfish=ve),ve}));
6
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).SaltfishplaylistPlayer=e()}(this,(function(){"use strict";var t=Object.defineProperty,e=(e,n,i)=>((e,n,i)=>n in e?t(e,n,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[n]=i)(e,"symbol"!=typeof n?n+"":n,i);const n={};var i=Symbol.for("immer-nothing"),s=Symbol.for("immer-draftable"),r=Symbol.for("immer-state");function a(t,...e){throw new Error(`[Immer] minified error nr: ${t}. Full error at: https://bit.ly/3cXEKWf`)}var o=Object.getPrototypeOf;function l(t){return!!t&&!!t[r]}function c(t){var e;return!!t&&(h(t)||Array.isArray(t)||!!t[s]||!!(null==(e=t.constructor)?void 0:e[s])||f(t)||y(t))}var d=Object.prototype.constructor.toString();function h(t){if(!t||"object"!=typeof t)return!1;const e=o(t);if(null===e)return!0;const n=Object.hasOwnProperty.call(e,"constructor")&&e.constructor;return n===Object||"function"==typeof n&&Function.toString.call(n)===d}function u(t,e){0===p(t)?Reflect.ownKeys(t).forEach((n=>{e(n,t[n],t)})):t.forEach(((n,i)=>e(i,n,t)))}function p(t){const e=t[r];return e?e.type_:Array.isArray(t)?1:f(t)?2:y(t)?3:0}function g(t,e){return 2===p(t)?t.has(e):Object.prototype.hasOwnProperty.call(t,e)}function m(t,e,n){const i=p(t);2===i?t.set(e,n):3===i?t.add(n):t[e]=n}function f(t){return t instanceof Map}function y(t){return t instanceof Set}function v(t){return t.copy_||t.base_}function b(t,e){if(f(t))return new Map(t);if(y(t))return new Set(t);if(Array.isArray(t))return Array.prototype.slice.call(t);const n=h(t);if(!0===e||"class_only"===e&&!n){const e=Object.getOwnPropertyDescriptors(t);delete e[r];let n=Reflect.ownKeys(e);for(let i=0;i<n.length;i++){const s=n[i],r=e[s];!1===r.writable&&(r.writable=!0,r.configurable=!0),(r.get||r.set)&&(e[s]={configurable:!0,writable:!0,enumerable:r.enumerable,value:t[s]})}return Object.create(o(t),e)}{const e=o(t);if(null!==e&&n)return{...t};const i=Object.create(e);return Object.assign(i,t)}}function w(t,e=!1){return E(t)||l(t)||!c(t)||(p(t)>1&&(t.set=t.add=t.clear=t.delete=S),Object.freeze(t),e&&Object.entries(t).forEach((([t,e])=>w(e,!0)))),t}function S(){a(2)}function E(t){return Object.isFrozen(t)}var x,M={};function I(t){const e=M[t];return e||a(0),e}function P(){return x}function C(t,e){e&&(I("Patches"),t.patches_=[],t.inversePatches_=[],t.patchListener_=e)}function _(t){k(t),t.drafts_.forEach(A),t.drafts_=null}function k(t){t===x&&(x=t.parent_)}function T(t){return x={drafts_:[],parent_:x,immer_:t,canAutoFreeze_:!0,unfinalizedDrafts_:0}}function A(t){const e=t[r];0===e.type_||1===e.type_?e.revoke_():e.revoked_=!0}function z(t,e){e.unfinalizedDrafts_=e.drafts_.length;const n=e.drafts_[0];return void 0!==t&&t!==n?(n[r].modified_&&(_(e),a(4)),c(t)&&(t=L(e,t),e.parent_||O(e,t)),e.patches_&&I("Patches").generateReplacementPatches_(n[r].base_,t,e.patches_,e.inversePatches_)):t=L(e,n,[]),_(e),e.patches_&&e.patchListener_(e.patches_,e.inversePatches_),t!==i?t:void 0}function L(t,e,n){if(E(e))return e;const i=e[r];if(!i)return u(e,((s,r)=>V(t,i,e,s,r,n))),e;if(i.scope_!==t)return e;if(!i.modified_)return O(t,i.base_,!0),i.base_;if(!i.finalized_){i.finalized_=!0,i.scope_.unfinalizedDrafts_--;const e=i.copy_;let s=e,r=!1;3===i.type_&&(s=new Set(e),e.clear(),r=!0),u(s,((s,a)=>V(t,i,e,s,a,n,r))),O(t,e,!1),n&&t.patches_&&I("Patches").generatePatches_(i,n,t.patches_,t.inversePatches_)}return i.copy_}function V(t,e,n,i,s,r,a){if(l(s)){const a=L(t,s,r&&e&&3!==e.type_&&!g(e.assigned_,i)?r.concat(i):void 0);if(m(n,i,a),!l(a))return;t.canAutoFreeze_=!1}else a&&n.add(s);if(c(s)&&!E(s)){if(!t.immer_.autoFreeze_&&t.unfinalizedDrafts_<1)return;L(t,s),e&&e.scope_.parent_||"symbol"==typeof i||!Object.prototype.propertyIsEnumerable.call(n,i)||O(t,s)}}function O(t,e,n=!1){!t.parent_&&t.immer_.autoFreeze_&&t.canAutoFreeze_&&w(e,n)}var D={get(t,e){if(e===r)return t;const n=v(t);if(!g(n,e))return function(t,e,n){var i;const s=B(e,n);return s?"value"in s?s.value:null==(i=s.get)?void 0:i.call(t.draft_):void 0}(t,n,e);const i=n[e];return t.finalized_||!c(i)?i:i===U(t.base_,e)?(R(t),t.copy_[e]=H(i,t)):i},has:(t,e)=>e in v(t),ownKeys:t=>Reflect.ownKeys(v(t)),set(t,e,n){const i=B(v(t),e);if(null==i?void 0:i.set)return i.set.call(t.draft_,n),!0;if(!t.modified_){const i=U(v(t),e),o=null==i?void 0:i[r];if(o&&o.base_===n)return t.copy_[e]=n,t.assigned_[e]=!1,!0;if(((s=n)===(a=i)?0!==s||1/s==1/a:s!=s&&a!=a)&&(void 0!==n||g(t.base_,e)))return!0;R(t),N(t)}var s,a;return t.copy_[e]===n&&(void 0!==n||e in t.copy_)||Number.isNaN(n)&&Number.isNaN(t.copy_[e])||(t.copy_[e]=n,t.assigned_[e]=!0),!0},deleteProperty:(t,e)=>(void 0!==U(t.base_,e)||e in t.base_?(t.assigned_[e]=!1,R(t),N(t)):delete t.assigned_[e],t.copy_&&delete t.copy_[e],!0),getOwnPropertyDescriptor(t,e){const n=v(t),i=Reflect.getOwnPropertyDescriptor(n,e);return i?{writable:!0,configurable:1!==t.type_||"length"!==e,enumerable:i.enumerable,value:n[e]}:i},defineProperty(){a(11)},getPrototypeOf:t=>o(t.base_),setPrototypeOf(){a(12)}},F={};function U(t,e){const n=t[r];return(n?v(n):t)[e]}function B(t,e){if(!(e in t))return;let n=o(t);for(;n;){const t=Object.getOwnPropertyDescriptor(n,e);if(t)return t;n=o(n)}}function N(t){t.modified_||(t.modified_=!0,t.parent_&&N(t.parent_))}function R(t){t.copy_||(t.copy_=b(t.base_,t.scope_.immer_.useStrictShallowCopy_))}function H(t,e){const n=f(t)?I("MapSet").proxyMap_(t,e):y(t)?I("MapSet").proxySet_(t,e):function(t,e){const n=Array.isArray(t),i={type_:n?1:0,scope_:e?e.scope_:P(),modified_:!1,finalized_:!1,assigned_:{},parent_:e,base_:t,draft_:null,copy_:null,revoke_:null,isManual_:!1};let s=i,r=D;n&&(s=[i],r=F);const{revoke:a,proxy:o}=Proxy.revocable(s,r);return i.draft_=o,i.revoke_=a,o}(t,e);return(e?e.scope_:P()).drafts_.push(n),n}function $(t){if(!c(t)||E(t))return t;const e=t[r];let n;if(e){if(!e.modified_)return e.base_;e.finalized_=!0,n=b(t,e.scope_.immer_.useStrictShallowCopy_)}else n=b(t,!0);return u(n,((t,e)=>{m(n,t,$(e))})),e&&(e.finalized_=!1),n}u(D,((t,e)=>{F[t]=function(){return arguments[0]=arguments[0][0],e.apply(this,arguments)}})),F.deleteProperty=function(t,e){return F.set.call(this,t,e,void 0)},F.set=function(t,e,n){return D.set.call(this,t[0],e,n,t[0])};var Y=new class{constructor(t){this.autoFreeze_=!0,this.useStrictShallowCopy_=!1,this.produce=(t,e,n)=>{if("function"==typeof t&&"function"!=typeof e){const n=e;e=t;const i=this;return function(t=n,...s){return i.produce(t,(t=>e.call(this,t,...s)))}}let s;if("function"!=typeof e&&a(6),void 0!==n&&"function"!=typeof n&&a(7),c(t)){const i=T(this),r=H(t,void 0);let a=!0;try{s=e(r),a=!1}finally{a?_(i):k(i)}return C(i,n),z(s,i)}if(!t||"object"!=typeof t){if(s=e(t),void 0===s&&(s=t),s===i&&(s=void 0),this.autoFreeze_&&w(s,!0),n){const e=[],i=[];I("Patches").generateReplacementPatches_(t,s,e,i),n(e,i)}return s}a(1)},this.produceWithPatches=(t,e)=>{if("function"==typeof t)return(e,...n)=>this.produceWithPatches(e,(e=>t(e,...n)));let n,i;return[this.produce(t,e,((t,e)=>{n=t,i=e})),n,i]},"boolean"==typeof(null==t?void 0:t.autoFreeze)&&this.setAutoFreeze(t.autoFreeze),"boolean"==typeof(null==t?void 0:t.useStrictShallowCopy)&&this.setUseStrictShallowCopy(t.useStrictShallowCopy)}createDraft(t){c(t)||a(8),l(t)&&(t=function(t){return l(t)||a(10),$(t)}(t));const e=T(this),n=H(t,void 0);return n[r].isManual_=!0,k(e),n}finishDraft(t,e){const n=t&&t[r];n&&n.isManual_||a(9);const{scope_:i}=n;return C(i,e),z(void 0,i)}setAutoFreeze(t){this.autoFreeze_=t}setUseStrictShallowCopy(t){this.useStrictShallowCopy_=t}applyPatches(t,e){let n;for(n=e.length-1;n>=0;n--){const i=e[n];if(0===i.path.length&&"replace"===i.op){t=i.value;break}}n>-1&&(e=e.slice(n+1));const i=I("Patches").applyPatches_;return l(t)?i(t,e):this.produce(t,(t=>i(t,e)))}},X=Y.produce;Y.produceWithPatches.bind(Y),Y.setAutoFreeze.bind(Y),Y.setUseStrictShallowCopy.bind(Y),Y.applyPatches.bind(Y),Y.createDraft.bind(Y),Y.finishDraft.bind(Y);function j(t,e){void 0!==e?console.info(t,e):console.info(t)}function W(t,e){console.warn(t)}function q(t,e){void 0!==e?console.error(t,e):console.error(t)}class Z{constructor(t,n){e(this,"currentState"),e(this,"config"),e(this,"context"),e(this,"actionHandlers",{}),this.config=t,this.currentState=t.initial,this.context=n,this.runEntryActions(this.currentState)}registerActions(t){this.actionHandlers={...this.actionHandlers,...t},Object.keys(t).join(", ")}executeAction(t,e){if("string"==typeof t){const n=this.actionHandlers[t];n&&n(this.context,e)}else t(this.context,e)}send(t){const e=this.config.states[this.currentState].on[t.type];return e?(this.currentState,e.target,t.type,this.runExitActions(this.currentState),this.updateContextFromEvent(t),e.actions&&e.actions.forEach((e=>this.executeAction(e,t))),this.currentState,this.currentState=e.target,this.runEntryActions(this.currentState),this.currentState,this.currentState):(t.type,this.currentState,this.currentState)}updateContextFromEvent(t){"TRANSITION_TO_STEP"===t.type||"MANIFEST_LOADED"===t.type||"VIDEO_FINISHED_WAIT"===t.type?this.context.currentStep=t.step:"ERROR"===t.type&&(this.context.error=t.error)}getState(){return this.currentState}getContext(){return this.context}updateContext(t){const e=t(this.context);this.context={...this.context,...e}}runEntryActions(t){const e=this.config.states[t];e.entry&&e.entry.forEach((t=>this.executeAction(t)))}runExitActions(t){const e=this.config.states[t];e.exit&&e.exit.forEach((t=>this.executeAction(t)))}}const G={initial:"idle",states:{idle:{on:{INITIALIZE:{target:"idle"},LOAD_MANIFEST:{target:"loading"}}},loading:{on:{MANIFEST_LOADED:{target:"paused"},ERROR:{target:"error"}},entry:["showLoadingState"],exit:["hideLoadingState"]},playing:{on:{PAUSE:{target:"paused"},MINIMIZE:{target:"minimized"},VIDEO_FINISHED_WAIT:{target:"waitingForInteraction"},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"},TRANSITION_TO_STEP:{target:"playing"},ERROR:{target:"error"},COMPLETE_PLAYLIST:{target:"completed"},COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION:{target:"completedWaitingForInteraction"}},entry:["startVideoPlayback","showVideoControls","hidePlayButton"],exit:["pauseVideoPlayback"]},paused:{on:{PLAY:{target:"playing"},START_IDLE_MODE:{target:"idleMode"},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"},MINIMIZE:{target:"minimized"},TRANSITION_TO_STEP:{target:"playing"}},entry:["pauseVideoPlayback","showPlayButton"]},minimized:{on:{MAXIMIZE:{target:"playing"},EXIT:{target:"closing"}},entry:["pauseVideoPlayback"]},waitingForInteraction:{on:{PLAY:{target:"playing"},PAUSE:{target:"paused"},MINIMIZE:{target:"minimized"},COMPLETE_PLAYLIST:{target:"completed"},COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION:{target:"completedWaitingForInteraction"},TRANSITION_TO_STEP:{target:"playing"}},entry:["showPlayButton"]},autoplayBlocked:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["enterCompactMode","startMutedLoopedVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls","exitCompactMode"]},idleMode:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["startIdleModeVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls","exitCompactMode"]},error:{on:{INITIALIZE:{target:"idle"},PLAY:{target:"playing"},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"}},entry:["handleError","showPlayButton"],exit:["hideError"]},completedWaitingForInteraction:{on:{COMPLETE_PLAYLIST:{target:"completed"},INITIALIZE:{target:"idle"},TRANSITION_TO_STEP:{target:"playing"},PLAY:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["showPlayButton"]},completed:{on:{INITIALIZE:{target:"idle"}},entry:["trackPlaylistComplete"]},closing:{on:{},entry:["triggerPlaylistDismissed"]}}},K="saltfish_progress",J="saltfish_session",Q="saltfish_anonymous_user_data",tt="saltfish_pending_navigation",et="sf-player--minimized",nt="sf-player__ai-badge-label--visible",it="sf-error-display--visible",st="sf-error-display__message",rt=class t{constructor(){e(this,"isLocalStorageAvailable"),this.isLocalStorageAvailable=this.checkLocalStorageAvailability(),this.isLocalStorageAvailable}static getInstance(){return t.instance||(t.instance=new t),t.instance}static resetInstance(){t.instance=null}checkLocalStorageAvailability(){if("undefined"==typeof window)return!1;try{const t="__storage_test__";return localStorage.setItem(t,"test"),localStorage.removeItem(t),!0}catch(t){return!1}}safeGetItem(t){if(!this.isLocalStorageAvailable)return null;try{const e=localStorage.getItem(t);return null===e?null:JSON.parse(e)}catch(e){return this.safeClearItem(t),null}}safeSetItem(t,e){if(!this.isLocalStorageAvailable)return!1;try{return localStorage.setItem(t,JSON.stringify(e)),!0}catch(n){if(n instanceof DOMException&&22===n.code){this.clearOldData();try{return localStorage.setItem(t,JSON.stringify(e)),!0}catch(t){}}return!1}}safeClearItem(t){if(this.isLocalStorageAvailable)try{localStorage.removeItem(t)}catch(t){}}clearOldData(){this.safeClearItem(J)}getProgress(t){const e=this.safeGetItem(K);return e?t&&e.userId&&e.userId!==t?(e.userId,null):e.playlists||null:null}setProgress(t,e){const n={userId:e,playlists:t};return this.safeSetItem(K,n)}clearProgress(){this.safeClearItem(K)}getSession(){return this.safeGetItem(J)}setSession(t){return this.safeSetItem(J,t)}clearSession(){this.safeClearItem(J)}getAnonymousUserData(){return this.safeGetItem(Q)}setAnonymousUserData(t){return this.safeSetItem(Q,t)}clearAnonymousUserData(){this.safeClearItem(Q)}getPendingNavigation(){return this.safeGetItem(tt)}setPendingNavigation(t){return t.nextStepId,t.urlPattern,this.safeSetItem(tt,t)}clearPendingNavigation(){this.safeClearItem(tt)}clearAll(){this.clearProgress(),this.clearSession(),this.clearAnonymousUserData(),this.clearPendingNavigation()}};e(rt,"instance",null);let at=rt;const ot=at.getInstance(),lt=(t=>{let e;const i=new Set,s=(t,n)=>{const s="function"==typeof t?t(e):t;if(!Object.is(s,e)){const t=e;e=(null!=n?n:"object"!=typeof s||null===s)?s:Object.assign({},e,s),i.forEach((n=>n(e,t)))}},r=()=>e,a={setState:s,getState:r,getInitialState:()=>o,subscribe:t=>(i.add(t),()=>i.delete(t)),destroy:()=>{"production"!==(n?"production":void 0)&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),i.clear()}},o=e=t(s,r,a);return a})((t=>(e,n,i)=>(i.setState=(t,n,...i)=>{const s="function"==typeof t?X(t):t;return e(s,n,...i)},t(i.setState,n,i)))(((t,e)=>{let n=new Z(G,{currentStep:null,error:null});const i=t=>n.send(t),s=e=>{const i=n.send(e);return t((t=>{t.currentState=i})),i};return{config:null,user:null,userData:null,currentState:n.getState(),manifest:null,currentStepId:null,isMinimized:!1,position:null,progress:{},error:null,playlistOptions:null,backendPlaylists:[],isAdmin:!1,isMuted:!1,abTests:[],abTestAssignments:{},initialize:async e=>{t((t=>{t.config=e,t.currentState=i({type:"INITIALIZE"})}))},setPlaylistOptions:e=>{t((t=>{if(t.playlistOptions=e,e.position){const n="bottom-left"===e.position||"bottom-right"===e.position?e.position:"bottom-right";t.position={x:0,y:0},t.playlistOptions={...e,position:n}}}))},identifyUser:(e,n)=>{const i={id:e,...n};t((t=>{t.user=i}))},mergeUserFields:e=>{t((t=>{t.user&&Object.assign(t.user,e)}))},setUserData:e=>{t((t=>{var n;const i=(null==e?void 0:e.watchedPlaylists)||{},s=(null==(n=t.userData)?void 0:n.watchedPlaylists)||{},r={...i};for(const[t,e]of Object.entries(s)){if(!e)continue;const n=r[t],i="completed"===e.status||"dismissed"===e.status,s=!!n&&("completed"===n.status||"dismissed"===n.status);if(i&&!s)r[t]=e,e.status,null==n||n.status;else if(n){const i=Math.max(e.visitCount??0,n.visitCount??0);(n.visitCount??0)!==i&&(r[t]={...n,visitCount:i})}}t.userData={...e,watchedPlaylists:r}}))},updateWatchedPlaylist:(e,n,i)=>{t((t=>{t.userData||(t.userData={watchedPlaylists:{}}),t.userData.watchedPlaylists||(t.userData.watchedPlaylists={});const s=t.userData.watchedPlaylists[e],r=null==s?void 0:s.status,a=(null==s?void 0:s.visitCount)??0,o=("completed"===n||"dismissed"===n)&&r!==n,l=Date.now();t.userData.watchedPlaylists[e]={status:n,currentStepId:"completed"===n?null:i??t.currentStepId??null,timestamp:l,lastProgressAt:l,visitCount:o?a+1:a}}))},setManifest:(e,n)=>{t((t=>{t.manifest=e,t.currentStepId=n;const s=e.steps.find((t=>t.id===n));t.currentState=i(s?{type:"MANIFEST_LOADED",step:s}:{type:"ERROR",error:new Error(`Start step '${n}' not found in manifest`)})}))},play:()=>{const{currentState:n}=e();t((t=>{t.currentState=i({type:"PLAY"})}))},pause:()=>{const{currentState:n}=e();t((t=>{t.currentState=i({type:"PAUSE"})}))},minimize:()=>{const{currentState:n}=e();t((t=>{"playing"===t.currentState&&(t.currentState=i({type:"PAUSE"})),t.currentState=i({type:"MINIMIZE"}),t.isMinimized=!0}))},maximize:()=>{t((t=>{t.currentState=i({type:"MAXIMIZE"}),t.isMinimized=!1}))},goToStep:n=>{const{manifest:r}=e();if("completed"!==n){if(r&&r.steps.some((t=>t.id===n))){const e=r.steps.find((t=>t.id===n));t((t=>{var s,a,o;if(t.currentStepId=n,e&&(t.currentState=i({type:"TRANSITION_TO_STEP",step:e}),(t.position||(null==(s=t.playlistOptions)?void 0:s.position))&&(t.position={x:0,y:0})),t.progress[r.id]={...t.progress[r.id],lastStepId:n,lastVisited:(new Date).toISOString()},(null==(a=t.playlistOptions)?void 0:a.persistence)??1){const e=null==(o=t.user)?void 0:o.id;ot.setProgress(t.progress,e)}}))}}else s({type:"COMPLETE_PLAYLIST"})},reset:()=>{t((t=>{t.config=null,t.user=null,t.userData=null,t.currentState=n.getState(),t.manifest=null,t.currentStepId=null,t.isMinimized=!1,t.position=null,t.progress={},t.error=null,n=new Z(G,{currentStep:null,error:null})}))},setError:e=>{t((t=>{t.currentState=i({type:"ERROR",error:e}),t.error=e}))},setAutoplayFallback:()=>{t((t=>{t.currentState=i({type:"AUTOPLAY_FALLBACK"})}))},setIdleMode:()=>{t((t=>{t.currentState=i({type:"START_IDLE_MODE"})}))},setMuted:e=>{t((t=>{t.isMuted=e}))},setBackendPlaylists:e=>{t((t=>{t.backendPlaylists=e}))},setIsAdmin:e=>{t((t=>{t.isAdmin=e}))},completePlaylist:()=>{s({type:"COMPLETE_PLAYLIST"})},resetForNewPlaylist:()=>{t((t=>{const e=t.config,i=t.user,s=t.userData,r=t.progress;t.manifest=null,t.currentStepId=null,t.isMinimized=!1,t.position=null,t.error=null,t.playlistOptions=null,n=new Z(G,{currentStep:null,error:null}),t.currentState=n.getState(),t.config=e,t.user=i,t.userData=s,t.progress=r}))},loadPlaylistProgress:(e,n)=>{t((t=>{t.progress[e]=n}))},registerStateMachineActions:t=>{n.registerActions(t)},sendStateMachineEvent:t=>{s(t)},updateProgressWithCompletion:(e,n)=>{t((t=>{var s,r;if(t.currentState=i({type:"COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION"}),t.progress[e]={...t.progress[e],lastStepId:n,lastVisited:(new Date).toISOString(),completedWaitingForInteraction:!0},(null==(s=t.playlistOptions)?void 0:s.persistence)??1){const e=null==(r=t.user)?void 0:r.id;ot.setProgress(t.progress,e)}}))},setABTests:e=>{t((t=>{t.abTests=e}))},setABTestAssignments:e=>{t((t=>{t.abTestAssignments=e}))},getFilteredPlaylists:()=>{const t=e(),n=t.backendPlaylists||[],i=t.abTests||[],s=t.abTestAssignments||{};if(0===i.length)return n;const r=new Set;for(const t of i){const e=s[t.id];e&&e.assigned||r.add(t.playlistId)}return n.filter((t=>!r.has(t.id)))}}}))),ct={getState:()=>lt.getState(),setState:lt.setState,subscribe:lt.subscribe,destroy:lt.destroy};function dt(){try{return ct.getState()}catch(t){throw new Error(`[storeUtils] Failed to access Saltfish store: ${t}`)}}function ht(t){if(!t)return null;if(t.lastProgressAt&&"object"==typeof t.lastProgressAt&&"_seconds"in t.lastProgressAt&&"_nanoseconds"in t.lastProgressAt){const e=t.lastProgressAt;return 1e3*e._seconds+Math.floor(e._nanoseconds/1e6)}return t.timestamp&&"number"==typeof t.timestamp?t.timestamp:t.lastProgressAt&&"number"==typeof t.lastProgressAt?t.lastProgressAt:null}function ut(t,e=6e3){const n=ht(t);if(!n)return{isValid:!1,ageMs:null,timestampMs:null};const i=Date.now()-n;return{isValid:i<=e,ageMs:i,timestampMs:n}}class pt{static handle(t,e={},n={}){var i;const s={...this.DEFAULT_OPTIONS,...n},r=this.normalizeError(t,e);if(s.shouldLog&&this.logError(r,e,s.severity),s.shouldUpdateStore&&this.updateStore(r),s.shouldTriggerEvent&&this.triggerErrorEvent(r,e,null==(i=e.component)?void 0:i.toLowerCase()),s.shouldDestroy&&this.destroyPlayer(),s.shouldThrow)throw r;return r}static handleInitializationError(t,e={}){return this.handle(t,{...e,component:"Initialization"},{severity:"critical",shouldLog:!0,shouldUpdateStore:!0,shouldDestroy:!0,shouldThrow:!0})}static handlePlaylistError(t,e={}){return this.handle(t,{...e,component:"Playlist"},{severity:"error",shouldLog:!0,shouldUpdateStore:!0,shouldTriggerEvent:!0})}static handleVideoError(t,e={}){return this.handle(t,{...e,component:"Video"},{severity:"error",shouldLog:!0,shouldUpdateStore:!0,shouldTriggerEvent:!0})}static handleNetworkError(t,e={}){return this.handle(t,{...e,component:"Network"},{severity:"warning",shouldLog:!0,shouldTriggerEvent:!0})}static handleWarning(t,e={}){return this.handle(t,e,{severity:"warning",shouldLog:!0,shouldThrow:!1})}static handleCleanupError(t,e={}){return this.handle(t,{...e,component:"Cleanup"},{severity:"warning",shouldLog:!0,shouldThrow:!1})}static normalizeError(t,e){if(t instanceof Error)return t;if("string"==typeof t)return new Error(t);const n=String(t&&"object"==typeof t&&"message"in t?t.message:t);return new Error(`Unknown error in ${e.component||"application"}: ${n}`)}static formatErrorMessage(t,e){const n=[];return e.component&&n.push(`[${e.component}]`),e.method&&n.push(`${e.method}:`),n.push(t.message),n.join(" ")}static logError(t,e,n){const i=this.formatErrorMessage(t,e),s={error:{name:t.name,message:t.message,stack:t.stack},context:e,severity:n,timestamp:(new Date).toISOString()};switch(n){case"info":break;case"warning":console.warn(i,s);break;case"error":case"critical":console.error(i,s)}}static updateStore(t){try{dt().setError(t)}catch(t){console.error("Failed to update store with error:",t)}}static triggerErrorEvent(t,e,n){var i,s;try{const r=dt();if("undefined"!=typeof window&&window._saltfishPlayer){const a=window._saltfishPlayer;a&&a.eventManager&&a.eventManager.trigger("error",{timestamp:Date.now(),playlistId:e.playlistId||(null==(i=r.manifest)?void 0:i.id),stepId:e.stepId||r.currentStepId,error:t,errorType:e.errorType||n||(null==(s=e.component)?void 0:s.toLowerCase())||"unknown"})}}catch(t){console.error("Failed to trigger error event:",t)}}static destroyPlayer(){try{if("undefined"!=typeof window&&window._saltfishPlayer){const t=window._saltfishPlayer;t&&"function"==typeof t.destroy&&t.destroy()}}catch(t){console.error("Failed to destroy player during error handling:",t)}}static createError(t,e={}){const n=new Error(this.formatErrorMessage(new Error(t),e));return e.component&&(n.component=e.component),e.method&&(n.method=e.method),e.playlistId&&(n.playlistId=e.playlistId),e.stepId&&(n.stepId=e.stepId),n}static isRecoverable(t){return!!(t.message.includes("fetch")||t.message.includes("network")||t.message.includes("timeout"))||[/autoplay.*blocked/i,/video.*failed.*load/i,/manifest.*not.*found/i].some((e=>e.test(t.message)))}static async safeExecute(t,e={},n={}){try{return await t()}catch(t){return this.handle(t,e,n),null}}}e(pt,"DEFAULT_OPTIONS",{severity:"error",shouldLog:!0,shouldThrow:!1,shouldUpdateStore:!1,shouldTriggerEvent:!1,shouldDestroy:!1});class gt{detectShareIdFromUrl(){try{const t=window.location.href,e=/saltfish-share-id=([^&#]*)/,n=t.match(e);if(n&&n[1]){return n[1]}return null}catch(t){return null}}async fetchShareData(t){try{const e=await fetch(`https://studio-api.saltfish.ai/studio/flows2/share/${t}`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error(`Share API returned status ${e.status}`);const n=await e.json();if(!n.flowId)throw new Error("Share API response missing flowId");return n.shareId,n.flowId,n.createdBy,n}catch(e){throw pt.handleInitializationError(e,{component:"ShareLinkService",method:"fetchShareData",additionalData:{shareId:t}})}}async shouldAutoStartSharePlaylist(){try{const t=this.detectShareIdFromUrl();if(!t)return null;const e=await this.fetchShareData(t);return e.flowId,e.isGlobal,e}catch(t){return null}}}const mt=100;function ft(t){try{let e=t.replace(/[?&]saltfish-share-id=[^&#]*/g,((e,n)=>e.startsWith("?")&&t.substring(n+e.length).startsWith("&")?"?":""));return e=e.replace(/\?&/g,"?"),e=e.replace(/&&/g,"&"),e=e.replace(/\?$/g,""),e=e.replace(/&$/g,""),e}catch(e){return t}}function yt(t){const{pattern:e,matchType:n}=t;if(!e)return!0;const i=ft(window.location.href),s=window.location.pathname;if("regex"===n)try{const t=new RegExp(e),n=t.test(i),r=t.test(s);return n||r}catch(t){return!1}return"contains"===n?i.includes(e)||s.includes(e):i===e||s===e}class vt{constructor(t){e(this,"managers"),e(this,"userManagementService"),e(this,"playlistOrchestrator"),e(this,"shareLinkService"),e(this,"lastConfig",null),e(this,"boundVisibilityHandler",null),e(this,"lastUserDataFetchTimestamp",0),e(this,"currentUserId",null),e(this,"currentUserData"),e(this,"isAnonymousUser",!1),this.managers=t,this.shareLinkService=new gt}setUserManagementService(t){this.userManagementService=t}setPlaylistOrchestrator(t){this.playlistOrchestrator=t}getLastConfig(){return this.lastConfig}async initialize(t){var e;try{const n=await fetch("https://player.saltfish.ai/validate-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t.token,playerVersion:"0.3.81"})}),i=await n.json();if(!i.isValid)throw pt.handleInitializationError(i.error||"Token validation failed",{component:"PlayerInitializationService",method:"initialize",additionalData:{token:(null==(e=t.token)?void 0:e.substring(0,10))+"..."}});const s={...t,showLogo:!1!==i.showLogo};this.lastConfig=s;const r=dt();if(r.initialize(s),this.managers.analyticsManager.initialize(t,this.managers.sessionManager.getSessionId()),i.isAdmin&&r.setIsAdmin&&r.setIsAdmin(!0),i.playlists&&Array.isArray(i.playlists)&&r.setBackendPlaylists)i.playlists,r.setBackendPlaylists(i.playlists),i.playlists.length>0?this.managers.triggerManager.registerTriggers(i.playlists):i.isAdmin,i.abTests&&Array.isArray(i.abTests)&&(i.abTests,this.managers.abTestManager.initializeTests(i.abTests));else if(!i.isAdmin)throw pt.handleInitializationError("Backend validation successful, but no playlists array provided in the response. Cannot initialize player.",{component:"PlayerInitializationService",method:"initialize",additionalData:{responseData:i}});this.managers.eventManager.trigger("initialized",{timestamp:Date.now()})}catch(t){throw pt.handleInitializationError(t,{component:"PlayerInitializationService",method:"initialize"})}}async fetchUserData(t,e){var n;try{const i=dt();if(!(null==(n=i.config)?void 0:n.token))return void pt.handleWarning("Cannot fetch user data: Token not available",{component:"PlayerInitializationService",method:"fetchUserData",userId:t});const s=await fetch(`https://player.saltfish.ai/clients/${i.config.token}/users/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userData:e})});if(!s.ok)return await s.text(),s.status,void s.statusText;const r=await s.json();if(r.success){this.currentUserId=t,this.currentUserData=e,this.isAnonymousUser=!1,this.lastUserDataFetchTimestamp=Date.now(),r.firstIdentifiedAt&&i.mergeUserFields({firstIdentifiedAt:r.firstIdentifiedAt}),i.setUserData({watchedPlaylists:r.watchedPlaylists||{},language:r.language});const n=r.userListAssignments||{},s=r.abTestAssignments||{};this.managers.abTestManager.assignUserToTests(t,s,n),this.setupVisibilityChangeListener(),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:r.watchedPlaylists||{}}}),this.userManagementService&&this.userManagementService.resolveUserDataLoaded();if(!await this.checkAndResumeFromPendingNavigation()&&!await this.checkAndResumeInProgressPlaylist(r.watchedPlaylists||{})){const t=await this.shareLinkService.shouldAutoStartSharePlaylist();t&&this.playlistOrchestrator?(t.flowId,await this.playlistOrchestrator.startPlaylist(t.flowId,{once:!1,position:"bottom-right",_startedFromShareLink:!0,_isGlobalShare:t.isGlobal})):this.managers.triggerManager.startMonitoring()}}else this.userManagementService&&this.userManagementService.resolveUserDataLoaded()}catch(e){pt.handleNetworkError(e,{component:"PlayerInitializationService",method:"fetchUserData",userId:t}),this.userManagementService&&this.userManagementService.resolveUserDataLoaded()}}async loadAnonymousUserData(t,e){try{if("undefined"==typeof window)return;const n=this.managers.abTestManager.assignUserToTests(t,void 0,{}),i=this.managers.storageManager.getAnonymousUserData();let s={userId:t,userData:e||{},watchedPlaylists:{},abTestAssignments:n,timestamp:Date.now()};if(i){const n=i.abTestAssignments||{},r=this.managers.abTestManager.assignUserToTests(t,n);s={userId:t,userData:{...i.userData,...e},watchedPlaylists:i.watchedPlaylists||{},abTestAssignments:r,timestamp:Date.now()}}this.managers.storageManager.setAnonymousUserData(s),this.currentUserId=t,this.currentUserData=e,this.isAnonymousUser=!0,this.lastUserDataFetchTimestamp=Date.now(),dt().setUserData({watchedPlaylists:s.watchedPlaylists||{},language:null==e?void 0:e.language}),this.setupVisibilityChangeListener(),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:s.watchedPlaylists||{}}});const r=await this.checkAndResumeFromPendingNavigation(),a=s.watchedPlaylists||{};if(!r&&!await this.checkAndResumeInProgressPlaylist(a)){const t=await this.shareLinkService.shouldAutoStartSharePlaylist();t&&this.playlistOrchestrator?(t.flowId,await this.playlistOrchestrator.startPlaylist(t.flowId,{once:!1,position:"bottom-right",_startedFromShareLink:!0,_isGlobalShare:t.isGlobal})):this.managers.triggerManager.startMonitoring()}}catch(e){pt.handleNetworkError(e,{component:"PlayerInitializationService",method:"loadAnonymousUserData",userId:t})}}async checkAndResumeInProgressPlaylist(t){var e;if(!t)return!1;const n=dt(),i=null==(e=n.manifest)?void 0:e.id,s=n.currentState;if(i&&"idle"!==s&&"error"!==s)return!1;const r=Object.entries(t).find((([t,e])=>{if("in_progress"!==(null==e?void 0:e.status))return!1;const{isValid:n,ageMs:i}=ut(e);return!!n}));if(r){const[t,e]=r;ht(e);try{if(this.playlistOrchestrator)return await this.playlistOrchestrator.startPlaylist(t),!0}catch(t){return!1}}return!1}async checkAndResumeFromPendingNavigation(){const t=this.managers.storageManager.getPendingNavigation();if(!t)return!1;if(Date.now()-t.timestamp>6e4)return this.managers.storageManager.clearPendingNavigation(),!1;if(!this.isURLPathMatch(t.urlPattern))return t.urlPattern,this.managers.storageManager.clearPendingNavigation(),!1;t.playlistId,t.nextStepId,this.managers.storageManager.clearPendingNavigation();try{if(this.playlistOrchestrator)return await this.playlistOrchestrator.startPlaylist(t.playlistId,{startNodeId:t.nextStepId}),!0}catch(t){return!1}return!1}isURLPathMatch(t){if(!t||"undefined"==typeof window)return!1;const e=ft(window.location.href),n=window.location.pathname,i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*"),s=new RegExp(i);return s.test(e)||s.test(n)}getOrCreateAnonymousUserId(){if("undefined"==typeof window)return`anonymous_${Date.now()}_${Math.random().toString(36).substring(2,11)}`;const t=this.managers.storageManager.getAnonymousUserData();if(null==t?void 0:t.userId)return t.userId,t.userId;const e=`anonymous_${Date.now()}_${Math.random().toString(36).substring(2,11)}`;return this.managers.storageManager.setAnonymousUserData({userId:e,userData:{},watchedPlaylists:{},timestamp:Date.now()}),e}setupVisibilityChangeListener(){"undefined"!=typeof window&&"undefined"!=typeof document&&(this.removeVisibilityChangeListener(),this.boundVisibilityHandler=()=>this.handleVisibilityChange(),document.addEventListener("visibilitychange",this.boundVisibilityHandler))}removeVisibilityChangeListener(){this.boundVisibilityHandler&&"undefined"!=typeof document&&(document.removeEventListener("visibilitychange",this.boundVisibilityHandler),this.boundVisibilityHandler=null)}async handleVisibilityChange(){if("visible"!==document.visibilityState)return;if(!this.currentUserId)return;if(Date.now()-this.lastUserDataFetchTimestamp<5e3)return;const t=dt().currentState;if(!["playing","paused","loading","waitingForInteraction","autoplayBlocked","minimized","idleMode"].includes(t))try{this.isAnonymousUser?await this.refreshAnonymousUserData():await this.refreshIdentifiedUserData()}catch(t){}}async refreshIdentifiedUserData(){var t;const e=dt();if((null==(t=e.config)?void 0:t.token)&&this.currentUserId){this.currentUserId;try{const t=await fetch(`https://player.saltfish.ai/clients/${e.config.token}/users/${this.currentUserId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userData:this.currentUserData})});if(!t.ok)return;const n=await t.json();if(n.success){this.lastUserDataFetchTimestamp=Date.now(),n.firstIdentifiedAt&&e.mergeUserFields({firstIdentifiedAt:n.firstIdentifiedAt}),e.setUserData({watchedPlaylists:n.watchedPlaylists||{},language:n.language});const t=n.userListAssignments||{},i=n.abTestAssignments||{};this.managers.abTestManager.assignUserToTests(this.currentUserId,i,t),this.managers.triggerManager.evaluateAllTriggers()}}catch(t){}}}async refreshAnonymousUserData(){var t;if(!this.currentUserId)return;this.currentUserId,this.lastUserDataFetchTimestamp=Date.now();const e=this.managers.storageManager.getAnonymousUserData();e&&(dt().setUserData({watchedPlaylists:e.watchedPlaylists||{},language:null==(t=this.currentUserData)?void 0:t.language}),this.managers.triggerManager.evaluateAllTriggers())}destroy(){this.removeVisibilityChangeListener(),this.lastConfig=null,this.currentUserId=null,this.currentUserData=void 0,this.lastUserDataFetchTimestamp=0,this.isAnonymousUser=!1}}function bt(t){if(t)return"auto"===t?function(){try{const t=navigator.language||navigator.userLanguage;if(!t)return;return t.split("-")[0].toLowerCase()}catch(t){return}}():t.split("-")[0].toLowerCase()}class wt{constructor(t){e(this,"managers"),e(this,"playerInitializationService"),e(this,"userDataLoadedPromise",null),e(this,"userDataLoadedResolve",null),e(this,"lastUserIdentification",null),this.managers=t}setPlayerInitializationService(t){this.playerInitializationService=t}getLastUserIdentification(){return this.lastUserIdentification}getUserDataLoadedPromise(){return this.userDataLoadedPromise}identifyUser(t,e){let n=e;if(e&&"string"==typeof e.language){const t=bt(e.language);n={...e,language:t},e.language}this.lastUserIdentification={userId:t,userData:n};const i=dt();i.identifyUser(t,n),this.managers.analyticsManager.setUser({id:t,...n}),(i.abTests||[]).length>0&&(this.userDataLoadedPromise=new Promise((t=>{this.userDataLoadedResolve=t}))),this.playerInitializationService&&this.playerInitializationService.fetchUserData(t,n)}async identifyAnonymous(t){if(!this.playerInitializationService)throw new Error("PlayerInitializationService not set");let e=t;if(t&&"string"==typeof t.language){const n=bt(t.language);e={...t,language:n},t.language}const n=this.playerInitializationService.getOrCreateAnonymousUserId();this.lastUserIdentification={userId:n,userData:e},dt().identifyUser(n,{...e,__isAnonymous:!0}),this.managers.analyticsManager.setUser({id:n,...e}),await this.playerInitializationService.loadAnonymousUserData(n,e)}async recordABTestAttempt(t){var e;try{const n=dt(),i=n.user;if(!i||!(null==(e=n.config)?void 0:e.token))return;const s=(n.abTests||[]).find((e=>e.playlistId===t));if(!s)return;const r=(n.abTestAssignments||{})[s.id];if(!r)return void s.id;s.name,r.assigned;const a=await fetch(`https://player.saltfish.ai/clients/${n.config.token}/users/${i.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({abTestAssignments:{[s.id]:r}})});a.ok?s.name:(a.status,a.statusText)}catch(t){}}resolveUserDataLoaded(){this.userDataLoadedResolve&&(this.userDataLoadedResolve(),this.userDataLoadedResolve=null,this.userDataLoadedPromise=null)}destroy(){this.userDataLoadedPromise=null,this.userDataLoadedResolve=null,this.lastUserIdentification=null}}class St{async validatePlaylistStart(t){const{playlistId:e,options:n,eventManager:i}=t;try{const t=dt();if(!t.config)return{isValid:!1,error:"Saltfish Player must be initialized before starting a playlist"};if(!0===t.isAdmin)return{isValid:!0,manifestPath:`https://storage.saltfish.ai/flows2/drafts/${e}.json`,updatedOptions:n};if(!0===(null==n?void 0:n._startedFromShareLink)&&!0===(null==n?void 0:n._isGlobalShare))return{isValid:!0,manifestPath:`https://storage.saltfish.ai/flows2/drafts/${e}.json`,updatedOptions:n};!0===(null==n?void 0:n._startedFromShareLink)&&(null==n||n._isGlobalShare);const s=t.backendPlaylists;if(!s||0===s.length)return pt.handlePlaylistError("No playlist list available from backend validation",{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,errorType:"playlist_backend_unavailable"}),{isValid:!1,error:"No backend playlists available"};const r=s.find((t=>t.id===e));if(!r)return pt.handlePlaylistError(`Playlist ID '${e}' not found in the list provided by backend validation`,{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,errorType:"playlist_not_found",additionalData:{backendPlaylists:s}}),{isValid:!1,error:"Playlist not found in backend list"};if((null==r?void 0:r.hasTriggers)??(null==r?void 0:r.autoStart)){const t=await this.validateTriggerConditions(e,r,i);if(!t.isValid)return t}let a=n;if(null==n?void 0:n.once){const t=await this.validateOnceOptionConditions(e,n,i);if(!t.isValid)return t;a=t.updatedOptions||n}const o=await this.validateDeviceCompatibility(r,e);return o.isValid?{isValid:!0,manifestPath:r.path,updatedOptions:a}:o}catch(t){const n=t instanceof Error?t.message:"Unknown validation error";return pt.handlePlaylistError(`Playlist validation failed: ${n}`,{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,additionalData:{error:t}}),{isValid:!1,error:n}}}async validateTriggerConditions(t,e,n){var i,s;const r=dt();if(!r.user)return pt.handlePlaylistError("User must be identified before starting auto-start playlist",{component:"PlaylistValidator",method:"validateAutoStartConditions",playlistId:t,errorType:"playlist_user_required"}),{isValid:!1,error:"User identification required for triggered playlist"};r.userData||await this.waitForUserData(n);const a=(null==(i=dt().userData)?void 0:i.watchedPlaylists)||{},o=e.hasTriggers??e.autoStart??!1,l=a[t],c=null==(s=e.triggers)?void 0:s.maxVisits,d=(null==l?void 0:l.visitCount)??("completed"===(null==l?void 0:l.status)||"dismissed"===(null==l?void 0:l.status)?1:0);return o&&null!=c&&d>=c?(j(`Playlist ${t} has hasTriggers enabled with maxVisits:${c} and user has ${d} visits. Skipping playlist start.`,{watchedPlaylists:a,triggers:e.triggers}),{isValid:!1,error:`Playlist visit limit reached (${d}/${c})`}):{isValid:!0}}async validateOnceOptionConditions(t,e,n){var i;const s=dt();if(!s.user)return pt.handlePlaylistError("User must be identified before starting playlist with once option",{component:"PlaylistValidator",method:"validateOnceOptionConditions",playlistId:t,errorType:"playlist_auth_required"}),{isValid:!1,error:"User identification required for once option"};s.userData||await this.waitForUserData(n);const r=(null==(i=dt().userData)?void 0:i.watchedPlaylists)||{},a=r[t];return!a||"completed"!==a.status&&"dismissed"!==a.status?a&&"in_progress"===a.status&&!(null==e?void 0:e.startNodeId)&&a.currentStepId?{isValid:!0,updatedOptions:{...e,startNodeId:a.currentStepId}}:{isValid:!0}:(j(`Playlist ${t} has once option enabled and has already been ${a.status}. Skipping playlist start.`,{watchedPlaylists:r,playlistStatus:a.status}),{isValid:!1,error:`Playlist already ${a.status} with once option`})}async validateDeviceCompatibility(t,e){try{const n=t.deviceType||"both",{isDeviceCompatible:i}=await Promise.resolve().then((()=>kt));return i(n)?{isValid:!0}:(pt.handlePlaylistError(`Playlist '${e}' is not compatible with this device. Required: ${n}`,{component:"PlaylistValidator",method:"validateDeviceCompatibility",playlistId:e,errorType:"playlist_device_incompatible",additionalData:{requiredDeviceType:n,manifestPath:t.path}}),{isValid:!1,error:`Device incompatible. Required: ${n}`})}catch(n){const i=n instanceof Error?n.message:"Unknown error";return pt.handlePlaylistError(`Device compatibility check failed: ${i}`,{component:"PlaylistValidator",method:"validateDeviceCompatibility",playlistId:e,additionalData:{error:n,manifestPath:t.path}}),{isValid:!1,error:`Device compatibility check failed: ${i}`}}}async waitForUserData(t){return new Promise(((e,n)=>{const i=setTimeout((()=>{t.off("userDataLoaded",s),n(new Error("Timeout waiting for user data"))}),5e3),s=()=>{clearTimeout(i),dt(),e()};t.on("userDataLoaded",s)}))}}class Et{constructor(t){e(this,"managers"),e(this,"userManagementService"),e(this,"managerOrchestrator"),e(this,"playerInitializationService"),e(this,"stateMachineActionHandler"),this.managers=t}setUserManagementService(t){this.userManagementService=t}setManagerOrchestrator(t){this.managerOrchestrator=t}setPlayerInitializationService(t){this.playerInitializationService=t}setStateMachineActionHandler(t){this.stateMachineActionHandler=t}async startPlaylist(t,e){var n,i,s,r,a;try{const o=this.isInitialized()&&!this.managers.uiManager.getPlayerElement();if(!this.isInitialized()&&this.playerInitializationService){const e=this.playerInitializationService.getLastConfig();if(e)try{await this.playerInitializationService.initialize(e);const t=null==(n=this.userManagementService)?void 0:n.getLastUserIdentification();t&&this.userManagementService&&this.userManagementService.identifyUser(t.userId,t.userData),this.resetManagers(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()}catch(e){throw pt.handleInitializationError(`Failed to reinitialize player: ${e instanceof Error?e.message:"Unknown error"}`,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,additionalData:{reinitError:e}})}}o&&(this.resetManagers(),this.managers.transitionManager.setTriggerManager(this.managers.triggerManager),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions());const l=dt();if(!l.config){if(!(null==(i=this.playerInitializationService)?void 0:i.getLastConfig()))throw pt.createError("Saltfish Player must be initialized at least once before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t});throw pt.createError("Saltfish Player must be initialized before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t})}l.manifest&&("playing"===l.currentState||"paused"===l.currentState||"loading"===l.currentState||"waitingForInteraction"===l.currentState||"autoplayBlocked"===l.currentState||"minimized"===l.currentState||"idleMode"===l.currentState)&&(this.managerOrchestrator&&this.managerOrchestrator.cleanupCurrentPlaylist(),l.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()),"completed"!==l.currentState&&"closing"!==l.currentState||(l.currentState,l.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()),this.managers.sessionManager.startNewRun(),this.managers.triggerManager.markPlaylistAsTriggered(t);const c=null==(s=this.userManagementService)?void 0:s.getUserDataLoadedPromise();if(c&&await c,this.userManagementService&&await this.userManagementService.recordABTestAttempt(t),!0!==(null==e?void 0:e._startedFromShareLink)){if(!this.managers.abTestManager.isPlaylistAvailable(t))return}else null==e||e._startedFromShareLink;const d=new St,h=await d.validatePlaylistStart({playlistId:t,options:e,eventManager:this.managers.eventManager});if(!h.isValid)return;e=h.updatedOptions||e;const u=h.manifestPath,p=e||{};p?(l.setPlaylistOptions(p),p.position||l.setPlaylistOptions({...p,position:"bottom-right"})):l.setPlaylistOptions({position:"bottom-right"}),this.managers.uiManager.createPlayerUI(this.managers.videoManager,this.managers.cursorManager,this.managers.interactionManager),this.managerOrchestrator&&this.managerOrchestrator.setupUpdaters(),this.managers.uiManager.updatePosition(),l.sendStateMachineEvent({type:"LOAD_MANIFEST"});const g=null==e?void 0:e.persistence;if("undefined"!=typeof window){const e=null==(r=l.user)?void 0:r.id,n=this.managers.storageManager.getProgress(e);if(n&&n[t])l.loadPlaylistProgress(t,n[t]);else if(l.progress[t]){const e={...l.progress};delete e[t],ct.setState((t=>{t.progress=e}))}}this.managers.cursorManager.resetFirstAnimation(),await this.managers.playlistManager.load(u,{...p,persistence:g});const m=dt();if(m.manifest){const t=p.persistence??m.manifest.isPersistent??!0,e=m.playlistOptions||{};m.setPlaylistOptions({...e,...p,persistence:t})}if(p.startNodeId&&m.manifest&&(m.manifest.steps.find((t=>t.id===p.startNodeId))?m.goToStep(p.startNodeId):console.warn(`[PlaylistOrchestrator] startNodeId '${p.startNodeId}' not found in manifest steps. Starting from default step.`)),m.manifest){m.manifest.cursorColor&&this.managers.cursorManager.setColor(m.manifest.cursorColor),m.manifest.cursorLabel&&this.managers.cursorManager.setLabel(m.manifest.cursorLabel),p._triggeredByTriggerManager;const t=m.currentStepId===(null==(a=m.manifest.steps[0])?void 0:a.id);if(m.manifest.idleMode&&t){if(m.manifest.compactFirstStep){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.add("sf-player--compact"),m.manifest.compactLabel&&this.managers.uiManager.showCompactLabel(m.manifest.compactLabel)}l.setIdleMode()}else l.play()}else l.play();j(`Playlist started: ${t}${m.manifest?` (${m.manifest.name})`:""}`)}catch(e){this.managers.uiManager.hideLoading(),dt().sendStateMachineEvent({type:"ERROR",error:e instanceof Error?e:new Error(String(e))}),pt.handlePlaylistError(e,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,errorType:"playlist_load_failed"})}}resetPlaylist(){const t=dt();t.manifest&&t.goToStep(t.manifest.startStep)}isInitialized(){return!!dt().config}resetManagers(){this.managers.videoManager.reset(),this.managers.cursorManager.reset(),this.managers.interactionManager.reset(),this.managers.transitionManager.reset(),this.managers.uiManager.reset(),this.managers.stepTimeoutManager.reset()}destroy(){}}class xt{constructor(t,n){e(this,"listener",null),e(this,"videoElement",null),e(this,"stepId",null),this.managers=t,this.logPrefix=n}cleanup(t){if(t&&this.stepId&&t!==this.stepId)return this.logPrefix,void this.stepId;this.listener&&this.videoElement&&(this.videoElement.removeEventListener("timeupdate",this.listener),this.listener=null,this.videoElement=null,this.stepId=null)}schedule(t,e){this.cleanup();let n=t.showAtSeconds??0;if("number"==typeof n&&isFinite(n)||(this.logPrefix,n=0),n<0&&(this.logPrefix,n=0),n<=0)return this.logPrefix,void this.managers.cursorManager.animate(t);this.logPrefix;const i=this.managers.videoManager.getVideoElement();if(!i)return void this.logPrefix;let s=!1,r=!1;const a=()=>{if(s)return;const e=i.currentTime,a=i.duration;if(a&&!isNaN(a)&&n>a&&!r)return this.logPrefix,r=!0,s=!0,this.cleanup(),void this.managers.cursorManager.animate(t);e>=n&&(s=!0,this.logPrefix,this.cleanup(),this.managers.cursorManager.animate(t))};this.listener=()=>{a()},this.videoElement=i,this.stepId=e,i.addEventListener("timeupdate",this.listener),i.addEventListener("ended",(()=>{if(s)return;const n=dt();if(n.currentStepId!==e)return this.logPrefix,n.currentStepId,void this.cleanup(e);i.duration,this.logPrefix,s=!0,this.managers.cursorManager.animate(t),this.cleanup()}),{once:!0})}}class Mt{constructor(t){e(this,"managers"),e(this,"destroyCallback",null),e(this,"cursorScheduler"),this.managers=t,this.cursorScheduler=new xt(t,"StateMachineActionHandler")}setDestroyCallback(t){this.destroyCallback=t}registerStateMachineActions(){dt().registerStateMachineActions({startVideoPlayback:t=>this.handleStartVideoPlayback(t),startIdleModeVideo:t=>this.handleStartIdleModeVideo(t),handleError:t=>this.handleError(t),pauseVideoPlayback:()=>this.handlePauseVideoPlayback(),startMutedLoopedVideo:()=>this.handleStartMutedLoopedVideo(),trackPlaylistComplete:()=>this.handleTrackPlaylistComplete(),hideError:()=>this.handleHideError(),showLoadingState:()=>this.handleShowLoadingState(),hideLoadingState:()=>this.handleHideLoadingState(),hideVideoControls:()=>this.handleHideVideoControls(),showVideoControls:()=>this.handleShowVideoControls(),showPlayButton:()=>this.handleShowPlayButton(),hidePlayButton:()=>this.handleHidePlayButton(),enablePlayButtonProminent:()=>this.handleEnablePlayButtonProminent(),disablePlayButtonProminent:()=>this.handleDisablePlayButtonProminent(),enterCompactMode:()=>this.handleEnterCompactMode(),exitCompactMode:()=>this.handleExitCompactMode(),triggerPlaylistDismissed:()=>this.handleTriggerPlaylistDismissed(),scheduleDestroy:()=>this.handleScheduleDestroy()})}getVideoUrl(t){var e;const n=null==(e=dt().userData)?void 0:e.language;let i;return i=n&&t.translations&&t.translations[n]?t.translations[n].videoUrl:t.compressedUrl||t.videoUrl,i&&""!==i.trim()||!t.audioUrl||""===t.audioUrl.trim()?i:(t.id,t.audioUrl)}isUsingAudioFallback(t){var e;const n=null==(e=dt().userData)?void 0:e.language;let i;return i=n&&t.translations&&t.translations[n]?t.translations[n].videoUrl:t.compressedUrl||t.videoUrl,!(i&&""!==i.trim()||!t.audioUrl||""===t.audioUrl.trim())}findNextVideoUrl(t){const e=dt();if(!e.manifest||!t)return null;if(t.transitions.length>0){const n=t.transitions[0];if("url-path"===n.type||"dom-click"===n.type)return null;const i=n.nextStep,s=e.manifest.steps.find((t=>t.id===i));if(s)return this.getVideoUrl(s)}const n=e.manifest.steps.findIndex((e=>e.id===t.id));return n>=0&&n<e.manifest.steps.length-1?this.getVideoUrl(e.manifest.steps[n+1]):null}destroy(){this.cursorScheduler.cleanup()}async validateStepUrlRequirement(t){if(!t.urlRequirement)return!0;t.id,this.managers.transitionManager.startStateMachineValidation();try{const e=await async function(t,e=20,n=100){if(!t)return!0;for(let i=0;i<e;i++){if(yt(t))return!0;if(i<e-1&&(await new Promise((t=>setTimeout(t,n))),!window._saltfishPlayer))return!1}return t.pattern,t.matchType,!1}(t.urlRequirement);if(!e){t.id;const e=window._saltfishPlayer;e&&"function"==typeof e.destroy&&e.destroy()}return e}finally{this.managers.transitionManager.endStateMachineValidation()}}async handleStartVideoPlayback(t){if(!t.currentStep)return;const e=t.currentStep;if(e.urlRequirement&&(e.id,!await this.validateStepUrlRequirement(e)))return;this.managers.uiManager.updatePosition(),this.managers.uiManager.showPlayer();const n=this.getVideoUrl(e),i=this.isUsingAudioFallback(e);this.showOrHideAudioOverlay(e,i);try{this.managers.interactionManager.clearButtons(),e.buttons&&this.managers.interactionManager.createButtons(e.buttons);const t=e.buttons&&e.buttons.length>0||e.transitions.some((t=>"dom-click"===t.type||"url-path"===t.type||"dom-element-visible"===t.type));t&&this.managers.transitionManager.setupTransitions(e,!1,!0),this.managers.videoManager.setCompletionPolicy(t?"manual":"auto",(()=>this.handleStepVideoEnded(e,t))),this.managers.videoManager.loadVideo(n).then((()=>this.handleStepVideoLoaded(e,i))).catch((t=>this.handleStepVideoLoadError(t,e)))}catch(t){}}showOrHideAudioOverlay(t,e){if(e){const e=dt().manifest;this.managers.videoManager.showAudioFallbackOverlay(t.gifUrl,null==e?void 0:e.avatarThumbnailUrl)}else this.managers.videoManager.hideAudioFallbackOverlay()}handleStepVideoEnded(t,e){var n;const i=dt();if(!e){const e=t.transitions.find((t=>"timeout"===t.type));return e&&e.timeout&&e.timeout>0?(e.timeout,this.managers.transitionManager.setupTransitions(t,!1)):this.managers.transitionManager.setupTransitions(t,!0),void(t.transitions.some((t=>i.manifest.steps.some((e=>e.id===t.nextStep))))||i.sendStateMachineEvent({type:"COMPLETE_PLAYLIST"}))}const s=t.transitions.find((t=>"timeout"===t.type)),r=null==(n=t.buttons)?void 0:n.some((t=>"goto"===t.action.type||"next"===t.action.type));if(s&&!r){const e=s.timeout||0;s.nextStep,setTimeout((()=>{var e;const n=dt();n.currentStepId!==t.id||"waitingForInteraction"!==n.currentState&&"playing"!==n.currentState?n.currentState:(s.nextStep,null==(e=n.goToStep)||e.call(n,s.nextStep))}),e)}i.sendStateMachineEvent({type:"VIDEO_FINISHED_WAIT",step:t})}handleStepVideoLoaded(t,e){this.managers.uiManager.hideError(),this.loadTranscriptForStep(t),t.cursorAnimations&&t.cursorAnimations.length>0?(t.id,this.managers.cursorManager.setShouldShowCursor(!0),this.cursorScheduler.schedule(t.cursorAnimations[0],t.id)):(t.id,this.managers.cursorManager.setShouldShowCursor(!1)),e?this.managers.videoManager.startAudioVisualization():this.managers.videoManager.initializeAudioForVideo(),this.managers.videoManager.play();const n=this.findNextVideoUrl(t);n&&this.managers.videoManager.preloadNextVideo(n)}handleStepVideoLoadError(t,e){var n;const i=t instanceof Error?t:new Error(`Failed to load video: ${t}`);this.managers.uiManager.showError(i,"video");const s=dt(),r=t;this.managers.eventManager.trigger("error",{timestamp:Date.now(),playlistId:(null==(n=s.manifest)?void 0:n.id)||void 0,stepId:e.id,error:i,errorType:"video",videoUrl:null==r?void 0:r.videoUrl,mediaErrorCode:null==r?void 0:r.mediaErrorCode,mediaErrorMessage:null==r?void 0:r.mediaErrorMessage,failureReason:null==r?void 0:r.failureReason})}loadTranscriptForStep(t){var e,n;const i=dt(),s=(null==(e=i.manifest)?void 0:e.captions)??!0,r=null==(n=i.userData)?void 0:n.language;let a=t.transcript;if(r&&t.translations&&t.translations[r]){const e=t.translations[r].transcript;e&&(a=e,t.id)}a?(t.id,this.managers.videoManager.loadTranscript(a,s)):(t.id,this.managers.videoManager.loadTranscript(null,!0))}handlePauseVideoPlayback(){this.managers.videoManager.pause()}handleStartMutedLoopedVideo(){const t=this.managers.videoManager.getVideoElement();t&&(t.muted=!0,t.loop=!0,t.play().catch((()=>{})))}handleStartIdleModeVideo(t){if(!t.currentStep)return;const e=t.currentStep,n=this.getVideoUrl(e),i=this.isUsingAudioFallback(e);this.managers.uiManager.showPlayer(),this.showOrHideAudioOverlay(e,i),this.managers.videoManager.loadVideo(n).then((()=>{this.managers.uiManager.hideError(),i&&this.managers.videoManager.startAudioVisualization();const t=this.managers.videoManager.getVideoElement();t&&(t.muted=!0,t.loop=!0,t.play().catch((()=>{})))})).catch((t=>{}))}handleTrackPlaylistComplete(){var t,e;const n=dt();if(n.manifest&&this.managers.eventManager){const i=n.manifest.id;if(this.managers.eventManager.trigger("playlistEnded",{timestamp:Date.now(),playlist:{id:i,title:n.manifest.name}}),((null==(t=n.playlistOptions)?void 0:t.persistence)??1)&&n.progress[i]){const t={...n.progress};delete t[i];const s=null==(e=n.user)?void 0:e.id;this.managers.storageManager.setProgress(t,s)}}}handleError(t){var e,n;if(null==(e=t.error)||e.message,t.error&&this.managers.uiManager.getPlayerElement()){this.managers.uiManager.showError(t.error,"player");const e=dt();this.managers.eventManager.trigger("error",{timestamp:Date.now(),playlistId:(null==(n=e.manifest)?void 0:n.id)||void 0,stepId:e.currentStepId||void 0,error:t.error,errorType:"player"})}}handleHideError(){this.managers.uiManager.hideError()}handleShowLoadingState(){this.managers.uiManager.showLoading("Loading...")}handleHideLoadingState(){this.managers.uiManager.hideLoading()}handleHideVideoControls(){this.managers.videoManager.hideProgressBar(),this.managers.videoManager.hideMuteButton()}handleShowVideoControls(){this.managers.videoManager.showProgressBar(),this.managers.videoManager.showMuteButton()}handleShowPlayButton(){this.managers.uiManager.updatePlayPauseButton("paused")}handleHidePlayButton(){this.managers.uiManager.updatePlayPauseButton("playing")}handleEnablePlayButtonProminent(){this.managers.uiManager.enablePlayButtonProminent()}handleDisablePlayButtonProminent(){this.managers.uiManager.disablePlayButtonProminent()}handleEnterCompactMode(){var t,e,n;const i=dt();if(i.manifest&&i.currentStepId===(null==(t=i.manifest.steps[0])?void 0:t.id)&&(null==(e=i.manifest)?void 0:e.compactFirstStep)){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.add("sf-player--compact"),(null==(n=i.manifest)?void 0:n.compactLabel)&&this.managers.uiManager.showCompactLabel(i.manifest.compactLabel)}}handleExitCompactMode(){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.remove("sf-player--compact"),this.managers.uiManager.hideCompactLabel()}handleTriggerPlaylistDismissed(){const t=dt();t.manifest&&this.managers.eventManager&&this.managers.eventManager.trigger("playlistDismissed",{timestamp:Date.now(),playlist:{id:t.manifest.id,title:t.manifest.name}})}handleScheduleDestroy(){setTimeout((()=>{this.destroyCallback&&this.destroyCallback()}),0)}}const It=class t{constructor(t){e(this,"managers"),e(this,"uiUpdaterUnsubscribe",null),e(this,"eventUpdaterUnsubscribe",null),e(this,"cursorScheduler"),e(this,"isInitialized",!1),this.managers=t,this.cursorScheduler=new xt(t,"ManagerOrchestrator")}setInitialized(t){this.isInitialized=t}setupUpdaters(){this.uiUpdaterUnsubscribe&&this.uiUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe&&this.eventUpdaterUnsubscribe();const t=this.managers.uiManager.getPlayerElement();t&&(this.uiUpdaterUnsubscribe=function(t,e){let n=null;const i=()=>{n=t.querySelector(".sf-player__minimize-button")};i();let s={currentState:"",isMinimized:!1,currentStepId:null};function r(t,n){var i;if(!e)return;const s=null==(i=null==n?void 0:n.steps)?void 0:i.find((e=>e.id===t));s&&s.cursorAnimations&&s.cursorAnimations.length>0&&e.setShouldShowCursor(!0)}return ct.subscribe((a=>{var o,l,c,d;n||i(),a.currentState!==s.currentState&&(o=a.currentState,["sf-player--idle","sf-player--loading","sf-player--playing","sf-player--paused","sf-player--waitingForInteraction","sf-player--autoplayBlocked","sf-player--idleMode","sf-player--error","sf-player--completed","sf-player--completedWaitingForInteraction"].forEach((e=>{t.classList.remove(e)})),t.classList.add(`sf-player--${o}`)),a.isMinimized!==s.isMinimized&&(l=a.isMinimized,c=a.currentStepId,d=a.manifest,l?(t.classList.add("sf-player--minimized"),e&&e.setShouldShowCursor(!1)):(t.classList.remove("sf-player--minimized"),r(c,d)),function(t){n&&(n.innerHTML=t?'\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>\n ':'\n <svg width="20" height="20" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>\n </svg>\n ')}(a.isMinimized)),a.currentStepId!==s.currentStepId&&(a.isMinimized||r(a.currentStepId,a.manifest)),s={currentState:a.currentState,isMinimized:a.isMinimized,currentStepId:a.currentStepId}}))}(t,this.managers.cursorManager)),this.eventUpdaterUnsubscribe=function(t){let e=null,n=null,i=null,s=null,r={playlistData:null,stepData:null},a=null;const o=()=>{a&&(clearTimeout(a),a=null),r.playlistData&&t.trigger("playlistStarted",{timestamp:Date.now(),playlist:r.playlistData}),r.stepData&&t.trigger("stepStarted",{timestamp:Date.now(),step:{id:r.stepData.id,title:r.stepData.title},playlist:{id:r.stepData.playlistId,title:r.stepData.playlistTitle}}),r={playlistData:null,stepData:null}};return ct.subscribe((l=>{var c;if(e===l.currentState&&i===l.isMinimized&&s===l.currentStepId)return;const d=e,h=n,u=i,p=s;n=e,e=l.currentState,i=l.isMinimized,s=l.currentStepId;const g={prevPreviousState:h,previousState:d,currentState:l.currentState,currentStepId:l.currentStepId,isMinimized:l.isMinimized};null==(c=l.manifest)||c.id,"playing"===g.previousState&&("autoplayBlocked"===g.currentState||"idleMode"===g.currentState?(a&&(clearTimeout(a),a=null),(r.playlistData||r.stepData)&&(r={playlistData:null,stepData:null})):(r.playlistData||r.stepData)&&o()),"autoplayBlocked"!==g.currentState&&"idleMode"!==g.currentState||"autoplayBlocked"===g.previousState||"idleMode"===g.previousState||l.manifest&&(l.manifest.id,t.trigger("bubbleShown",{timestamp:Date.now(),playlist:{id:l.manifest.id,title:l.manifest.name}})),function(t,e,n,i){const{prevPreviousState:s,previousState:r,currentState:a,currentStepId:o}=t,l="playing"===a&&"paused"===r&&"loading"===s,c="playing"===a&&("autoplayBlocked"===r||"idleMode"===r);if(e.manifest&&o&&o===e.manifest.startStep){if(c)return e.manifest.id,void n.trigger("playlistStarted",{timestamp:Date.now(),playlist:{id:e.manifest.id,title:e.manifest.name}});if(l)return e.manifest.id,void(i.playlistData={id:e.manifest.id,title:e.manifest.name})}"paused"===r&&"playing"===a?n.trigger("playerResumed",{timestamp:Date.now(),previousState:r,currentState:a}):"playing"===r&&"paused"===a&&n.trigger("playerPaused",{timestamp:Date.now(),previousState:r,currentState:a})}(g,l,t,r),function(t,e,n,i){const{previousState:s,currentState:r,isMinimized:a}=t,o=i||!1;!a&&o?n.trigger("playerMaximized",{timestamp:Date.now(),previousState:s,currentState:r}):a&&!o&&n.trigger("playerMinimized",{timestamp:Date.now(),previousState:s,currentState:r})}(g,0,t,u),function(t,e,n,i,s){var r,a,o;const{prevPreviousState:l,previousState:c,currentStepId:d,currentState:h}=t,u=e.currentStepId?((null==(r=e.manifest)?void 0:r.steps)||[]).find((t=>t.id===e.currentStepId)):null;null==u||u.id,null==(a=e.manifest)||a.id,e.manifest;const p=i&&e.manifest&&(i!==d||"waitingForInteraction"===h||"completed"===h);if(e.manifest,p){const t=((null==(o=e.manifest)?void 0:o.steps)||[]).find((t=>t.id===i));null==t||t.id,t&&(t.id,n.trigger("stepEnded",{timestamp:Date.now(),step:{id:t.id,title:t.title||t.id},playlist:{id:e.manifest.id,title:e.manifest.name}}))}const g=d!==i&&"playing"===h,m=("autoplayBlocked"===c||"idleMode"===c)&&"playing"===h&&i===d,f="loading"===l&&"paused"===c&&"playing"===h&&d,y=e.manifest&&d===e.manifest.startStep,v=y&&f,b=!y&&f;null==u||u.id,e.manifest,u&&e.manifest&&(g||m||b?(u.id,n.trigger("stepStarted",{timestamp:Date.now(),step:{id:u.id,title:u.title||u.id},playlist:{id:e.manifest.id,title:e.manifest.name}})):v&&(u.id,s.stepData={id:u.id,title:u.title||u.id,playlistId:e.manifest.id,playlistTitle:e.manifest.name}))}(g,l,t,p,r),function(t,e,n){var i;const{currentState:s,previousState:r}=t;"error"===s&&"error"!==r&&e.error&&n.trigger("error",{timestamp:Date.now(),playlistId:null==(i=e.manifest)?void 0:i.id,stepId:e.currentStepId,error:e.error,errorType:"state"})}(g,l,t),!r.playlistData&&!r.stepData||a||(a&&clearTimeout(a),a=setTimeout((()=>{(r.playlistData||r.stepData)&&o(),a=null}),500))}))}(this.managers.eventManager);const e=ct.subscribe((t=>{this.managers.stepTimeoutManager.update({currentState:t.currentState,currentStepId:t.currentStepId,isMinimized:t.isMinimized,previousState:void 0})})),n=this.eventUpdaterUnsubscribe;this.eventUpdaterUnsubscribe=()=>{n&&n(),e()}}handleStoreChanges(){if(!this.isInitialized)return;const e=dt();if(e.currentState!==t.prevState.currentState||e.currentStepId!==t.prevState.currentStepId||e.isMinimized!==t.prevState.isMinimized){if(t.prevState.currentState,e.currentState,t.prevState.currentStepId,e.currentStepId,t.prevState.isMinimized,e.isMinimized,this.managers.uiManager.getPlayerRoot()&&this.managers.uiManager.getPlayerElement()&&this.managers.uiManager.updatePosition(),this.managers.videoManager.transcriptManager.handleStateChange(e.currentState),"autoplayBlocked"===e.currentState)this.managers.cursorManager.stopAnimation(),this.managers.cursorManager.setShouldShowCursor(!1);else if("playing"===e.currentState&&"autoplayBlocked"===t.prevState.currentState){const t=e.manifest,n=null==t?void 0:t.steps.find((t=>t.id===e.currentStepId));(null==n?void 0:n.cursorAnimations)&&n.cursorAnimations.length>0&&(this.managers.cursorManager.setShouldShowCursor(!0),this.cursorScheduler.schedule(n.cursorAnimations[0],e.currentStepId||"unknown"))}else"completed"!==e.currentState&&"closing"!==e.currentState||this.cleanupPlaylist();e.isMinimized!==t.prevState.isMinimized&&this.managers.uiManager.handleMinimizeStateChange(e.isMinimized),t.prevState={currentState:e.currentState,currentStepId:e.currentStepId,isMinimized:e.isMinimized}}}cleanupCurrentPlaylist(){try{this.cursorScheduler.cleanup(),this.eventUpdaterUnsubscribe&&(this.eventUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe=null),this.managers.stepTimeoutManager&&this.managers.stepTimeoutManager.reset(),this.managers.videoManager&&(this.managers.videoManager.pause(),this.managers.videoManager.reset()),this.managers.cursorManager&&(this.managers.cursorManager.stopAnimation(),this.managers.cursorManager.setShouldShowCursor(!1)),this.managers.transitionManager&&this.managers.transitionManager.cleanupTransitions(),this.managers.interactionManager&&this.managers.interactionManager.clearButtons(),this.managers.uiManager.reset()}catch(t){pt.handleCleanupError(t,{component:"ManagerOrchestrator",method:"cleanupCurrentPlaylist"})}}cleanupPlaylist(){var t;if(this.isInitialized)try{const e=dt();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,this.uiUpdaterUnsubscribe&&(this.uiUpdaterUnsubscribe(),this.uiUpdaterUnsubscribe=null),this.managers.transitionManager.reset(),this.managers.videoManager.destroy(),this.managers.cursorManager.destroy(),this.managers.interactionManager.destroy(),this.managers.playlistManager.destroy(),this.managers.stepTimeoutManager.destroy(),this.managers.uiManager.destroy()}catch(t){pt.handleCleanupError(t,{component:"ManagerOrchestrator",method:"cleanupPlaylist"})}else console.warn("Saltfish playlist Player is not initialized")}destroyAll(){var t;if(this.isInitialized)try{const e=dt();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,this.cursorScheduler.cleanup(),this.uiUpdaterUnsubscribe&&(this.uiUpdaterUnsubscribe(),this.uiUpdaterUnsubscribe=null),this.eventUpdaterUnsubscribe&&(this.eventUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe=null),this.managers.transitionManager.destroy(),this.managers.triggerManager.destroy(),this.managers.videoManager.destroy(),this.managers.cursorManager.destroy(),this.managers.interactionManager.destroy(),this.managers.analyticsManager.destroy(),this.managers.sessionManager.destroy(),this.managers.playlistManager.destroy(),this.managers.stepTimeoutManager.destroy(),this.managers.uiManager.destroy(),this.isInitialized=!1,e.reset()}catch(t){pt.handleCleanupError(t,{component:"ManagerOrchestrator",method:"destroyAll"});try{this.isInitialized=!1,dt().reset()}catch(e){pt.handleCleanupError(e,{component:"ManagerOrchestrator",method:"destroyAll",additionalData:{originalError:t}})}}else console.warn("Saltfish playlist Player is not initialized")}getManagers(){return this.managers}destroy(){this.destroyAll()}};e(It,"prevState",{currentState:"idle",currentStepId:null,isMinimized:!1});let Pt=It;class Ct{constructor(){e(this,"container",null),e(this,"shadowRoot",null),e(this,"styleElement",null)}create(){if(this.container)return;this.container=document.createElement("div"),this.container.id="saltfish-container",this.container.appendChild(document.createTextNode("​")),document.body.appendChild(this.container),this.shadowRoot=this.container.attachShadow({mode:"open"});try{const t=new CSSStyleSheet;t.replaceSync(this.getBaseStyles()),this.shadowRoot.adoptedStyleSheets=[t]}catch(t){this.styleElement=document.createElement("style"),this.styleElement.textContent=this.getBaseStyles(),this.shadowRoot.appendChild(this.styleElement)}const t=document.createElement("div");t.id="sf-player-root",this.shadowRoot.appendChild(t)}getShadowRoot(){return this.shadowRoot}getRootElement(){return this.shadowRoot?this.shadowRoot.getElementById("sf-player-root"):null}addStyles(t){if(this.shadowRoot){if(this.shadowRoot.adoptedStyleSheets&&this.shadowRoot.adoptedStyleSheets.length>0)try{const e=this.shadowRoot.adoptedStyleSheets[0],n=Array.from(e.cssRules).map((t=>t.cssText)).join("\n");return void e.replaceSync(n+"\n"+t)}catch(t){console.warn("ShadowDOMManager: Failed to append to adoptedStyleSheet:",t)}this.styleElement&&(this.styleElement.textContent+=t)}}remove(){this.container&&(document.body.removeChild(this.container),this.container=null,this.shadowRoot=null,this.styleElement=null)}getBaseStyles(){return"\n /* \n * CSS Reset for the Saltfish playlist Player\n * Minimal reset for the Shadow DOM to ensure consistent rendering\n */\n\n:host {\n all: initial;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n box-sizing: border-box;\n}\n\n:host *,\n:host *::before,\n:host *::after {\n box-sizing: inherit;\n margin: 0;\n padding: 0;\n}\n\nbutton {\n background: none;\n border: none;\n cursor: pointer;\n font: inherit;\n outline: none;\n padding: 0;\n}\n\n/* Utility classes for CSP-compliant styling */\n.sf-hidden {\n display: none !important;\n} \n /* \n * Variables for the Saltfish playlist Player\n * Defines all design tokens used throughout the application\n */\n\n:host {\n /* Colors */\n --sf-primary-color: #4a9bff;\n --sf-secondary-color: #6ccfff;\n --sf-background-color: #1e1e1e;\n --sf-text-color: #ffffff;\n --sf-button-bg: rgba(0, 0, 0, 0.5);\n --sf-button-hover-bg: rgba(0, 0, 0, 0.7);\n --sf-overlay-gradient: linear-gradient(180deg, rgba(0, 0, 0, 0.7) 0%, transparent 30%, transparent 70%, rgba(0, 0, 0, 0.7) 100%);\n --sf-progress-gradient: linear-gradient(90deg, var(--sf-primary-color), var(--sf-secondary-color));\n --sf-error-color: #ff4d4d;\n --sf-error-bg: rgba(255, 77, 77, 0.1);\n \n /* Spacing */\n --sf-spacing-xs: 4px;\n --sf-spacing-sm: 8px;\n --sf-spacing-md: 12px;\n --sf-spacing-lg: 16px;\n --sf-spacing-xl: 24px;\n \n /* Sizes */\n --sf-player-width: 240px;\n --sf-player-height: 336px;\n --sf-player-min-width: 80px;\n --sf-player-min-height: 80px;\n --sf-player-compact-width: 120px;\n --sf-player-compact-height: 120px;\n --sf-control-button-size: 24px;\n --sf-play-button-size: 60px;\n --sf-play-button-compact-size: 44px;\n --sf-minimize-button-size: 34px;\n --sf-mute-button-size: 32px;\n --sf-cc-button-size: 32px;\n --sf-cursor-size: 32px;\n \n /* Border radius */\n --sf-border-radius-sm: 4px;\n --sf-border-radius-md: 8px;\n --sf-border-radius-lg: 16px;\n --sf-border-radius-circle: 50%;\n \n /* Transitions */\n --sf-transition-fast: 0.1s ease;\n --sf-transition-normal: 0.2s ease;\n --sf-transition-slow: 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n \n /* Shadows */\n --sf-shadow-small: 0 2px 5px rgba(0, 0, 0, 0.2);\n --sf-shadow-medium: 0 4px 8px rgba(0, 0, 0, 0.15);\n --sf-shadow-large: 0 10px 25px rgba(0, 0, 0, 0.2);\n \n /* Z-index layering */\n --sf-z-index-base: 1;\n --sf-z-index-overlay: 2;\n --sf-z-index-controls: 10;\n --sf-z-index-cursor: 9999;\n --sf-z-index-player: 2147483648;\n \n /* Font sizes */\n --sf-font-size-sm: 14px;\n --sf-font-size-md: 16px;\n --sf-font-size-lg: 18px;\n --sf-font-size-xl: 24px;\n} \n\n/* Mobile device responsive adjustments - make player smaller for mobile screens */\n@media (max-width: 768px) {\n :host {\n /* Reduce player size on mobile for better space utilization */\n --sf-player-width: 180px; /* 25% smaller than desktop (240px -> 180px) */\n --sf-player-height: 252px; /* 25% smaller than desktop (336px -> 252px) */\n --sf-player-min-width: 60px; /* Smaller when minimized (80px -> 60px) */\n --sf-player-min-height: 60px; /* Smaller when minimized (80px -> 60px) */\n --sf-player-compact-width: 90px; /* Smaller compact mode for mobile (120px -> 90px) */\n --sf-player-compact-height: 90px; /* Smaller compact mode for mobile (120px -> 90px) */\n\n /* Keep controls touch-friendly despite smaller player size */\n --sf-play-button-size: 44px; /* Smaller but still touch-friendly (60px -> 44px) */\n --sf-play-button-compact-size: 36px; /* Touch-friendly compact play button */\n --sf-control-button-size: 28px; /* Keep larger for touch targets (24px -> 28px) */\n --sf-mute-button-size: 26px; /* Smaller for mobile (32px -> 26px) */\n --sf-cc-button-size: 26px; /* Smaller for mobile (32px -> 26px) */\n --sf-minimize-button-size: 26px; /* Match other mobile button sizes */\n }\n}\n\n/* Touch device specific adjustments (tablets and larger touch devices, excluding mobile) */\n@media (pointer: coarse) and (min-width: 769px) {\n :host {\n /* Ensure touch-friendly sizes even on larger touch devices */\n --sf-control-button-size: 28px;\n --sf-mute-button-size: 38px;\n --sf-cc-button-size: 38px;\n --sf-minimize-button-size: 38px; /* Match other touch device button sizes */\n }\n} \n\n /* \n * Player component styles for the Saltfish playlist Player\n * Following BEM naming convention\n */\n\n/* Main player container */\n.sf-player {\n border-radius: var(--sf-border-radius-md);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15), 0 5px 15px rgba(0, 0, 0, 0.08);\n position: relative;\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n opacity: 0;\n /* Smooth transitions for size changes and opacity */\n transition: opacity 0.3s ease-in-out,\n width 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),\n height 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),\n border-radius 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n/* Player visible state - show with fade in */\n.sf-player--visible {\n opacity: 1;\n}\n\n/* Gradient overlay now moved to video container - see _video.css */\n\n/* Full-size player state */\n.sf-player:not(.sf-player--minimized) {\n width: var(--sf-player-width);\n height: var(--sf-player-height);\n}\n\n/* Autoplay fallback state - ensure play button is visible */\n.sf-player--waiting-for-user-interaction .sf-controls-container__play-button {\n display: flex !important;\n opacity: 1 !important;\n visibility: visible !important;\n}\n\n/* Also show the center play button in autoplay fallback state */\n.sf-player--waiting-for-user-interaction .sf-player__center-play-button {\n display: flex !important;\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 20) !important; /* Higher z-index to appear above overlay */\n}\n\n/* Make the autoplay fallback state more prominent to indicate need for interaction */\n.sf-player--waiting-for-user-interaction::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n}\n\n/* Player state: minimized */\n.sf-player--minimized {\n /* Equal width and height are essential for maintaining a perfect circle when using border-radius: 50% */\n width: var(--sf-player-min-width);\n height: var(--sf-player-min-height);\n border-radius: var(--sf-border-radius-circle);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.20), 0 5px 15px rgba(0, 0, 0, 0.12);\n cursor: pointer;\n /* Force overriding any inline styles that might be applied */\n max-width: var(--sf-player-min-width) !important;\n max-height: var(--sf-player-min-height) !important;\n min-width: var(--sf-player-min-width) !important;\n min-height: var(--sf-player-min-height) !important;\n}\n\n/* Player state: compact (first step, small rounded) */\n.sf-player--compact {\n width: var(--sf-player-compact-width) !important;\n height: var(--sf-player-compact-height) !important;\n border-radius: var(--sf-border-radius-circle);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.20), 0 5px 15px rgba(0, 0, 0, 0.12);\n cursor: pointer; /* Whole bubble is clickable */\n /* Force overriding any inline styles that might be applied */\n max-width: var(--sf-player-compact-width) !important;\n max-height: var(--sf-player-compact-height) !important;\n min-width: var(--sf-player-compact-width) !important;\n min-height: var(--sf-player-compact-height) !important;\n}\n\n/* Hide center play button in compact mode - the whole bubble is clickable */\n.sf-player--compact .sf-player__center-play-button {\n display: none !important;\n}\n\n/* Hide elements in compact mode */\n.sf-player--compact .sf-player__logo,\n.sf-player--compact .sf-player__bottom-bar,\n.sf-player--compact .sf-player__minimize-button {\n display: none;\n}\n\n/* Compact bubble still shows AI-generated footage, so keep a small AI badge.\n The whole bubble is clickable, so the badge must not intercept pointer\n events (no hover label). */\n.sf-player--compact .sf-player__ai-badge {\n /* Offsets keep the badge fully inside the circular bubble (also at the\n 90px mobile size) */\n right: 16px;\n bottom: 16px;\n height: 16px;\n pointer-events: none;\n}\n\n.sf-player--compact .sf-player__ai-badge svg {\n width: 12px;\n height: 12px;\n}\n\n/* Hide gradient overlay when in compact mode - see _video.css */\n.sf-player--compact .sf-video-container::after {\n display: none;\n}\n\n/* Hide controls when minimized */\n.sf-player--minimized .sf-controls-container {\n display: none;\n}\n\n/* Hide controls when in compact mode */\n.sf-player--compact .sf-controls-container {\n display: none;\n}\n\n/* Only show the minimize button when hovering on minimized player */\n.sf-player--minimized .sf-player__minimize-button {\n opacity: 0;\n}\n\n.sf-player--minimized:hover .sf-player__minimize-button {\n opacity: 1;\n}\n\n/* Player root element */\n#sf-player-root {\n position: fixed;\n z-index: var(--sf-z-index-player);\n}\n\n/* Fixed positioning classes */\n.sf-player-root--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.sf-player-root--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n/* Player error message */\n.sf-player__error {\n padding: var(--sf-spacing-md);\n color: var(--sf-error-color);\n background-color: var(--sf-error-bg);\n border-radius: var(--sf-border-radius-md);\n margin: var(--sf-spacing-sm);\n font-size: var(--sf-font-size-sm);\n border-left: 4px solid var(--sf-error-color);\n}\n\n/* Minimize button */\n.sf-player__minimize-button {\n position: absolute;\n top: 8px;\n right: 4px;\n width: var(--sf-minimize-button-size);\n height: var(--sf-minimize-button-size);\n background: none !important;\n border-radius: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: calc(var(--sf-font-size-sm) + 4px);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n opacity: 0;\n}\n\n/* Minimize button background circle */\n.sf-player__minimize-button::before {\n content: '';\n position: absolute;\n width: 80%;\n height: 80%;\n background-color: rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n z-index: -1;\n transition: all var(--sf-transition-normal);\n}\n\n/* Minimize button hover state */\n.sf-player__minimize-button:hover {\n transform: scale(1.1);\n}\n\n/* Show minimize button on player hover */\n.sf-player:hover .sf-player__minimize-button {\n opacity: 1;\n}\n\n/* Mobile and touch device overrides for minimize button visibility */\n/* Ensure minimize button is always visible on touch devices, even when minimized */\n@media (pointer: coarse) {\n .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for touch devices */\n }\n \n .sf-player--minimized .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for touch devices */\n }\n}\n\n/* Ensure minimize button is always visible on mobile screens under 768px */\n@media (max-width: 768px) {\n .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for mobile */\n /* Position closer to top right corner on mobile */\n top: var(--sf-spacing-xs) !important; /* 4px from top instead of 16px */\n right: var(--sf-spacing-xs) !important; /* 4px from right instead of 12px */\n }\n \n .sf-player--minimized .sf-player__minimize-button {\n opacity: 1 !important;\n z-index: calc(var(--sf-z-index-controls) + 50) !important; /* Much higher z-index for mobile */\n /* Position closer to top right corner on mobile */\n top: var(--sf-spacing-xs) !important; /* 4px from top instead of 16px */\n right: var(--sf-spacing-xs) !important; /* 4px from right instead of 12px */\n }\n}\n\n/* Player title */\n.sf-player__title {\n position: absolute;\n top: var(--sf-spacing-md);\n left: var(--sf-spacing-md);\n color: var(--sf-text-color);\n font-size: var(--sf-font-size-md);\n font-weight: 600;\n z-index: var(--sf-z-index-controls);\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n max-width: 70%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Centered play/pause button overlay */\n.sf-player__center-play-button {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: var(--sf-play-button-size);\n height: var(--sf-play-button-size);\n background-color: rgba(0, 0, 0, 0.5);\n border-radius: var(--sf-border-radius-circle);\n display: none; /* Hidden by default */\n justify-content: center;\n align-items: center;\n z-index: calc(var(--sf-z-index-controls) + 10); /* Ensure higher z-index than other elements */\n color: white;\n border: none;\n font-size: var(--sf-control-button-size);\n cursor: pointer;\n transition: transform var(--sf-transition-normal), background-color var(--sf-transition-normal), opacity var(--sf-transition-normal);\n backdrop-filter: blur(1px);\n -webkit-backdrop-filter: blur(1px);\n pointer-events: auto; /* Enable pointer events to capture clicks */\n}\n\n/* Icon visibility control - use opacity for smooth transitions */\n.sf-player__center-play-button__pause-icon,\n.sf-player__center-play-button__play-icon {\n position: absolute;\n transition: opacity var(--sf-transition-normal);\n}\n\n.sf-player__center-play-button__pause-icon {\n opacity: 0;\n}\n\n.sf-player__center-play-button__play-icon {\n opacity: 1;\n}\n\n/* When playing, make button hoverable but invisible (desktop only) */\n@media (hover: hover) and (pointer: fine) {\n .sf-player--playing .sf-player__center-play-button {\n display: flex;\n opacity: 0;\n pointer-events: auto;\n }\n\n /* Show pause icon on hover when playing */\n .sf-player--playing .sf-player__center-play-button:hover {\n opacity: 1;\n }\n\n .sf-player--playing .sf-player__center-play-button:hover .sf-player__center-play-button__play-icon {\n opacity: 0;\n transition: none; /* Instant switch when hovering during playback */\n }\n\n .sf-player--playing .sf-player__center-play-button:hover .sf-player__center-play-button__pause-icon {\n opacity: 1;\n transition: none; /* Instant switch when hovering during playback */\n }\n\n /* Delay icon switch when not hovering during playback so pause icon stays visible during fade-out */\n .sf-player--playing .sf-player__center-play-button .sf-player__center-play-button__play-icon,\n .sf-player--playing .sf-player__center-play-button .sf-player__center-play-button__pause-icon {\n transition: opacity 0s 0.2s; /* Instant transition but delayed by button fade duration */\n }\n}\n\n/* Replay icon hidden by default */\n.sf-player__center-play-button__replay-icon {\n opacity: 0;\n position: absolute;\n transition: opacity var(--sf-transition-normal);\n}\n\n/* Show replay icon when video completed or waiting for interaction */\n.sf-player--completedWaitingForInteraction .sf-player__center-play-button__replay-icon,\n.sf-player--waitingForInteraction .sf-player__center-play-button__replay-icon {\n opacity: 1;\n transition: none;\n}\n\n/* Hide play/pause icons when showing replay */\n.sf-player--completedWaitingForInteraction .sf-player__center-play-button__play-icon,\n.sf-player--completedWaitingForInteraction .sf-player__center-play-button__pause-icon,\n.sf-player--waitingForInteraction .sf-player__center-play-button__play-icon,\n.sf-player--waitingForInteraction .sf-player__center-play-button__pause-icon {\n opacity: 0;\n transition: none;\n}\n\n/* Center play button visible state */\n.sf-player__center-play-button--visible {\n display: flex !important;\n}\n\n/* Center play button prominent state (for autoplay blocked, idle mode) */\n.sf-player__center-play-button--prominent {\n opacity: 1 !important;\n pointer-events: auto !important;\n}\n\n/* Center play button hover state */\n.sf-player__center-play-button:hover {\n transform: translate(-50%, -50%) scale(1.1);\n}\n\n/* Hide center play button in minimized state */\n.sf-player--minimized .sf-player__center-play-button {\n display: none !important;\n}\n\n/* Center play button with dynamic positioning when buttons are present */\n/* Positions button centered between top of player and top of first button */\n.sf-player__center-play-button--with-buttons {\n /* Available space above buttons = playerHeight - bottomSpacing - buttonContainerHeight */\n /* Center point = availableSpace / 2 */\n top: calc((var(--sf-player-height) - var(--sf-spacing-xl) - var(--sf-button-container-height, 0px)) / 2) !important;\n transform: translate(-50%, -50%) !important;\n}\n\n/* Maintain scale on hover for buttons with dynamic positioning */\n.sf-player__center-play-button--with-buttons:hover {\n transform: translate(-50%, -50%) scale(1.1) !important;\n}\n\n/* Exit button for minimized mode */\n.sf-player__exit-button {\n position: absolute;\n top: -22px; /* Position it above the player */\n right: 0;\n width: 22px;\n height: 22px;\n background-color: rgba(0, 0, 0, 0.5);\n border-radius: var(--sf-border-radius-circle);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: var(--sf-font-size-md);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n}\n\n.sf-player__exit-button svg {\n width: 18px;\n height: 18px;\n}\n\n/* Exit button hover state */\n.sf-player__exit-button:hover {\n transform: scale(1.1);\n background-color: rgba(0, 0, 0, 0.7);\n}\n\n/* Show exit button on minimized player hover */\n.sf-player--minimized:hover .sf-player__exit-button {\n opacity: 1;\n}\n\n/* Bottom bar behind the Saltfish logo - keeps it legible on bright videos.\n Only rendered when the logo is shown (showLogo entitlement). */\n.sf-player__bottom-bar {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 32px;\n /* Soft fade with no hard top edge - stacks on the video's bottom\n gradient (0.6 black at the bottom edge), so the white logo stays\n legible without the strip reading as a solid bar */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.45) 0%, rgba(0, 0, 0, 0) 100%);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n pointer-events: none;\n z-index: var(--sf-z-index-controls);\n}\n\n/* Saltfish logo */\n.sf-player__logo {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 26px;\n z-index: var(--sf-z-index-controls);\n opacity: 0.9;\n transition: opacity var(--sf-transition-normal);\n cursor: pointer;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.sf-player__logo svg {\n width: 55px;\n height: 13px;\n}\n\n/* Logo hover state */\n.sf-player:hover .sf-player__logo {\n opacity: 1;\n}\n\n/* AI transparency badge (EU AI Act disclosure) - always visible, even for\n whitelabel clients that hide the Saltfish logo */\n.sf-player__ai-badge {\n position: absolute;\n bottom: 0;\n right: var(--sf-spacing-sm);\n height: 26px;\n display: flex;\n align-items: center;\n z-index: var(--sf-z-index-controls);\n opacity: 0.9;\n cursor: default;\n}\n\n.sf-player__ai-badge:hover {\n opacity: 1;\n}\n\n.sf-player__ai-badge svg {\n width: 16px;\n height: 16px;\n display: block;\n /* Self-contained contrast so the white badge stays visible on bright\n footage, including modes that hide the bottom gradient */\n filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.35));\n}\n\n/* Disclosure text shown when hovering the AI badge */\n.sf-player__ai-badge-label {\n position: absolute;\n bottom: calc(100% + var(--sf-spacing-xs));\n right: 0;\n padding: 4px 8px;\n background: rgba(0, 0, 0, 0.8);\n color: #ffffff;\n font-size: 11px;\n line-height: 1.2;\n border-radius: var(--sf-border-radius-sm);\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: opacity var(--sf-transition-normal);\n pointer-events: none;\n}\n\n/* Hover only on devices that support it - on touch, tapping applies a\n sticky :hover that would keep the label stuck open */\n@media (hover: hover) {\n .sf-player__ai-badge:hover .sf-player__ai-badge-label {\n opacity: 1;\n visibility: visible;\n }\n}\n\n.sf-player__ai-badge-label--visible {\n opacity: 1;\n visibility: visible;\n}\n\n/* Hide logo and bottom bar when minimized; keep a small AI badge on the\n bubble since the avatar is still visible. The whole bubble is clickable,\n so the badge must not intercept pointer events (no hover label). */\n.sf-player--minimized .sf-player__logo,\n.sf-player--minimized .sf-player__bottom-bar {\n display: none;\n}\n\n.sf-player--minimized .sf-player__ai-badge {\n /* Offsets keep the badge fully inside the circular bubble (also at the\n 60px mobile size) */\n right: 11px;\n bottom: 11px;\n height: 10px;\n pointer-events: none;\n}\n\n.sf-player--minimized .sf-player__ai-badge svg {\n width: 10px;\n height: 10px;\n}\n /* \n * Video component styles for the Saltfish playlist Player\n * Following BEM naming convention\n */\n\n/* Video container */\n.sf-video-container {\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: var(--sf-border-radius-md);\n overflow: hidden;\n pointer-events: auto; /* Ensure clicks on video container are captured */\n background-color: #000; /* Fallback background for audio-only mode */\n /* Force clean border-radius clipping */\n isolation: isolate;\n transform: translateZ(0);\n -webkit-mask-image: -webkit-radial-gradient(white, black);\n /* Ensure video container and its children (including captions) sit above the gradient overlay */\n z-index: 3;\n /* Smooth transition for border-radius changes */\n transition: border-radius var(--sf-transition-slow);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-lg) var(--sf-border-radius-lg);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-lg) var(--sf-border-radius-lg);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Dark gradient overlay at bottom of video - ensures captions are visible above it */\n.sf-video-container::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of container height */\n background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);\n pointer-events: none;\n z-index: var(--sf-z-index-overlay);\n border-radius: 0 0 var(--sf-border-radius-md) var(--sf-border-radius-md);\n}\n\n/* Audio fallback poster image */\n.sf-video-container--audio-fallback {\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n background-image: var(--sf-audio-poster-url, none);\n}\n\n/* Audio fallback overlay */\n.sf-audio-fallback-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.6);\n z-index: 2;\n pointer-events: none;\n}\n\n/* Avatar mode overlay - no background, just container */\n.sf-audio-fallback-overlay--avatar {\n background: none;\n}\n\n.sf-audio-fallback-overlay__icon {\n width: 60px;\n height: 60px;\n margin-bottom: 16px;\n color: white;\n opacity: 0.9;\n}\n\n.sf-audio-fallback-overlay__text {\n color: white;\n font-size: 14px;\n text-align: center;\n padding: 0 20px;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\n opacity: 0.9;\n}\n\n.sf-audio-fallback-overlay__avatar {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 1;\n}\n\n/* Semi-transparent overlay on top of avatar */\n.sf-audio-fallback-overlay__dim {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.3);\n z-index: 2;\n}\n\n/* Soundbar-only mode overlay - dark background for soundbar visibility */\n.sf-audio-fallback-overlay--soundbar-only {\n background: rgba(0, 0, 0, 0.85);\n}\n\n/* Audio visualization soundbar container */\n.sf-audio-soundbar {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n height: 120px;\n width: auto;\n max-width: 300px;\n z-index: 3;\n position: relative;\n padding: 0 20px;\n}\n\n/* Individual soundbar frequency bar */\n.sf-audio-soundbar__bar {\n flex: 1;\n min-width: 8px;\n max-width: 20px;\n height: var(--sf-bar-height, 10%);\n background-color: var(--sf-bar-color, hsla(180, 70%, 60%, 0.3));\n border-radius: 4px;\n transition: height 0.05s ease-out, background-color 0.1s ease-out;\n transform-origin: center;\n will-change: height, background-color;\n}\n\n/* Video element */\n.sf-video-container__video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n background-color: white;\n /* Ensure video is visible on mobile */\n display: block;\n /* Add explicit positioning to ensure video is visible */\n position: relative;\n z-index: 1;\n /* Remove any border-radius - let container's overflow: hidden do the clipping */\n border-radius: 0;\n /* Force GPU acceleration for cleaner clipping with scale effect */\n transform: scale(1.04) translateZ(0);\n backface-visibility: hidden;\n transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n/* Video blur effect (for end-of-video transitions) */\n.sf-video-container__video--blurred {\n filter: blur(3px);\n transform: scale(1.04) translateZ(0);\n transition: filter 0.3s ease-out, transform 0.3s ease-out;\n}\n\n\n\n/* Mobile-specific video styles */\n@media (max-width: 768px) {\n\n .sf-video-container__video {\n /* Force video dimensions on mobile */\n width: 100% !important;\n height: 100% !important;\n object-fit: cover !important;\n /* Prevent video from being hidden */\n opacity: 1 !important;\n visibility: visible !important;\n position: relative !important;\n }\n \n /* Make controls more touch-friendly on mobile */\n .sf-video-container__controls {\n height: 5px; /* Thicker on mobile for easier touch */\n }\n \n /* Adjust pseudo-element for mobile touch target */\n .sf-video-container__controls::before {\n height: 14px; /* Larger touch target on mobile */\n }\n \n .sf-video-container__mute-button {\n /* Use CSS variable for consistent sizing */\n min-width: var(--sf-mute-button-size) !important;\n min-height: var(--sf-mute-button-size) !important;\n opacity: 1; /* Always visible on mobile (no hover) */\n }\n \n .sf-video-container__cc-button {\n /* Use CSS variable for consistent sizing */\n min-width: var(--sf-cc-button-size) !important;\n min-height: var(--sf-cc-button-size) !important;\n opacity: 1; /* Always visible on mobile (no hover) */\n }\n}\n\n/* Touch device specific styles */\n@media (pointer: coarse) {\n .sf-video-container__controls:hover {\n height: 5px; /* Keep consistent height on touch devices */\n }\n \n /* Maintain consistent clickable area on touch devices */\n .sf-video-container__controls::before,\n .sf-video-container__controls:hover::before {\n height: 14px; /* Consistent touch target */\n }\n \n .sf-video-container__mute-button {\n opacity: 1; /* Always show on touch devices */\n }\n \n .sf-video-container__cc-button {\n opacity: 1; /* Always show on touch devices */\n }\n \n .sf-video-container:hover .sf-video-container__mute-button {\n opacity: 1;\n }\n}\n\n/* Video in minimized state */\n.sf-player--minimized .sf-video-container {\n border-radius: var(--sf-border-radius-circle);\n cursor: pointer;\n z-index: var(--sf-z-index-base);\n width: 100%;\n height: 100%;\n /* Ensure clean clipping in circular state */\n isolation: isolate;\n transform: translateZ(0);\n}\n\n/* Hide gradient overlay when minimized */\n.sf-player--minimized .sf-video-container::after {\n display: none;\n}\n\n.sf-player--minimized .sf-video-container__video {\n border-radius: 0; /* Let container handle clipping */\n object-fit: cover;\n width: 100%;\n height: 100%;\n transform: scale(1.2) translateZ(0);\n}\n\n/* Hide progress bar in minimized state */\n.sf-player--minimized .sf-video-container__controls {\n display: none !important;\n}\n\n/* Also hide mute button in minimized state */\n.sf-player--minimized .sf-video-container__mute-button {\n display: none !important;\n}\n\n/* Also hide CC button in minimized state */\n.sf-player--minimized .sf-video-container__cc-button {\n display: none !important;\n}\n\n/* Progress bar container */\n.sf-video-container__controls {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n width: 100%;\n height: 4px;\n background-color: rgba(255, 255, 255, 0.3);\n z-index: var(--sf-z-index-controls);\n /* Match the container's top border-radius for seamless integration */\n border-radius: var(--sf-border-radius-md) var(--sf-border-radius-md) 0 0;\n cursor: pointer;\n /* Ensure pixel-perfect alignment and edge-to-edge coverage */\n transform: translateZ(0);\n backface-visibility: hidden;\n /* Smooth transition for height change on hover */\n transition: height 0.15s ease-in-out, background-color 0.15s ease-in-out;\n /* Ensure it covers the full width */\n margin: 0;\n box-sizing: border-box;\n}\n\n/* Invisible pseudo-element to extend clickable area downward */\n.sf-video-container__controls::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 10px; /* Visual height (4px) + extended clickable area (6px) */\n cursor: pointer;\n}\n\n/* Show slightly thicker progress bar on hover for better UX */\n.sf-video-container__controls:hover {\n height: 6px;\n background-color: rgba(255, 255, 255, 0.35);\n}\n\n/* Extend pseudo-element when progress bar grows on hover */\n.sf-video-container__controls:hover::before {\n height: 12px; /* Visual height (6px) + extended clickable area (6px) */\n}\n\n/* Progress indicator */\n.sf-video-container__progress {\n height: 100%;\n background: linear-gradient(90deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.85) 100%);\n width: var(--sf-progress-width, 0%);\n transition: var(--sf-progress-transition, width 0.1s linear);\n /* Only apply top-left border-radius to maintain seamless look */\n border-radius: var(--sf-border-radius-md) 0 0 0;\n cursor: pointer;\n transform-origin: left;\n /* Ensure smooth rendering */\n will-change: width;\n}\n\n/* Mute button */\n.sf-video-container__mute-button {\n position: absolute;\n top: calc(8px + var(--sf-minimize-button-size) + 6px);\n right: 4px;\n width: var(--sf-mute-button-size);\n height: var(--sf-mute-button-size);\n background: none !important;\n border-radius: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: calc(var(--sf-font-size-md) + 2px);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n opacity: 0;\n}\n\n/* Mute button background circle */\n.sf-video-container__mute-button::before {\n content: '';\n position: absolute;\n width: 80%;\n height: 80%;\n background-color: rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n z-index: -1;\n transition: all var(--sf-transition-normal);\n}\n\n/* Mute button hover state */\n.sf-video-container__mute-button:hover {\n transform: scale(1.1);\n}\n\n/* Show mute button on container hover */\n.sf-video-container:hover .sf-video-container__mute-button {\n opacity: 1;\n}\n\n/* CC button */\n.sf-video-container__cc-button {\n position: absolute;\n top: calc(8px + var(--sf-minimize-button-size) + 6px + var(--sf-mute-button-size) + 6px);\n right: 4px;\n width: var(--sf-cc-button-size);\n height: var(--sf-cc-button-size);\n background: none !important;\n border-radius: 0;\n padding: 0; /* Remove default button padding */\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: var(--sf-z-index-controls);\n color: white;\n border: none;\n font-size: calc(var(--sf-font-size-md) + 2px);\n transition: all var(--sf-transition-normal);\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n opacity: 0;\n}\n\n/* CC button background circle */\n.sf-video-container__cc-button::before {\n content: '';\n position: absolute;\n width: 80%;\n height: 80%;\n background-color: rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n z-index: -1;\n transition: all var(--sf-transition-normal);\n}\n\n.sf-video-container__cc-button svg {\n display: block;\n margin: auto;\n width: 60%;\n height: 60%;\n}\n\n/* CC button hover state */\n.sf-video-container__cc-button:hover {\n transform: scale(1.1);\n}\n\n/* Compact mode styling - circular border-radius for video container */\n.sf-player--compact .sf-video-container {\n border-radius: var(--sf-border-radius-circle);\n}\n\n/* Hide gradient overlay in compact mode (already handled in _player.css but kept for clarity) */\n.sf-player--compact .sf-video-container::after {\n display: none;\n}\n\n/* Hide mute and cc buttons in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-video-container__mute-button,\n.sf-player--autoplayBlocked .sf-video-container__cc-button,\n.sf-player--idleMode .sf-video-container__mute-button,\n.sf-player--idleMode .sf-video-container__cc-button {\n display: none !important;\n}\n\n/* Show mute and cc buttons on hover in playing/paused states */\n.sf-player--playing .sf-video-container:hover .sf-video-container__mute-button,\n.sf-player--playing .sf-video-container:hover .sf-video-container__cc-button,\n.sf-player--paused .sf-video-container:hover .sf-video-container__mute-button,\n.sf-player--paused .sf-video-container:hover .sf-video-container__cc-button {\n opacity: 1;\n} \n /* \n * Controls component styles for the Saltfish playlist Player\n * Following BEM naming convention\n */\n\n/* Main controls container */\n.sf-controls-container {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: transparent;\n z-index: var(--sf-z-index-controls);\n pointer-events: auto;\n}\n\n/* Play button */\n.sf-controls-container__play-button {\n background-color: rgba(0, 0, 0, 0.6);\n border: none;\n color: var(--sf-text-color);\n font-size: var(--sf-control-button-size);\n cursor: pointer;\n width: var(--sf-play-button-size);\n height: var(--sf-play-button-size);\n border-radius: var(--sf-border-radius-circle);\n display: flex;\n justify-content: center;\n align-items: center;\n transition: transform var(--sf-transition-normal), background-color var(--sf-transition-normal);\n padding-left: 4px; /* Optical centering for play icon */\n}\n\n/* Button hover state */\n.sf-controls-container__play-button:hover {\n background-color: rgba(0, 0, 0, 0.4);\n transform: scale(1.1);\n}\n\n/* Button container for interactive buttons */\n.sf-controls-container__buttons {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: var(--sf-spacing-md);\n}\n\n/* Interactive button */\n.sf-controls-container__interactive-button {\n background-color: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: white;\n border: none;\n border-radius: var(--sf-border-radius-md);\n padding: var(--sf-spacing-xs) var(--sf-spacing-md);\n font-size: var(--sf-font-size-sm);\n cursor: pointer;\n transition: background-color var(--sf-transition-normal), transform var(--sf-transition-fast);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n\n.sf-controls-container__interactive-button:hover {\n background-color: rgba(255, 255, 255, 0.3);\n transform: translateY(-2px);\n}\n\n/* \n * Choice buttons container and buttons - positioned inside player\n */\n\n/* Choice buttons container - positioned inside the player at the bottom */\n.sf-choice-buttons-container {\n position: absolute;\n bottom: var(--sf-spacing-xl);\n left: 50%;\n transform: translateX(-50%);\n width: calc(100% - var(--sf-spacing-lg));\n max-width: calc(100% - var(--sf-spacing-lg));\n z-index: calc(var(--sf-z-index-controls) + 1);\n gap: var(--sf-spacing-sm);\n pointer-events: auto;\n align-items: center;\n display: flex;\n flex-direction: column;\n /* Ensure container is fully transparent */\n background: transparent;\n border: none;\n outline: none;\n}\n\n/* Choice buttons container with scrolling for 5+ buttons */\n.sf-choice-buttons-container--scrollable {\n max-height: 176px; /* Show ~4 buttons with gaps (4 * 36px button + 4 * 8px gap) */\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: thin; /* Show thin scrollbar in Firefox */\n scrollbar-color: rgba(255, 255, 255, 0.2) transparent; /* More transparent Firefox scrollbar */\n scroll-behavior: smooth;\n /* Important: Use block display for scrollable container */\n display: block !important;\n}\n\n/* Style webkit scrollbar to be visible but subtle */\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar {\n width: 4px;\n}\n\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2); /* More transparent */\n border-radius: 2px;\n}\n\n.sf-choice-buttons-container--scrollable::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.4); /* Still subtle on hover */\n}\n\n/* Removed fade gradient to keep container fully transparent */\n\n/* Choice button styles - solid rounded buttons matching the image */\n.sf-choice-button {\n width: 100%;\n max-width: none;\n background: rgba(0, 0, 0, 4);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: white;\n border: none;\n border-radius: 24px; /* More rounded for pill shape */\n padding: var(--sf-spacing-md) var(--sf-spacing-md);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: center;\n outline: none;\n font-family: inherit;\n margin-bottom: 0;\n position: relative;\n overflow: hidden;\n opacity: 0; /* Start hidden for animation */\n pointer-events: none;\n /* Animation will be triggered by JavaScript when video reaches 90% */\n}\n\n/* Add margin between buttons in scrollable container */\n.sf-choice-buttons-container--scrollable .sf-choice-button {\n margin-bottom: var(--sf-spacing-sm);\n}\n\n/* Remove margin from last button */\n.sf-choice-buttons-container--scrollable .sf-choice-button:last-child {\n margin-bottom: 0;\n}\n\n/* Hover state for buttons */\n.sf-choice-button:hover {\n background: rgba(0, 0, 0, 0.9);\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.8);\n}\n\n/* Active state for all buttons */\n.sf-choice-button:active {\n transform: translateY(0) scale(0.98);\n transition: all 0.1s ease;\n}\n\n/* Remove specific action type styling - use consistent dark buttons */\n.sf-choice-button--goto,\n.sf-choice-button--url,\n.sf-choice-button--next,\n.sf-choice-button--dom,\n.sf-choice-button--function {\n background: rgba(0, 0, 0, 0.4);\n border: none;\n}\n\n.sf-choice-button--goto:hover,\n.sf-choice-button--url:hover,\n.sf-choice-button--next:hover,\n.sf-choice-button--dom:hover,\n.sf-choice-button--function:hover {\n background: rgba(0, 0, 0, 0.9);\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n}\n\n/* Hide choice buttons in minimized state */\n.sf-player--minimized .sf-choice-buttons-container {\n display: none !important;\n}\n\n/* Hide choice buttons in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-choice-buttons-container,\n.sf-player--idleMode .sf-choice-buttons-container {\n display: none !important;\n}\n\n/* Smaller mobile screens - maintain same layout but with tighter spacing */\n@media (max-width: 480px) {\n .sf-choice-buttons-container {\n bottom: var(--sf-spacing-sm);\n width: calc(100% - var(--sf-spacing-md));\n max-width: calc(100% - var(--sf-spacing-md));\n gap: calc(var(--sf-spacing-xs) + 2px);\n }\n \n .sf-choice-button {\n padding: var(--sf-spacing-sm) var(--sf-spacing-sm);\n font-size: 11px;\n border-radius: 20px;\n }\n}\n\n/* Touch device specific adjustments */\n@media (pointer: coarse) {\n .sf-choice-buttons-container {\n gap: var(--sf-spacing-sm);\n }\n \n .sf-choice-button {\n min-height: 44px; /* Apple's recommended minimum touch target size */\n padding: var(--sf-spacing-md) var(--sf-spacing-md);\n }\n}\n\n/* Button fade-in animation */\n@keyframes buttonFadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Animation class that will be added by JavaScript at 90% video progress */\n.sf-choice-button.sf-show-button {\n animation: buttonFadeIn 0.3s ease-out forwards;\n pointer-events: auto;\n}\n\n/* Staggered animation delays for multiple buttons when shown */\n.sf-choice-button.sf-show-button:nth-child(1) {\n animation-delay: 0s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(2) {\n animation-delay: 0.15s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(3) {\n animation-delay: 0.3s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(4) {\n animation-delay: 0.45s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(5) {\n animation-delay: 0.6s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(6) {\n animation-delay: 0.75s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(7) {\n animation-delay: 0.9s;\n}\n\n.sf-choice-button.sf-show-button:nth-child(8) {\n animation-delay: 1.05s;\n}\n\n/* Scroll indicator arrow */\n.sf-scroll-indicator {\n position: absolute;\n bottom: calc(var(--sf-spacing-xl) - 25px);\n left: 50%;\n transform: translateX(-50%);\n color: rgba(255, 255, 255, 0.6);\n font-size: 20px;\n pointer-events: none;\n z-index: calc(var(--sf-z-index-controls) + 2);\n transition: opacity 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0; /* Start hidden */\n}\n\n/* Show scroll indicator with animation - appears after buttons */\n.sf-scroll-indicator.sf-show-scroll-indicator {\n animation: scrollIndicatorFadeIn 0.4s ease-out 1.2s forwards, bounceArrow 1.5s ease-in-out 1.6s infinite;\n}\n\n/* Hide arrow when scrolled to bottom */\n.sf-scroll-indicator--hidden {\n opacity: 0;\n}\n\n/* Fade in animation for scroll indicator */\n@keyframes scrollIndicatorFadeIn {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n/* Bounce animation for the arrow */\n@keyframes bounceArrow {\n 0%, 100% {\n transform: translateX(-50%) translateY(0);\n }\n 50% {\n transform: translateX(-50%) translateY(5px);\n }\n}\n\n/* Hide scroll indicator in minimized state */\n.sf-player--minimized .sf-scroll-indicator {\n display: none !important;\n}\n\n/* Hide scroll indicator in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-scroll-indicator,\n.sf-player--idleMode .sf-scroll-indicator {\n display: none !important;\n} \n /* \n * Transcript component styles for the Saltfish Playlist Player\n * Following BEM naming convention\n */\n\n/* Transcript container */\n.sf-transcript {\n position: absolute;\n bottom: 40px; /* Above the progress bar */\n left: 0;\n right: 0;\n max-height: 200px;\n background: transparent;\n margin: 0 var(--sf-spacing-md);\n overflow: hidden;\n z-index: var(--sf-z-index-controls);\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.3s ease-out;\n pointer-events: none;\n}\n\n/* Visible state */\n.sf-transcript--visible {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n/* Transcript content */\n.sf-transcript__content {\n max-height: 180px;\n overflow: visible;\n padding: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 100%;\n text-align: center;\n}\n\n/* Webkit scrollbar styling */\n.sf-transcript__content::-webkit-scrollbar {\n width: 4px;\n}\n\n.sf-transcript__content::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sf-transcript__content::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n}\n\n.sf-transcript__content::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.5);\n}\n\n/* Word-by-word display container - progressive reveal style */\n.sf-transcript__word-container {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 0.04em; /* Much tighter gap to compensate for inverse scaling effect */\n min-height: 60px;\n padding: 0 var(--sf-spacing-md);\n flex-wrap: nowrap;\n overflow: hidden;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n text-align: center;\n transition: opacity 0.15s ease-in-out; /* Smooth fade during window transitions */\n}\n\n/* Hidden state for fade transitions */\n.sf-transcript__word-container--hidden {\n opacity: 0;\n}\n\n/* Individual word styling - base state (hidden by default) */\n.sf-transcript__word {\n color: rgba(255, 255, 255, 0.65);\n font-size: 20px; /* Increased from 18px to compensate for 0.893 scale (20 * 0.893 ≈ 18px) */\n font-weight: 500; /* Set to 500 from start to prevent pixel shift on activation */\n line-height: 1.3;\n white-space: nowrap;\n text-align: center;\n opacity: 0;\n transform: scale(0.893) translateY(0); /* Scaled down - active word will be normal size (1/1.12 ≈ 0.893) */\n transition: opacity 0.2s ease, color 0.2s ease, text-shadow 0.2s ease, transform 0.2s ease;\n padding-left: 0.12em; /* Consistent padding */\n padding-right: 0.12em;\n}\n\n/* Visible state - word has appeared */\n.sf-transcript__word--visible {\n opacity: 0.8;\n transform: scale(0.893) translateY(0); /* Keep scaled down */\n}\n\n/* Active word (currently speaking) - highlighted at normal size (inverse scale approach) */\n.sf-transcript__word--active {\n color: rgba(255, 255, 255, 1) !important;\n opacity: 1 !important;\n transform: scale(1) translateY(0); /* Normal size - appears 12% larger relative to scaled-down neighbors */\n text-shadow: 0 0 20px rgba(255, 255, 255, 0.3);\n /* font-weight removed - already 500 from base to prevent pixel shift */\n}\n\n/* Legacy segment styling (kept for compatibility) */\n.sf-transcript__segment {\n color: rgba(255, 255, 255);\n font-size: var(--sf-font-size-sm);\n line-height: 1.4;\n padding: var(--sf-spacing-xs) 0;\n cursor: pointer;\n transition: all 0.2s ease;\n padding-left: var(--sf-spacing-xs);\n padding-right: var(--sf-spacing-xs);\n}\n\n/* CC button styling removed - now handled via icon toggling */\n\n/* Mobile responsive styles */\n@media (max-width: 768px) {\n .sf-transcript {\n bottom: 35px; /* Positioned lower on mobile for better visibility */\n margin: 0 var(--sf-spacing-sm);\n max-height: 150px; /* Smaller on mobile */\n }\n\n .sf-transcript__content {\n max-height: 130px;\n padding: var(--sf-spacing-sm);\n }\n\n .sf-transcript__word-container {\n min-height: 50px;\n padding: 0 var(--sf-spacing-sm);\n gap: 0.2em; /* Tighter gap for mobile */\n }\n \n .sf-transcript__word {\n font-size: var(--sf-font-size-md);\n /* font-weight already 500 from base styles */\n }\n \n .sf-transcript__segment {\n font-size: var(--sf-font-size-xs);\n padding: var(--sf-spacing-xs) var(--sf-spacing-sm);\n }\n}\n\n/* Touch device optimizations */\n@media (pointer: coarse) {\n .sf-transcript__segment {\n padding: var(--sf-spacing-sm) var(--sf-spacing-xs);\n min-height: 44px; /* Larger touch target */\n display: flex;\n align-items: center;\n }\n}\n\n/* Hide transcript in minimized state */\n.sf-player--minimized .sf-transcript {\n display: none !important;\n}\n\n/* Hide transcript in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-transcript,\n.sf-player--idleMode .sf-transcript {\n display: none !important;\n}\n\n/* Animation for transcript appearance */\n@keyframes transcriptFadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes transcriptFadeOut {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(20px);\n }\n}\n /* \n * Error Display component styles for the Saltfish playlist Player\n * Clean and subtle full-widget error overlay\n */\n\n/* Error display overlay - covers full widget */\n.sf-error-display {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: calc(var(--sf-z-index-controls) + 30);\n border-radius: var(--sf-border-radius-lg);\n opacity: 0;\n transition: opacity var(--sf-transition-slow);\n pointer-events: auto;\n}\n\n/* Error display visible state */\n.sf-error-display--visible {\n opacity: 1;\n}\n\n/* Error content container */\n.sf-error-display__content {\n background-color: rgba(20, 20, 20, 0.9);\n border-radius: var(--sf-border-radius-md);\n padding: var(--sf-spacing-lg) var(--sf-spacing-xl);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.08);\n transform: translateY(8px);\n transition: transform var(--sf-transition-slow);\n max-width: 85%;\n text-align: center;\n}\n\n/* Error content visible animation */\n.sf-error-display--visible .sf-error-display__content {\n transform: translateY(0);\n}\n\n/* Error message */\n.sf-error-display__message {\n color: rgba(255, 255, 255, 0.95);\n font-size: var(--sf-font-size-md);\n line-height: 1.5;\n margin: 0;\n text-align: center;\n font-weight: 500;\n}\n\n/* Mobile responsive adjustments */\n@media (max-width: 768px) {\n .sf-error-display__content {\n padding: var(--sf-spacing-md) var(--sf-spacing-lg);\n max-width: 90%;\n }\n\n .sf-error-display__message {\n font-size: var(--sf-font-size-sm);\n }\n}\n\n/* Minimized player state adjustments */\n.sf-player--minimized .sf-error-display__content {\n padding: var(--sf-spacing-sm) var(--sf-spacing-md);\n max-width: 80%;\n}\n\n.sf-player--minimized .sf-error-display__message {\n font-size: var(--sf-font-size-sm);\n font-weight: 400;\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n .sf-error-display__content {\n background-color: rgba(0, 0, 0, 0.95);\n border: 2px solid rgba(255, 255, 255, 0.3);\n }\n\n .sf-error-display__message {\n color: rgba(255, 255, 255, 0.95);\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n .sf-error-display,\n .sf-error-display__content {\n transition: none;\n }\n}\n /**\n * Loading spinner styles\n */\n\n.sf-loading-spinner {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(2px);\n z-index: 100;\n border-radius: 12px;\n opacity: 1 !important; /* Always visible when shown, overrides parent opacity */\n}\n\n.sf-loading-spinner__content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n}\n\n.sf-loading-spinner__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #000000;\n opacity: 0.9;\n}\n\n.sf-loading-spinner__icon svg {\n width: 60px;\n height: 60px;\n /* Remove the rotation animation since we now have internal SVG animation */\n}\n\n.sf-loading-spinner__text {\n color: #333333;\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n opacity: 0.8;\n letter-spacing: 0.5px;\n}\n\n/* CSS keyframe animation removed - using SVG animateTransform instead */\n\n/* Responsive adjustments */\n@media (max-width: 480px) {\n .sf-loading-spinner__content {\n padding: 20px;\n gap: 10px;\n }\n \n .sf-loading-spinner__icon svg {\n width: 50px;\n height: 50px;\n }\n \n .sf-loading-spinner__text {\n font-size: 13px;\n }\n}\n /*\n * Cursor animation component styles for the Saltfish playlist Player\n * CSP-compliant: All styles use CSS classes and CSS custom properties instead of inline styles\n */\n\n/* Base cursor element */\n.sf-cursor {\n position: fixed;\n top: 0;\n left: 0;\n width: 36px;\n height: 36px;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n}\n\n.sf-cursor--visible {\n display: block;\n}\n\n/* Selection element */\n.sf-selection {\n position: fixed;\n pointer-events: none;\n display: none;\n z-index: 9999998;\n border: 2px solid var(--sf-selection-color, #ff7614);\n background: var(--sf-selection-bg-color, rgba(255, 118, 20, 0.1));\n border-radius: 4px;\n left: var(--sf-selection-left, 0);\n top: var(--sf-selection-top, 0);\n width: var(--sf-selection-width, 0);\n height: var(--sf-selection-height, 0);\n}\n\n.sf-selection--visible {\n display: block;\n}\n\n/* Flashlight overlay */\n.sf-flashlight-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 999997;\n display: none;\n background: var(--sf-flashlight-bg, radial-gradient(circle 150px at 50% 50%, transparent 0%, rgba(0, 0, 0, 0.4) 100%));\n clip-path: var(--sf-flashlight-clip, none);\n}\n\n.sf-flashlight-overlay--visible {\n display: block;\n}\n\n /**\n * Compact Label Styles\n * Label that appears next to the player when in compact first step mode\n * Position adapts based on player placement (left/right)\n */\n\n.sf-compact-label {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n\n /* Typography */\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n font-weight: 500;\n line-height: 1.4;\n color: #ffffff;\n\n /* Visual styling */\n background: rgba(0, 0, 0, 0.85);\n backdrop-filter: blur(10px);\n padding: 10px 16px;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3),\n 0 0 0 1px rgba(255, 255, 255, 0.1);\n\n /* Ensure it doesn't wrap */\n white-space: nowrap;\n\n /* Layering */\n z-index: 10;\n\n /* Pointer events - will be enabled via sf-compact-label--clickable class */\n pointer-events: none;\n user-select: none;\n\n /* Smooth transitions for hover effects */\n transition: transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\n box-shadow 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\n background 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n/* Clickable state - enables pointer events and cursor */\n.sf-compact-label--clickable {\n cursor: pointer;\n pointer-events: auto;\n}\n\n/* Position to the LEFT of player (when player is on the right side) */\n.sf-compact-label--left {\n right: calc(100% + 16px); /* 16px spacing from player edge */\n animation: sf-compact-label-enter-from-left 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Position to the RIGHT of player (when player is on the left side) */\n.sf-compact-label--right {\n left: calc(100% + 16px); /* 16px spacing from player edge */\n animation: sf-compact-label-enter-from-right 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Entrance animation from LEFT - slide in from left with fade */\n@keyframes sf-compact-label-enter-from-left {\n 0% {\n opacity: 0;\n transform: translateY(-50%) translateX(-20px);\n }\n 100% {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n }\n}\n\n/* Entrance animation from RIGHT - slide in from right with fade */\n@keyframes sf-compact-label-enter-from-right {\n 0% {\n opacity: 0;\n transform: translateY(-50%) translateX(20px);\n }\n 100% {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n }\n}\n\n/* Hover effect - only applies when label is clickable (pointer-events: auto) */\n.sf-compact-label--left:hover,\n.sf-compact-label--right:hover {\n background: rgba(0, 0, 0, 0.95);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4),\n 0 0 0 1px rgba(255, 255, 255, 0.2),\n 0 0 25px rgba(255, 255, 255, 0.08);\n}\n\n.sf-compact-label--left:hover {\n transform: translateY(-50%) translateX(-2px);\n}\n\n.sf-compact-label--right:hover {\n transform: translateY(-50%) translateX(2px);\n}\n\n/* Active/click state */\n.sf-compact-label--left:active,\n.sf-compact-label--right:active {\n transform: translateY(-50%) scale(0.98);\n}\n\n/* Mobile adjustments */\n@media (max-width: 768px) {\n .sf-compact-label {\n font-size: 12px;\n padding: 8px 12px;\n }\n\n .sf-compact-label--left {\n right: calc(100% + 12px); /* Slightly less spacing on mobile */\n }\n\n .sf-compact-label--right {\n left: calc(100% + 12px); /* Slightly less spacing on mobile */\n }\n}\n\n/* Very small screens - keep to side with tighter spacing */\n@media (max-width: 480px) {\n .sf-compact-label {\n /* Use most of the available screen width - on 390px wide screen this gives ~270px */\n max-width: calc(100vw - 90px - 20px - 8px - 10px); /* viewport - player - margin - spacing - small buffer */\n /* Keep nowrap - we have plenty of space on mobile screens */\n }\n\n .sf-compact-label--left {\n right: calc(100% + 8px); /* Reduce spacing slightly for mobile */\n }\n\n .sf-compact-label--right {\n left: calc(100% + 8px); /* Reduce spacing slightly for mobile */\n }\n}\n\n\n /* \n * Transitions and animations for Saltfish playlist Player\n */\n\n/* Fade in animation */\n@keyframes sf-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.sf-fade-in {\n animation: sf-fade-in 0.3s ease-in-out forwards;\n}\n\n/* Slide in from bottom animation */\n@keyframes sf-slide-in-bottom {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n\n.sf-slide-in-bottom {\n animation: sf-slide-in-bottom 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Slide in from right animation */\n@keyframes sf-slide-in-right {\n from { transform: translateX(100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n}\n\n.sf-slide-in-right {\n animation: sf-slide-in-right 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Scale in animation */\n@keyframes sf-scale-in {\n from { transform: scale(0.8); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n}\n\n.sf-scale-in {\n animation: sf-scale-in 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Scale out animation */\n@keyframes sf-scale-out {\n from { transform: scale(1); opacity: 1; }\n to { transform: scale(0.8); opacity: 0; }\n}\n\n.sf-scale-out {\n animation: sf-scale-out 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n} \n"}}class _t{static isMobile(){return this.getDeviceInfo().isMobile}static isTablet(){return this.getDeviceInfo().isTablet}static isDesktop(){return this.getDeviceInfo().isDesktop}static isTouchDevice(){return this.getDeviceInfo().isTouchDevice}static getOrientation(){return this.getDeviceInfo().orientation}static getDeviceInfo(){if(this.cachedDeviceInfo)return this.cachedDeviceInfo.orientation=this.detectOrientation(),this.cachedDeviceInfo;const t="undefined"!=typeof navigator?navigator.userAgent:"",e=this.detectTouchSupport(),{width:n,height:i}=this.getScreenDimensions(),s=/iPad|Android(?!.*Mobile)|Tablet|tablet/i,r=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i.test(t)&&!s.test(t),a=s.test(t),o=this.getScreenSize(n,i),l="small"===o&&Math.min(n,i)<768,c=r||l&&e,d=a||"medium"===o&&!l&&e&&!c,h={isMobile:c,isTablet:d,isDesktop:!c&&!d,isTouchDevice:e,screenSize:o,orientation:this.detectOrientation(),userAgent:t};return this.cachedDeviceInfo=h,h}static detectTouchSupport(){return"undefined"!=typeof window&&("ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0)}static getScreenDimensions(){return"undefined"==typeof window?{width:1920,height:1080}:{width:window.innerWidth||document.documentElement.clientWidth||1920,height:window.innerHeight||document.documentElement.clientHeight||1080}}static getScreenSize(t,e){const n=Math.min(t,e);return n<768?"small":n<1024?"medium":"large"}static detectOrientation(){if("undefined"==typeof window)return"landscape";const{width:t,height:e}=this.getScreenDimensions();return e>t?"portrait":"landscape"}static clearCache(){this.cachedDeviceInfo=null}static onDeviceChange(t){if("undefined"==typeof window)return()=>{};const e=()=>{try{this.clearCache(),t(this.getDeviceInfo())}catch(t){console.warn("DeviceDetector: Error in device change handler:",t)}};return window.addEventListener("orientationchange",e),window.addEventListener("resize",e),()=>{window.removeEventListener("orientationchange",e),window.removeEventListener("resize",e)}}}e(_t,"cachedDeviceInfo",null);const kt=Object.freeze(Object.defineProperty({__proto__:null,DeviceDetector:_t,isDeviceCompatible:t=>{if(!t||"both"===t)return!0;const e=_t.getDeviceInfo();return"mobile"===t?e.isMobile||e.isTablet:"desktop"===t&&e.isDesktop}},Symbol.toStringTag,{value:"Module"})),Tt=class t{constructor(){e(this,"transcriptContainer",null),e(this,"transcriptContent",null),e(this,"ccButton",null),e(this,"isVisible",!0),e(this,"currentTranscript",null),e(this,"chunks",[]),e(this,"videoElement",null),e(this,"timeUpdateListener",null),e(this,"videoManager",null),e(this,"firstWordForceDisplayUntil",0),e(this,"isNewVideo",!1),e(this,"lastDisplayedChunkIndex",-1),e(this,"animationFrameId",null),e(this,"isAnimationLoopActive",!1),e(this,"currentWindowStartIndex",-1),e(this,"currentWindowEndIndex",-1)}setup(t,e,n){this.videoElement=t,this.ccButton=e,this.videoManager=n,this.ccButton.addEventListener("click",this.handleCCButtonClick.bind(this)),this.timeUpdateListener=this.handleTimeUpdate.bind(this),this.videoElement.addEventListener("timeupdate",this.timeUpdateListener)}updateVideoElement(t){this.videoElement&&this.timeUpdateListener&&this.videoElement.removeEventListener("timeupdate",this.timeUpdateListener),this.videoElement=t,this.videoElement&&this.timeUpdateListener&&this.videoElement.addEventListener("timeupdate",this.timeUpdateListener)}loadTranscript(e,n=!0){this.transcriptContent&&(this.transcriptContent.innerHTML=""),this.lastDisplayedChunkIndex=-1,this.currentWindowStartIndex=-1,this.currentWindowEndIndex=-1,this.currentTranscript=e,e?(this.createTranscriptUI(),this.chunks=e.chunks||[],this.isNewVideo=!0,this.firstWordForceDisplayUntil=Date.now()+500,this.setupWordDisplay(),null!==t.userCaptionPreference?(this.isVisible=t.userCaptionPreference,this.isVisible):(this.isVisible=n,this.isVisible),this.updateCCButtonState(!0),this.isVisible?this.showTranscript():this.hideTranscript(),this.chunks.length,this.isVisible):(this.updateCCButtonState(!1),this.hideTranscript())}toggleVisibility(){this.currentTranscript&&(this.isVisible=!this.isVisible,t.userCaptionPreference=this.isVisible,this.isVisible,this.isVisible?(this.showTranscript(),this.startAnimationLoop()):(this.hideTranscript(),this.stopAnimationLoop()),this.updateCCButtonState(!!this.currentTranscript),this.isVisible)}handleCCButtonClick(t){t.preventDefault(),t.stopPropagation(),this.toggleVisibility()}handleTimeUpdate(t){!this.isAnimationLoopActive&&this.isVisible&&this.chunks.length>0&&this.startAnimationLoop()}startAnimationLoop(){if(this.isAnimationLoopActive)return;this.isAnimationLoopActive=!0;const t=()=>{if(!this.currentTranscript||!this.isVisible||!this.videoElement||0===this.chunks.length)return void this.stopAnimationLoop();const e=this.videoElement.currentTime;let n=this.findActiveChunkIndex(e);const i=Date.now();this.isNewVideo&&i<this.firstWordForceDisplayUntil&&this.chunks.length>0?n=0:this.isNewVideo&&i>=this.firstWordForceDisplayUntil&&(this.isNewVideo=!1),this.updateIntelligentWordDisplay(n),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopAnimationLoop(){null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.isAnimationLoopActive=!1}findActiveChunkIndex(t){if(0===this.chunks.length)return-1;for(let e=0;e<this.chunks.length;e++){const n=this.chunks[e];if(t>=n.start&&t<=n.end)return e}if(t<this.chunks[0].start)return 0;if(t>this.chunks[this.chunks.length-1].end)return this.chunks.length-1;for(let e=0;e<this.chunks.length-1;e++)if(t>this.chunks[e].end&&t<this.chunks[e+1].start)return this.chunks[e+1].start-t<.1?e+1:t-this.chunks[e].end<.1?e:e+1;return-1}handleStateChange(t){if(this.currentTranscript,this.chunks.length,this.currentTranscript&&0!==this.chunks.length)return"waitingForInteraction"===t||"completedWaitingForInteraction"===t?(this.transcriptContent&&(this.transcriptContent.innerHTML=""),void this.stopAnimationLoop()):void(this.isVisible?(this.isVisible,this.showTranscript(),this.startAnimationLoop()):(this.isVisible,this.hideTranscript(),this.stopAnimationLoop()));this.stopAnimationLoop()}updateIntelligentWordDisplay(t){if(this.transcriptContent&&t!==this.lastDisplayedChunkIndex)return t>=0&&t<this.chunks.length&&this.chunks[t]?(t>=this.currentWindowStartIndex&&t<=this.currentWindowEndIndex&&-1!==this.currentWindowStartIndex?this.updateHighlightInWindow(t):this.createNewWindow(t),void(this.lastDisplayedChunkIndex=t)):(this.lastDisplayedChunkIndex=-1,void(this.transcriptContent.innerHTML=""))}updateHighlightInWindow(t){if(!this.transcriptContent)return;const e=this.transcriptContent.querySelectorAll(".sf-transcript__word"),n=t-this.currentWindowStartIndex;e.forEach(((t,e)=>{t.classList.remove("sf-transcript__word--active"),e<=n?t.classList.add("sf-transcript__word--visible"):t.classList.remove("sf-transcript__word--visible")})),e[n]&&e[n].classList.add("sf-transcript__word--active")}createNewWindow(t){if(!this.transcriptContent)return;const e=this.calculateWordWindow(t);this.currentWindowStartIndex=e.startIndex,this.currentWindowEndIndex=e.endIndex;const n=this.transcriptContent.querySelector(".sf-transcript__word-container"),i=()=>{const n=document.createElement("div");n.className="sf-transcript__word-container";const i=t-e.startIndex;for(let s=e.startIndex;s<=e.endIndex;s++){const r=this.chunks[s],a=document.createElement("span");let o="sf-transcript__word";s-e.startIndex<=i&&(o+=" sf-transcript__word--visible"),s===t&&(o+=" sf-transcript__word--active"),a.className=o,a.textContent=r.text,n.appendChild(a)}return n};if(n)n.classList.add("sf-transcript__word-container--hidden"),setTimeout((()=>{if(!this.transcriptContent)return;this.transcriptContent.innerHTML="";const t=i();t.classList.add("sf-transcript__word-container--hidden"),this.transcriptContent.appendChild(t),requestAnimationFrame((()=>{t.classList.remove("sf-transcript__word-container--hidden")}))}),150);else{const t=i();this.transcriptContent.appendChild(t)}}calculateWordWindow(t){if(t<0||t>=this.chunks.length)return{startIndex:-1,endIndex:-1};let e=t,n=t,i=this.chunks[t].text.length;const s=this.chunks[t].text.trim();if(s.endsWith(".")||s.endsWith("!")||s.endsWith("?"))return{startIndex:e,endIndex:n};for(;n-e+1<4&&n+1<this.chunks.length;){const t=this.chunks[n+1].text,e=Math.ceil(1.12*t.length);if(i+e>18)break;n++,i+=e;const s=t.trim();if(s.endsWith(".")||s.endsWith("!")||s.endsWith("?"))break}return{startIndex:e,endIndex:n}}createTranscriptUI(){var t;this.transcriptContainer&&this.transcriptContainer.parentNode&&(this.transcriptContainer.parentNode.removeChild(this.transcriptContainer),this.transcriptContainer=null,this.transcriptContent=null);const e=null==(t=this.videoElement)?void 0:t.closest(".sf-video-container");e&&(this.transcriptContainer=document.createElement("div"),this.transcriptContainer.className="sf-transcript",this.transcriptContainer.classList.add("sf-hidden"),this.transcriptContent=document.createElement("div"),this.transcriptContent.className="sf-transcript__content",this.transcriptContainer&&this.transcriptContent&&(this.transcriptContainer.appendChild(this.transcriptContent),e.appendChild(this.transcriptContainer)))}setupWordDisplay(){this.transcriptContent&&(this.transcriptContent.innerHTML="")}showTranscript(){this.transcriptContainer,this.transcriptContainer&&(this.transcriptContainer.classList.remove("sf-hidden"),this.transcriptContainer.classList.add("sf-transcript--visible"))}hideTranscript(){this.transcriptContainer,this.transcriptContainer&&(this.transcriptContainer.classList.add("sf-hidden"),this.transcriptContainer.classList.remove("sf-transcript--visible"))}updateCCButtonState(t){var e;this.ccButton&&(t?(this.ccButton.classList.remove("sf-hidden"),null==(e=this.videoManager)||e.updateCCButtonIcon(this.isVisible)):this.ccButton.classList.add("sf-hidden"))}reset(){this.stopAnimationLoop(),this.transcriptContent&&(this.transcriptContent.innerHTML=""),this.currentTranscript=null,this.chunks=[],this.isNewVideo=!1,this.firstWordForceDisplayUntil=0,this.lastDisplayedChunkIndex=-1,this.currentWindowStartIndex=-1,this.currentWindowEndIndex=-1,this.isVisible&&this.hideTranscript(),this.updateCCButtonState(!1),this.transcriptContainer=null,this.transcriptContent=null}static resetUserPreference(){t.userCaptionPreference=null}async destroy(){this.stopAnimationLoop(),this.timeUpdateListener&&this.videoElement&&this.videoElement.removeEventListener("timeupdate",this.timeUpdateListener),this.transcriptContainer&&this.transcriptContainer.parentNode&&this.transcriptContainer.parentNode.removeChild(this.transcriptContainer),this.transcriptContainer=null,this.transcriptContent=null,this.ccButton=null,this.videoElement=null,this.timeUpdateListener=null,this.currentTranscript=null,this.isVisible=!1}};e(Tt,"userCaptionPreference",null);let At=Tt;class zt{constructor(t){e(this,"deviceInfo"),this.deviceInfo=t}updateDeviceInfo(t){this.deviceInfo=t}}class Lt extends zt{getVideoElementConfig(){return{playsInline:!0,muted:!0,controls:!1,preload:"metadata",additionalAttributes:{"webkit-playsinline":"true",playsinline:"true","x-webkit-airplay":"allow"},styles:{width:"100%",height:"100%",objectFit:"cover",backgroundColor:"white"}}}getControlsConfig(){return{buttonMinSize:{width:"44px",height:"44px"},useTouch:!0,progressUpdateInterval:500}}getAutoplayConfig(t){return{shouldStartMuted:!t,enableFallbackLoop:!0,fallbackTimeout:3e3,requiresUserInteraction:!0}}configureVideoElement(t){const e=this.getVideoElementConfig();t.playsInline=e.playsInline,t.muted=e.muted,t.controls=e.controls,t.preload=e.preload,Object.entries(e.additionalAttributes).forEach((([e,n])=>{try{t.setAttribute(e,n)}catch(t){console.warn(`MobilePlaybackHandler: Failed to set attribute ${e}:`,t)}}))}configureControlElement(t){}async handlePlayAttempt(t,e){const n=dt().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(e){return t.muted,await this.handleAutoplayFallback(t),!1}}async handleAutoplayFallback(t){t.muted=!0,t.loop=!0,t.playsInline=!0,t.setAttribute("playsinline","true"),t.setAttribute("webkit-playsinline","true");try{await t.play()}catch(t){console.error("MobilePlaybackHandler: All autoplay attempts failed")}}destroy(){}getProgressUpdateFrequency(t){return t?500:16}}class Vt extends zt{getVideoElementConfig(){return{playsInline:!0,muted:!1,controls:!1,preload:"metadata",additionalAttributes:{},styles:{backgroundColor:"white"}}}getControlsConfig(){return{buttonMinSize:{width:"auto",height:"auto"},useTouch:!1,progressUpdateInterval:16}}getAutoplayConfig(t){return{shouldStartMuted:!1,enableFallbackLoop:!1,fallbackTimeout:5e3,requiresUserInteraction:!1}}configureVideoElement(t){const e=this.getVideoElementConfig();t.playsInline=e.playsInline,t.muted=e.muted,t.controls=e.controls,t.preload=e.preload}configureControlElement(t){}async handlePlayAttempt(t,e){const n=dt().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(e){return t.muted,await this.handleAutoplayFallback(t),!1}}async handleAutoplayFallback(t){t.muted=!0,t.loop=!0;try{await t.play()}catch(t){throw console.error("DesktopPlaybackHandler: All autoplay attempts failed"),new Error("Desktop autoplay completely blocked")}}getProgressUpdateFrequency(t){return 16}destroy(){}}function Ot(t=18){return`<svg width="${t}" height="${t}" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>`}class Dt{constructor(t,n,i){e(this,"container"),e(this,"controlsElement",null),e(this,"progressBar",null),e(this,"muteButton",null),e(this,"ccButton",null),e(this,"deviceHandler"),e(this,"callbacks"),e(this,"updateInterval",null),e(this,"animationFrameId",null),e(this,"lastTimeupdateEvent",0),e(this,"videoElement",null),e(this,"buttonsShownAt90Percent",!1),e(this,"handleDetailedTimeUpdate",(()=>{var t;this.lastTimeupdateEvent=Date.now(),this.progressBar&&!1===(null==(t=this.videoElement)?void 0:t.paused)&&this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear"),this.videoElement&&!this.buttonsShownAt90Percent&&this.videoElement.duration>0&&this.videoElement.currentTime/this.videoElement.duration>=.9&&(this.callbacks.on90PercentReached(),this.buttonsShownAt90Percent=!0)})),e(this,"handleSeeking",(()=>{this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.updateProgress())})),e(this,"handleSeeked",(()=>{this.progressBar&&this.videoElement&&(this.videoElement.paused||(this.updateProgress(),this.progressBar.offsetWidth,this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear")))})),e(this,"handleProgressBarClick",(t=>{const e=t.currentTarget;if(!this.videoElement||this.videoElement.duration<=0)return;const n=e.getBoundingClientRect(),i=(t.clientX-n.left)/n.width,s=this.videoElement.duration*i;this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width",100*i+"%")),this.callbacks.onSeek(s),t.preventDefault(),t.stopPropagation()})),this.container=t,this.deviceHandler=n,this.callbacks=i}create(t){this.videoElement=t,this.controlsElement=document.createElement("div"),this.controlsElement.className="sf-video-container__controls",this.container.appendChild(this.controlsElement),this.progressBar=document.createElement("div"),this.progressBar.className="sf-video-container__progress",this.controlsElement.appendChild(this.progressBar);const e=this.deviceHandler.getControlsConfig();e.useTouch&&this.controlsElement.addEventListener("touchend",this.handleProgressBarClick),this.controlsElement.addEventListener("click",this.handleProgressBarClick),this.muteButton=document.createElement("button"),this.muteButton.className="sf-video-container__mute-button",this.deviceHandler.configureControlElement(this.muteButton),this.muteButton.innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="none"/><path d="M15 9c0.8 0.8 1.5 1.9 1.5 3s-0.7 2.2-1.5 3" stroke="currentColor"/><path d="M19 7c1.6 1.6 2.5 3.8 2.5 6s-0.9 4.4-2.5 6" stroke="currentColor"/></svg>',e.useTouch&&this.muteButton.addEventListener("touchend",(t=>{t.preventDefault(),this.toggleMute()})),this.muteButton.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),this.toggleMute()})),this.container.appendChild(this.muteButton),this.updateMuteButtonIcon(),this.ccButton=document.createElement("button"),this.ccButton.className="sf-video-container__cc-button",this.deviceHandler.configureControlElement(this.ccButton),this.updateCCButtonIcon(!1),e.useTouch&&this.ccButton.addEventListener("touchend",(t=>{t.preventDefault()})),this.ccButton.addEventListener("click",(t=>{t.preventDefault()})),this.container.appendChild(this.ccButton),this.attachProgressListeners(t)}attachProgressListeners(t){t&&(t.addEventListener("seeking",this.handleSeeking),t.addEventListener("seeked",this.handleSeeked),t.addEventListener("timeupdate",this.handleDetailedTimeUpdate))}detachProgressListeners(t){t&&(t.removeEventListener("seeking",this.handleSeeking),t.removeEventListener("seeked",this.handleSeeked),t.removeEventListener("timeupdate",this.handleDetailedTimeUpdate))}updateVideoElement(t){this.detachProgressListeners(this.videoElement),this.videoElement=t,this.attachProgressListeners(t)}reset(){this.stopProgressTracking(),this.buttonsShownAt90Percent=!1,this.lastTimeupdateEvent=0,this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width","0%"))}reset90PercentTrigger(){this.buttonsShownAt90Percent=!1}destroy(){this.stopProgressTracking(),this.detachProgressListeners(this.videoElement),this.controlsElement&&(this.deviceHandler.getControlsConfig().useTouch&&this.controlsElement.removeEventListener("touchend",this.handleProgressBarClick),this.controlsElement.removeEventListener("click",this.handleProgressBarClick)),this.controlsElement=null,this.progressBar=null,this.muteButton=null,this.ccButton=null,this.videoElement=null}startProgressTracking(){if(this.stopProgressTracking(),!this.videoElement)return;const t=this.videoElement.loop&&this.videoElement.muted,e=this.deviceHandler.getProgressUpdateFrequency(t);if(e>=16){const t=()=>{!this.videoElement||this.videoElement.paused||this.videoElement.ended||this.updateProgress(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}else{const t=()=>{null===this.updateInterval||!this.videoElement||this.videoElement.paused||this.videoElement.ended||(this.updateProgress(),this.updateInterval=window.setTimeout(t,e))};this.updateInterval=window.setTimeout(t,e)}}stopProgressTracking(){null!==this.updateInterval&&(window.clearInterval(this.updateInterval),this.updateInterval=null),null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}updateProgressImmediate(t,e){if(!this.progressBar||e<=0)return;const n=t/e*100;this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width",`${n}%`)}updateProgress(){if(!this.progressBar||!this.videoElement)return;const t=this.videoElement.currentTime||0,e=this.videoElement.duration||0;if(e>0){const n=t/e*100,i="none"!==this.progressBar.style.getPropertyValue("--sf-progress-transition"),s=Date.now()-this.lastTimeupdateEvent;this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width",`${n}%`),this.progressBar.offsetWidth,this.videoElement.ended?this.progressBar.style.setProperty("--sf-progress-transition","width 0.2s ease-out"):!this.videoElement.paused&&!this.videoElement.seeking&&i&&s<500&&this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear")}}setMuted(t){dt().setMuted(t),this.updateMuteButtonIcon()}toggleMute(){const t=!dt().isMuted;this.setMuted(t),this.callbacks.onMuteToggle()}getMuted(){return dt().isMuted}updateMuteButtonIcon(){if(!this.muteButton)return;const t=dt().isMuted;this.muteButton.innerHTML=t?'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm101.66-61.3a8,8,0,0,1-11.32,11.32L216,139.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L204.69,128l-18.35-18.34a8,8,0,0,1,11.32-11.32L216,116.69l18.34-18.35a8,8,0,0,1,11.32,11.32L227.31,128Z"/></svg>':'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z"/></svg>'}updateCCButtonIcon(t){this.ccButton&&(this.ccButton.innerHTML=t?'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"/></svg>':'<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"/><line x1="48" y1="48" x2="208" y2="208" stroke="currentColor" stroke-width="16" stroke-linecap="round"/></svg>')}showProgressBar(){if(this.controlsElement){const t=this.controlsElement.closest(".sf-player");null==t||t.classList.contains("sf-player--minimized"),this.controlsElement.classList.remove("sf-hidden")}this.progressBar&&(this.progressBar.style.setProperty("--sf-progress-transition","none"),this.progressBar.style.setProperty("--sf-progress-width","0%"),this.progressBar.offsetWidth,this.progressBar.style.setProperty("--sf-progress-transition","width 0.1s linear"))}hideProgressBar(){this.controlsElement&&this.controlsElement.classList.add("sf-hidden")}showMuteButton(){this.muteButton&&this.muteButton.classList.remove("sf-hidden")}hideMuteButton(){this.muteButton&&this.muteButton.classList.add("sf-hidden")}getCCButton(){return this.ccButton}}class Ft{constructor(){e(this,"audioContext",null),e(this,"analyser",null),e(this,"sourceVideo1",null),e(this,"sourceVideo2",null),e(this,"activeSource",null),e(this,"videoElement1",null),e(this,"videoElement2",null),e(this,"dataArray",null),e(this,"animationId",null),e(this,"isInitialized",!1),e(this,"useFallbackMode",!1),e(this,"isPaused",!1),e(this,"fftSize",2048),e(this,"barCount",12),e(this,"smoothingTimeConstant",.75),e(this,"fallbackTime",0),e(this,"zeroDataFrameCount",0),e(this,"maxZeroFramesBeforeFallback",60)}initialize(t){try{if(!this.isInitialized){const t=window.AudioContext||window.webkitAudioContext;this.audioContext=new t,this.analyser=this.audioContext.createAnalyser(),this.analyser.fftSize=this.fftSize,this.analyser.smoothingTimeConstant=this.smoothingTimeConstant;const e=this.analyser.frequencyBinCount;this.dataArray=new Uint8Array(e),this.analyser.connect(this.audioContext.destination),this.isInitialized=!0,this.useFallbackMode=!1,this.zeroDataFrameCount=0}if(this.videoElement1===t)return this.resumeAudioContext(),void this.switchToSource(this.sourceVideo1);if(this.videoElement2===t)return this.resumeAudioContext(),void this.switchToSource(this.sourceVideo2);this.resumeAudioContext();const e=this.audioContext.createMediaElementSource(t);this.videoElement1?this.videoElement2?console.warn("AudioVisualizationManager: More than 2 video elements detected - this should not happen with dual video system"):(this.videoElement2=t,this.sourceVideo2=e,this.switchToSource(e)):(this.videoElement1=t,this.sourceVideo1=e,this.switchToSource(e)),this.zeroDataFrameCount=0}catch(t){console.warn("AudioVisualizationManager: Web Audio API failed, using fallback animation",t),this.isInitialized=!0,this.useFallbackMode=!0}}switchToSource(t){this.activeSource&&this.activeSource!==t&&this.activeSource.disconnect(),t.connect(this.analyser),this.activeSource=t}getBarHeights(){if(this.isPaused)return this.getFlatBarHeights();if(this.useFallbackMode||!this.analyser||!this.dataArray)return this.getFallbackBarHeights();this.analyser.getByteFrequencyData(this.dataArray);const t=this.dataArray.some((t=>t>0));if(!t)return this.zeroDataFrameCount++,this.zeroDataFrameCount>=this.maxZeroFramesBeforeFallback&&(this.useFallbackMode||(console.warn("AudioVisualizationManager: Detected CORS blocking audio analysis after",this.zeroDataFrameCount,"frames, switching to fallback animation"),this.useFallbackMode=!0)),this.getFallbackBarHeights();this.zeroDataFrameCount=0,this.useFallbackMode&&t&&(this.useFallbackMode=!1);const e=Math.floor(this.barCount/2),n=[],i=this.dataArray.length,s=Math.floor(i/this.barCount);for(let t=0;t<e;t++){let e=0;const r=t*s,a=r+s;for(let t=r;t<a&&t<i;t++)e+=this.dataArray[t];const o=e/s/255;n.push(o)}const r=[...n].reverse();return r.pop(),r.concat(n)}getFallbackBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let n=0;n<t;n++)e.push(0);const n=[...e].reverse();return n.pop(),n.concat(e)}getFlatBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let n=0;n<t;n++)e.push(.1);const n=[...e].reverse();return n.pop(),n.concat(e)}getAverageAmplitude(){if(this.useFallbackMode||!this.analyser||!this.dataArray)return 0;this.analyser.getByteFrequencyData(this.dataArray);let t=0;for(let e=0;e<this.dataArray.length;e++)t+=this.dataArray[e];const e=t/this.dataArray.length/255;return 0===e?0:e}startVisualization(t){if(!this.isInitialized)return void console.warn("AudioVisualizationManager: Cannot start visualization - not initialized");null!==this.animationId&&this.stopVisualization(),this.audioContext&&"suspended"===this.audioContext.state&&this.audioContext.resume(),this.fallbackTime=0,this.zeroDataFrameCount=0;const e=()=>{this.fallbackTime+=16;const n=this.getBarHeights(),i=this.getAverageAmplitude();t(n,i),this.animationId=requestAnimationFrame(e)};e()}stopVisualization(){null!==this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}pause(){this.isPaused=!0}resume(){this.isPaused=!1}resumeAudioContext(){this.audioContext&&"suspended"===this.audioContext.state&&this.audioContext.resume().catch((t=>{console.warn("AudioVisualizationManager: Failed to resume AudioContext",t)}))}resetFallbackMode(){this.useFallbackMode&&(this.useFallbackMode=!1,this.zeroDataFrameCount=0)}getIsInitialized(){return this.isInitialized}reset(){if(this.stopVisualization(),this.sourceVideo1)try{this.sourceVideo1.disconnect()}catch(t){}if(this.sourceVideo2)try{this.sourceVideo2.disconnect()}catch(t){}this.videoElement1=null,this.videoElement2=null,this.sourceVideo1=null,this.sourceVideo2=null,this.activeSource=null,this.useFallbackMode=!1,this.isPaused=!1,this.fallbackTime=0,this.zeroDataFrameCount=0}cleanup(){this.stopVisualization(),this.sourceVideo1&&this.sourceVideo1.disconnect(),this.sourceVideo2&&this.sourceVideo2.disconnect(),this.analyser&&this.analyser.disconnect(),this.audioContext&&"closed"!==this.audioContext.state&&this.audioContext.close(),this.audioContext=null,this.analyser=null,this.sourceVideo1=null,this.sourceVideo2=null,this.activeSource=null,this.videoElement1=null,this.videoElement2=null,this.dataArray=null,this.isInitialized=!1,this.useFallbackMode=!1,this.isPaused=!1,this.fallbackTime=0,this.zeroDataFrameCount=0}destroy(){this.cleanup()}}class Ut{constructor(){e(this,"currentVideo",null),e(this,"nextVideo",null),e(this,"activeVideoIndex",0),e(this,"container",null),e(this,"controls",null),e(this,"transcriptManager"),e(this,"preloadedVideos",new Map),e(this,"audioFallbackOverlay",null),e(this,"audioVisualizationManager"),e(this,"soundbarElement",null),e(this,"currentVideoUrl",""),e(this,"nextVideoUrl",""),e(this,"playbackPositions",new Map),e(this,"completionPolicy","auto"),e(this,"videoEndedCallback",null),e(this,"deviceHandler"),e(this,"deviceChangeCleanup",null),e(this,"hasUserInteracted",!1),e(this,"autoplayFallbackTimeout",null),e(this,"handleVideoEnded",(t=>{const e=t.target,n=this.getActiveVideo();if(e!==n)return;const i=dt();"autoplayBlocked"!==i.currentState&&"idleMode"!==i.currentState?(this.controls&&n&&this.controls.updateProgressImmediate(n.duration,n.duration),n&&n.classList.add("sf-video-container__video--blurred"),"auto"===this.completionPolicy?this.handleAutoVideoEnded():this.handleManualVideoEnded()):i.currentState})),e(this,"handleTimeUpdate",(t=>{const e=t.target;e===this.getActiveVideo()&&Math.floor(e.currentTime)})),e(this,"handleVideoError",(t=>{const e=t.target;e===this.getActiveVideo()&&console.error("VideoManager: Video error",e.error)})),e(this,"handleAutoVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()})),e(this,"handleManualVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()}));const t=_t.getDeviceInfo();this.deviceHandler=function(t){return t.isMobile?new Lt(t):new Vt(t)}(t),this.transcriptManager=new At,this.audioVisualizationManager=new Ft,this.deviceChangeCleanup=_t.onDeviceChange((t=>{this.deviceHandler.updateDeviceInfo(t)}))}getDeviceInfo(){return _t.getDeviceInfo()}isMobileDevice(){return this.getDeviceInfo().isMobile}create(t){this.container=document.createElement("div"),this.container.className="sf-video-container",t.appendChild(this.container),this.currentVideo=document.createElement("video"),this.currentVideo.className="sf-video-container__video sf-video-container__video--current",this.currentVideo.crossOrigin="anonymous",this.deviceHandler.configureVideoElement(this.currentVideo),this.container.appendChild(this.currentVideo),this.nextVideo=document.createElement("video"),this.nextVideo.className="sf-video-container__video sf-video-container__video--next sf-hidden",this.nextVideo.crossOrigin="anonymous",this.deviceHandler.configureVideoElement(this.nextVideo),this.container.appendChild(this.nextVideo),dt().isMuted&&(this.currentVideo.muted=!0,this.nextVideo.muted=!0);const e={onSeek:t=>this.seek(t),onMuteToggle:()=>{var t;const e=(null==(t=this.controls)?void 0:t.getMuted())??!1;this.currentVideo&&(this.currentVideo.muted=e),this.nextVideo&&(this.nextVideo.muted=e),!e&&this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resetFallbackMode()},on90PercentReached:()=>{if(this.container){const t=new CustomEvent("video90PercentReached",{bubbles:!0,detail:{timestamp:Date.now()}});this.container.dispatchEvent(t)}}};if(this.controls=new Dt(this.container,this.deviceHandler,e),this.controls.create(this.currentVideo),this.addEventListeners(),this.currentVideo&&this.controls){const t=this.controls.getCCButton();t&&this.transcriptManager.setup(this.currentVideo,t,this)}}getActiveVideo(){return 0===this.activeVideoIndex?this.currentVideo:this.nextVideo}getInactiveVideo(){return 0===this.activeVideoIndex?this.nextVideo:this.currentVideo}forEachVideo(t){for(const e of[this.currentVideo,this.nextVideo])e&&t(e)}applyStoreMuteState(t){t.muted=dt().isMuted}clearAutoplayFallbackTimeout(){null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null)}swapVideos(){const t=this.getActiveVideo(),e=this.getInactiveVideo();t&&e&&(t.pause(),this.applyStoreMuteState(e),t.classList.add("sf-hidden"),e.classList.remove("sf-hidden"),this.activeVideoIndex=0===this.activeVideoIndex?1:0,this.currentVideoUrl=this.nextVideoUrl,this.nextVideoUrl="")}async loadVideo(t){var e;const n=this.getActiveVideo();if(n){if(!t||""===t.trim())throw new Error("Cannot load video: No video URL provided for this step");this.controls&&this.controls.reset90PercentTrigger(),this.applyStoreMuteState(n);try{this.controls&&this.controls.reset();const i=(null==(e=dt().playlistOptions)?void 0:e.persistence)??!0;if(this.currentVideoUrl===t&&n.src&&(n.src===t||n.src.endsWith(t))){if(i){const e=this.playbackPositions.get(t);void 0!==e&&e>0&&Math.abs(n.currentTime-e)>.5&&(n.currentTime=e)}return}if(i&&this.currentVideoUrl&&n.currentTime>0&&this.playbackPositions.set(this.currentVideoUrl,n.currentTime),this.getInactiveVideo()&&this.nextVideoUrl===t){this.swapVideos();const t=this.getActiveVideo();return t&&(this.transcriptManager.updateVideoElement(t),this.controls&&this.controls.updateVideoElement(t)),void await new Promise((t=>{const e=this.getActiveVideo();if(!e)return t();if(e.readyState>=3)t();else{const n=()=>{e.removeEventListener("canplay",n),t()};e.addEventListener("canplay",n)}}))}this.currentVideoUrl=t;const s=this.preloadedVideos.get(t);if(s){const e=URL.createObjectURL(s);n.src=e,this.preloadedVideos.delete(t)}else n.src=t;n.load(),await new Promise(((e,s)=>{if(!n)return e(void 0);let r;const a=()=>{if(n){if(clearTimeout(r),i){const e=this.playbackPositions.get(t);if(void 0!==e&&e>0){const t=Math.min(e,n.duration-.5);n.currentTime=t}}else n.currentTime=0;this.transcriptManager.updateVideoElement(n),this.controls&&this.controls.updateVideoElement(n),n.removeEventListener("loadeddata",a),n.removeEventListener("error",o),e(void 0)}},o=e=>{clearTimeout(r);const i=e.target,l=null==i?void 0:i.error;console.error("VideoManager: Video load error:",l),n.removeEventListener("loadeddata",a),n.removeEventListener("error",o);const c=new Error(`Video load failed: ${(null==l?void 0:l.message)||"Unknown error"}`);c.videoUrl=t,c.mediaErrorCode=(null==l?void 0:l.code)||null,c.mediaErrorMessage=(null==l?void 0:l.message)||null,c.failureReason="media_error",s(c)};r=window.setTimeout((()=>{console.error("VideoManager: Video load timeout after 10 seconds"),n.removeEventListener("loadeddata",a),n.removeEventListener("error",o);const e=new Error("Video load timeout");e.videoUrl=t,e.mediaErrorCode=null,e.mediaErrorMessage=null,e.failureReason="timeout",s(e)}),1e4),n.addEventListener("loadeddata",a),n.addEventListener("error",o)}))}catch(e){if(console.error("VideoManager: Failed to load video:",e),e&&"object"==typeof e&&"videoUrl"in e)throw e;const n=new Error("Failed to load video");throw n.videoUrl=t,n.mediaErrorCode=null,n.mediaErrorMessage=null,n.failureReason="load_error",n}}}preloadNextVideo(t){if(!t||this.preloadedVideos.has(t))return;if(this.currentVideoUrl===t)return;if(this.nextVideoUrl===t)return;const e=this.getInactiveVideo();e?(this.nextVideoUrl=t,e.src=t,e.load(),e.preload="auto",this.applyStoreMuteState(e)):fetch(t).then((t=>{if(!t.ok)throw new Error(`Failed to fetch video: ${t.statusText}`);return t.blob()})).then((e=>{this.preloadedVideos.set(t,e)})).catch((e=>{console.error(`VideoManager: Error preloading video ${t}:`,e)}))}play(){var t;const e=this.getActiveVideo();if(!e)return void console.error("VideoManager: No active video element found");e.classList.remove("sf-video-container__video--blurred"),e.ended&&(e.currentTime=0);const n=dt();if(((null==(t=n.playlistOptions)?void 0:t.persistence)??1)&&this.currentVideoUrl){const t=this.playbackPositions.get(this.currentVideoUrl);t&&Math.abs(e.currentTime-t)>.5&&(e.currentTime=t)}if(e.loop=!1,this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resumeAudioContext(),!e.paused)return this.controls&&this.controls.startProgressTracking(),void(this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resume());this.deviceHandler.handlePlayAttempt(e,this.hasUserInteracted).then((t=>{e&&(t?(this.controls&&this.controls.startProgressTracking(),this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resume()):(n.setAutoplayFallback(),this.isMobileDevice()&&(e.playsInline=!0,e.setAttribute("playsinline","true"),e.setAttribute("webkit-playsinline","true"),setTimeout((()=>{e.paused&&e.play().catch((()=>{}))}),200))))})).catch((()=>{console.warn("VideoManager: Autoplay handler threw error - browser has strict autoplay policy"),dt().setAutoplayFallback()}))}pause(){const t=this.getActiveVideo();t&&(t.paused||(t.muted=!0,this.controls&&this.controls.updateProgressImmediate(t.currentTime,t.duration),t.pause(),this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.pause(),this.controls&&this.controls.stopProgressTracking()))}seek(t){const e=this.getActiveVideo();e&&(this.controls&&e.duration>0&&this.controls.updateProgressImmediate(t,e.duration),e.currentTime=t)}getCurrentTime(){const t=this.getActiveVideo();return t?t.currentTime:0}getDuration(){const t=this.getActiveVideo();return t?t.duration:0}getVideoElement(){return this.getActiveVideo()}reset(){this.controls&&this.controls.reset(),this.preloadedVideos.clear(),this.playbackPositions.clear(),this.currentVideoUrl="",this.nextVideoUrl="",this.activeVideoIndex=0,this.hasUserInteracted=!1,this.clearAutoplayFallbackTimeout(),this.completionPolicy="auto",this.videoEndedCallback=null,this.transcriptManager.reset(),this.hideAudioFallbackOverlay();const t=this.audioVisualizationManager.getIsInitialized();t&&this.audioVisualizationManager.reset(),this.currentVideo&&(t||(this.currentVideo.src=""),this.currentVideo.currentTime=0,this.currentVideo.pause()),this.nextVideo&&(t||(this.nextVideo.src=""),this.nextVideo.currentTime=0,this.nextVideo.pause())}async destroy(){this.removeEventListeners(),this.controls&&(this.controls.destroy(),this.controls=null),this.transcriptManager.destroy(),this.hideAudioFallbackOverlay(),this.clearAutoplayFallbackTimeout(),this.deviceChangeCleanup&&(this.deviceChangeCleanup(),this.deviceChangeCleanup=null),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.currentVideo=null,this.nextVideo=null,this.container=null,this.currentVideoUrl="",this.nextVideoUrl="",this.videoEndedCallback=null}addEventListeners(){this.forEachVideo((t=>{t.addEventListener("ended",this.handleVideoEnded),t.addEventListener("error",this.handleVideoError)}))}removeEventListeners(){this.forEachVideo((t=>{t.removeEventListener("ended",this.handleVideoEnded),t.removeEventListener("error",this.handleVideoError)}))}setMuted(t){this.currentVideo&&(this.currentVideo.muted=t),this.nextVideo&&(this.nextVideo.muted=t),this.controls&&this.controls.setMuted(t),!t&&this.audioVisualizationManager.getIsInitialized()&&this.audioVisualizationManager.resetFallbackMode()}updateCCButtonIcon(t){this.controls&&this.controls.updateCCButtonIcon(t)}isMuted(){var t;return(null==(t=this.controls)?void 0:t.getMuted())??!0}showProgressBar(){this.controls&&this.controls.showProgressBar()}hideProgressBar(){this.controls&&this.controls.hideProgressBar()}showMuteButton(){this.controls&&this.controls.showMuteButton()}hideMuteButton(){this.controls&&this.controls.hideMuteButton()}setCompletionPolicy(t,e){this.completionPolicy=t,this.videoEndedCallback=e||null,this.updateVideoEndedHandler()}updateVideoEndedHandler(){}markUserInteraction(){this.hasUserInteracted||(this.hasUserInteracted=!0,this.autoplayFallbackTimeout,this.clearAutoplayFallbackTimeout())}hasUserInteractedWith(){return this.hasUserInteracted}resetUserInteraction(){this.hasUserInteracted=!1,this.clearAutoplayFallbackTimeout()}handleAutoplayFallbackClick(t){this.markUserInteraction(),t.muted=!1,t.loop=!1,t.currentTime=0}loadTranscript(t,e=!0){this.transcriptManager.loadTranscript(t,e)}createSoundbar(){const t=document.createElement("div");t.className="sf-audio-soundbar";for(let e=0;e<11;e++){const n=document.createElement("div");n.className="sf-audio-soundbar__bar",n.dataset.barIndex=e.toString(),t.appendChild(n)}return t}showAudioFallbackOverlay(t,e){if(this.container){if(t&&(this.container.style.setProperty("--sf-audio-poster-url",`url('${t}')`),this.container.classList.add("sf-video-container--audio-fallback")),!this.audioFallbackOverlay){if(this.audioFallbackOverlay=document.createElement("div"),e){this.audioFallbackOverlay.className="sf-audio-fallback-overlay sf-audio-fallback-overlay--avatar";const t=document.createElement("img");t.className="sf-audio-fallback-overlay__avatar",t.src=e,t.alt="Speaker avatar";const n=document.createElement("div");n.className="sf-audio-fallback-overlay__dim",this.audioFallbackOverlay.appendChild(t),this.audioFallbackOverlay.appendChild(n)}else this.audioFallbackOverlay.className="sf-audio-fallback-overlay sf-audio-fallback-overlay--soundbar-only";this.soundbarElement=this.createSoundbar(),this.audioFallbackOverlay.appendChild(this.soundbarElement),this.container.appendChild(this.audioFallbackOverlay)}}else console.warn("VideoManager: Cannot show audio fallback overlay - container not available")}startAudioVisualization(){if(!this.soundbarElement)return;const t=this.getActiveVideo();if(t)try{this.audioVisualizationManager.initialize(t),this.audioVisualizationManager.startVisualization(((t,e)=>{this.soundbarElement&&this.soundbarElement.querySelectorAll(".sf-audio-soundbar__bar").forEach(((e,n)=>{const i=t[n]||0,s=e,r=Math.max(10,100*i);s.style.setProperty("--sf-bar-height",`${r}%`);const a=180+Math.abs(n-5)/5*120;s.style.setProperty("--sf-bar-color",`hsla(${a}, 70%, 60%, 1)`)}))}))}catch(t){console.error("VideoManager: Failed to initialize audio visualization",t)}}initializeAudioForVideo(){const t=this.getActiveVideo();if(t)try{this.audioVisualizationManager.initialize(t)}catch(t){console.error("VideoManager: Failed to initialize audio for video",t)}}hideAudioFallbackOverlay(){this.container&&(this.audioVisualizationManager.stopVisualization(),this.container.style.removeProperty("--sf-audio-poster-url"),this.container.classList.remove("sf-video-container--audio-fallback"),this.audioFallbackOverlay&&this.audioFallbackOverlay.parentNode&&(this.audioFallbackOverlay.parentNode.removeChild(this.audioFallbackOverlay),this.audioFallbackOverlay=null),this.soundbarElement=null)}}const Bt={tolerance:.3,minSize:1};function Nt(t){return t.trim().replace(/\s+/g," ")}function Rt(t,e){return t.tagName.toUpperCase()===e.tagName.toUpperCase()&&Nt(t.textContent||"")===Nt(e.textContent)}function Ht(t,e){const n=t.getBoundingClientRect();return 0===n.width||0===n.height?"zero size":n.width<e.minSize||n.height<e.minSize?`too small (${n.width.toFixed(0)}x${n.height.toFixed(0)})`:null}function $t(t,e){const n=t.getBoundingClientRect();return(Math.min(n.width,e.width)/Math.max(n.width,e.width)+Math.min(n.height,e.height)/Math.max(n.height,e.height))/2*100}function Yt(t,e,n,i=Bt){const s=document.querySelectorAll(t);if(0===s.length)return null;if(e){const t=function(t,e,n){const i=[];for(const s of t)Ht(s,n)||Rt(s,e)&&i.push(s);return 0===i.length?(e.tagName,e.textContent.substring(0,50),e.textContent.length,null):(i.length,i[0])}(s,e,i);if(t)return t;if(!n)return null}if(n)return function(t,e,n,i){const s=100*(1-i.tolerance),r=[];for(const t of e){const e=Ht(t,i);if(e){r.push({element:t,score:-1,rejection:e});continue}const a=$t(t,n);if(a<s){const e=t.getBoundingClientRect();r.push({element:t,score:a,rejection:`size mismatch: expected ~${n.width.toFixed(0)}x${n.height.toFixed(0)}, got ${e.width.toFixed(0)}x${e.height.toFixed(0)}`})}else r.push({element:t,score:a})}r.length,n.width.toFixed(0),n.height.toFixed(0);for(let t=0;t<r.length;t++){const e=r[t],n=e.element.getBoundingClientRect();e.rejection?e.rejection:e.score.toFixed(0),n.width.toFixed(0),n.height.toFixed(0)}const a=r.filter((t=>!t.rejection));return 0===a.length?null:(a.sort(((t,e)=>e.score-t.score)),a[0].score.toFixed(0),a[0].element)}(0,s,n,i);for(const t of s)if(!Ht(t,i))return t;return s[0]}function Xt(t,e,n,i=Bt){if(Ht(t,i))return!1;if(e&&Rt(t,e))return!0;if(n){const e=100*(1-i.tolerance);return $t(t,n)>=e}return!0}function jt(t,e,n,i,s){const r=function(t,e,n){const i=document.querySelectorAll(t);return 0===i.length?"no_elements":e?Array.from(i).some((t=>t.tagName.toUpperCase()===e.tagName.toUpperCase()))?"text_mismatch":"tag_mismatch":n?"size_mismatch":"no_elements"}(n,i,s);(async()=>{try{const i={playlistId:t,stepId:e,failureReason:r,selector:n},s=await async function(){const t=await async function(){try{return(await import("https://storage.saltfish.ai/libs/rrweb-snapshot-2.0.0-alpha.18.js")).snapshot(document)}catch(t){return console.warn("Failed to capture DOM snapshot:",t),null}}();if(!t)return null;try{return JSON.stringify(t)}catch(t){return console.warn("Failed to serialize DOM snapshot:",t),null}}();s&&(i.domSnapshot=s),await fetch("https://player.saltfish.ai/element-errors",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)})}catch(t){console.warn("Failed to report element error:",t)}})()}function Wt(t){const e=document.createElement("canvas");e.width=1,e.height=1;const n=e.getContext("2d");if(!n)return null;n.fillStyle=t,n.fillRect(0,0,1,1);const[i,s,r]=n.getImageData(0,0,1,1).data;return{r:i,g:s,b:r}}class qt{constructor(){e(this,"cursor",null),e(this,"animationFrameId",null),e(this,"animationStartTime",null),e(this,"currentAnimation",null),e(this,"flashlightOverlay",null),e(this,"startX",null),e(this,"startY",null),e(this,"targetX",null),e(this,"targetY",null),e(this,"shouldShowCursor",!1),e(this,"lastCursorX",50),e(this,"lastCursorY",50),e(this,"isFirstAnimation",!0),e(this,"currentTargetElement",null),e(this,"boundScrollHandler",null),e(this,"scrollRafId",null),e(this,"scrollUpdatePending",!1),e(this,"scrollableParents",[]),e(this,"parentScrollHandlers",new Map),e(this,"selectionElement",null),e(this,"isSelectionMode",!1),e(this,"selectionPadding",4),e(this,"labelElement",null),e(this,"labelText",null),e(this,"dragStartX",null),e(this,"dragStartY",null),e(this,"dragEndX",null),e(this,"dragEndY",null),e(this,"dragPhase","move-to-start"),e(this,"dragAnimationStartTime",null),e(this,"TARGET_SPEED",350),e(this,"MIN_ANIMATION_DURATION",600),e(this,"MAX_ANIMATION_DURATION",2e3),e(this,"animationDuration",800),e(this,"totalDistance",0),e(this,"controlPointX",null),e(this,"controlPointY",null),e(this,"targetMutationObserver",null),e(this,"POINTER_HORIZONTAL_OFFSET",16),e(this,"POINTER_VERTICAL_OFFSET",16),e(this,"SELECTION_HORIZONTAL_OFFSET",8),e(this,"SELECTION_VERTICAL_OFFSET",8),e(this,"animationUtils",{validateAnimationState:()=>!this.isAutoplayBlocked()||(this.stopAnimation(),!1),calculateEasedProgress:(t,e)=>{const n=e>0?t/e:1,i=Math.min(n,1);return.5-.5*Math.cos(i*Math.PI)},calculateBezierPoint:(t,e,n,i)=>{const s=1-t;return{x:Math.pow(s,2)*e.x+2*s*t*n.x+Math.pow(t,2)*i.x,y:Math.pow(s,2)*e.y+2*s*t*n.y+Math.pow(t,2)*i.y}},hasSignificantPositionChange:(t,e,n=10)=>{const i=Math.abs(e.x-t.x),s=Math.abs(e.y-t.y);return i>n||s>n}})}getPaddingFromStyles(t){return"number"==typeof(null==t?void 0:t.padding)?t.padding:(null==t?void 0:t.padding)?parseInt(t.padding,10):this.selectionPadding}calculateDistance(t,e,n,i){return Math.sqrt(Math.pow(n-t,2)+Math.pow(i-e,2))}calculateAnimationDuration(t){const e=t/(this.TARGET_SPEED/1e3);return Math.min(Math.max(e,this.MIN_ANIMATION_DURATION),this.MAX_ANIMATION_DURATION)}getCurrentCursorPosition(){return{x:this.lastCursorX,y:this.lastCursorY}}canShowCursor(){return this.shouldShowCursor&&!this.isAutoplayBlocked()}waitForScrollComplete(t,e,n=1e3){let i=null;const s=()=>{null!==i&&clearTimeout(i),i=window.setTimeout((()=>{t.removeEventListener("scroll",s),e()}),100)};t.addEventListener("scroll",s),setTimeout((()=>{t.removeEventListener("scroll",s),null!==i&&clearTimeout(i),e()}),n)}waitForElement(t,e,n,i){this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null);let s=0,r=null,a=!1;const o=()=>{var e;if(a)return;a=!0;const s=lt.getState(),r=null==(e=s.manifest)?void 0:e.id,o=s.currentStepId;r&&o&&jt(r,o,t,n,i)},l=()=>{this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null),null!==r&&(clearInterval(r),r=null)},c=async()=>(s++,s>10?(console.warn(`CursorManager: Stopped waiting for element '${t}' after 10 attempts`),o(),l(),null):this.findElementAndScrollIntoView(t,n,i));this.targetMutationObserver=new MutationObserver((async()=>{if(this.isAutoplayBlocked())return void l();const t=await c();t&&(l(),e(t))})),this.targetMutationObserver.observe(document.body,{childList:!0,subtree:!0}),r=setInterval((()=>{if(!this.targetMutationObserver||this.isAutoplayBlocked())return void l();if(s++,s>10)return console.warn(`CursorManager: Stopped waiting for element '${t}' after 10 attempts`),o(),void l();const r=this.findElement(t,n,i);r&&(l(),e(r))}),1e3)}findScrollableParents(t){const e=[];let n=t.parentElement;for(;n&&n!==document.body;){const t=window.getComputedStyle(n),i=t.overflow,s=t.overflowX,r=t.overflowY;"scroll"!==i&&"auto"!==i&&"scroll"!==s&&"auto"!==s&&"scroll"!==r&&"auto"!==r||(n.scrollHeight>n.clientHeight||n.scrollWidth>n.clientWidth)&&e.push(n),n=n.parentElement}return e}addScrollListenersToParents(t){this.removeScrollListenersFromParents(),this.scrollableParents=this.findScrollableParents(t),this.scrollableParents.forEach((t=>{const e=this.handleScroll.bind(this);this.parentScrollHandlers.set(t,e),t.addEventListener("scroll",e,{passive:!0})}))}removeScrollListenersFromParents(){this.parentScrollHandlers.forEach(((t,e)=>{e.removeEventListener("scroll",t)})),this.parentScrollHandlers.clear(),this.scrollableParents=[]}findElement(t,e,n){if(e||n){return Yt(t,e,n)||null}const i=document.querySelectorAll(t);if(0===i.length)return null;if(1===i.length)return i[0];for(const t of i)if(this.isElementInViewport(t))return t.getBoundingClientRect(),t;const s=window.innerWidth/2,r=window.innerHeight/2;let a=i[0],o=1/0;for(const t of i){const e=t.getBoundingClientRect(),n=e.left+e.width/2,i=e.top+e.height/2,l=Math.sqrt(Math.pow(n-s,2)+Math.pow(i-r,2));l<o&&(o=l,a=t)}return a.getBoundingClientRect(),a}isElementInViewport(t){const e=t.getBoundingClientRect(),n=window.innerHeight||document.documentElement.clientHeight,i=window.innerWidth||document.documentElement.clientWidth;if(!(e.top>=0&&e.bottom<=n&&e.left>=0&&e.right<=i))return!1;const s=this.findScrollableParents(t);for(const t of s){const n=t.getBoundingClientRect();if(!(e.top>=n.top&&e.bottom<=n.bottom&&e.left>=n.left&&e.right<=n.right))return!1}return!0}async scrollElementIntoView(t){return new Promise((e=>{const n=this.findScrollableParents(t),i=t.getBoundingClientRect(),s=window.innerHeight||document.documentElement.clientHeight,r=i.height>s?"start":"center";0===n.length?(t.scrollIntoView({behavior:"smooth",block:r,inline:"center"}),this.waitForScrollComplete(window,e)):this.scrollParentContainersToShowElement(t,n).then((()=>{this.isElementInViewport(t)||t.scrollIntoView({behavior:"smooth",block:r,inline:"center"}),setTimeout((()=>{e()}),200)}))}))}async scrollParentContainersToShowElement(t,e){return new Promise((n=>{let i=0;const s=e.length;if(0===s)return void n();const r=()=>{i++,i>=s&&n()};e.forEach((e=>{const n=t.getBoundingClientRect(),i=e.getBoundingClientRect(),s=e.scrollTop,a=e.scrollLeft;let o;o=n.height>i.height?s+(n.top-i.top):s+(n.top-i.top)-i.height/2+n.height/2;const l=a+(n.left-i.left)-i.width/2+n.width/2;e.scrollTo({top:Math.max(0,o),left:Math.max(0,l),behavior:"smooth"}),this.waitForScrollComplete(e,r,800)}))}))}async findElementAndScrollIntoView(t,e,n){const i=this.findElement(t,e,n);return i?(this.isElementInViewport(i)||await this.scrollElementIntoView(i),i):null}cleanupExistingElements(){document.querySelectorAll(".sf-cursor").forEach((t=>t.remove())),document.querySelectorAll(".sf-cursor-label").forEach((t=>t.remove())),document.querySelectorAll(".sf-selection").forEach((t=>t.remove())),document.querySelectorAll(".sf-flashlight-overlay").forEach((t=>t.remove())),this.cursor=null,this.labelElement=null,this.selectionElement=null,this.flashlightOverlay=null}create(){this.cleanupExistingElements(),this.injectCursorStyles(),this.cursor=document.createElement("div"),this.cursor.className="sf-cursor",this.cursor.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none"><defs><filter id="cursor-shadow" x="-50%" y="-50%" width="200%" height="200%"><feDropShadow dx="0" dy="1" stdDeviation="1.2" flood-color="rgba(0, 0, 0, 0.22)"/></filter></defs><path d="M3.5 3.5L10.5 20.5L13.3 13.3L20.5 10.5L3.5 3.5Z" fill="#ff7614" stroke="white" stroke-width="0.7" stroke-linejoin="round" stroke-linecap="round" filter="url(#cursor-shadow)"/></svg>',this.labelElement=document.createElement("div"),this.labelElement.className="sf-cursor-label",this.selectionElement=document.createElement("div"),this.selectionElement.className="sf-selection",document.body.appendChild(this.cursor),document.body.appendChild(this.labelElement),document.body.appendChild(this.selectionElement),this.flashlightOverlay=document.createElement("div"),this.flashlightOverlay.className="sf-flashlight-overlay",document.body.appendChild(this.flashlightOverlay),this.boundScrollHandler=this.handleScroll.bind(this),window.addEventListener("scroll",this.boundScrollHandler,{passive:!0}),this.lastCursorX=window.innerWidth-50,this.lastCursorY=window.innerHeight-50}injectCursorStyles(){const t="\n .sf-cursor {\n position: fixed;\n top: 0;\n left: 0;\n width: 40px;\n height: 40px;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n /* Defensive styles to prevent host page CSS interference */\n margin: 0;\n padding: 0;\n border: 0;\n box-sizing: content-box;\n line-height: 0;\n font-size: 0;\n vertical-align: baseline;\n overflow: visible;\n }\n\n .sf-cursor--visible {\n display: block;\n }\n\n .sf-cursor svg {\n display: block;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n .sf-selection {\n position: fixed;\n pointer-events: none;\n display: none;\n z-index: 9999998;\n top: 0;\n left: 0;\n border: 2px solid var(--sf-selection-color, #ff7614);\n background: var(--sf-selection-bg-color, rgba(255, 118, 20, 0));\n border-radius: 4px;\n width: var(--sf-selection-width, 0);\n height: var(--sf-selection-height, 0);\n transform: var(--sf-selection-transform, translate(0, 0));\n will-change: transform;\n box-sizing: border-box;\n }\n\n .sf-selection--visible {\n display: block;\n }\n\n .sf-flashlight-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 9999997;\n display: none;\n background: var(--sf-flashlight-bg, radial-gradient(circle 150px at 50% 50%, transparent 0%, rgba(0, 0, 0, 0.4) 100%));\n clip-path: var(--sf-flashlight-clip, none);\n }\n\n .sf-flashlight-overlay--visible {\n display: block;\n }\n\n .sf-cursor-label {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-label-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n font-size: 13px;\n font-weight: 500;\n color: var(--sf-cursor-label-text, #fff);\n background: var(--sf-cursor-label-bg, #ff7614);\n padding: 4px 10px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n white-space: nowrap;\n margin: 0;\n border: 0;\n box-sizing: border-box;\n line-height: 1.4;\n }\n\n .sf-cursor-label--visible {\n display: block;\n }\n ";try{const e=new CSSStyleSheet;e.replaceSync(t),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e]}catch(e){const n=document.createElement("style");n.textContent=t,document.head.appendChild(n)}}handleScroll(){!this.isAutoplayBlocked()&&this.shouldShowCursor&&this.currentTargetElement&&(null!==this.animationFrameId||this.scrollUpdatePending||(this.scrollUpdatePending=!0,this.scrollRafId=requestAnimationFrame((()=>{this.updateCursorPositionOnScroll(),this.scrollUpdatePending=!1,this.scrollRafId=null}))))}updateCursorPositionOnScroll(){var t,e;if(!this.currentTargetElement)return;const n=this.currentTargetElement.getBoundingClientRect();let i,s;if(this.isSelectionMode){const e=this.getPaddingFromStyles(null==(t=this.currentAnimation)?void 0:t.selectionStyles);i=n.right+e+this.SELECTION_HORIZONTAL_OFFSET,s=n.bottom+e+this.SELECTION_VERTICAL_OFFSET}else i=n.left+n.width/2+this.POINTER_HORIZONTAL_OFFSET,s=n.top+n.height/2+this.POINTER_VERTICAL_OFFSET;if(this.show(i,s),this.lastCursorX=i,this.lastCursorY=s,this.selectionElement&&this.isSelectionMode){const t=this.getPaddingFromStyles(null==(e=this.currentAnimation)?void 0:e.selectionStyles),i=Math.floor(n.left-t),s=Math.floor(n.top-t),r=Math.ceil(n.width+2*t),a=Math.ceil(n.height+2*t);this.selectionElement.style.setProperty("--sf-selection-transform",`translate(${i}px, ${s}px)`),this.selectionElement.style.setProperty("--sf-selection-width",`${r}px`),this.selectionElement.style.setProperty("--sf-selection-height",`${a}px`),this.dragStartX=i,this.dragStartY=s,this.dragEndX=i+r,this.dragEndY=s+a,this.updateFlashlightWithCutout(i,s,r,a)}}isAutoplayBlocked(){return"autoplayBlocked"===lt.getState().currentState}setShouldShowCursor(t){if(this.isAutoplayBlocked())return this.shouldShowCursor=!1,void this.hideCursorElements();this.shouldShowCursor=t,t?this.isFirstAnimation||this.show(this.lastCursorX,this.lastCursorY):this.hideCursorElements()}show(t,e){this.canShowCursor()&&(this.lastCursorX=t,this.lastCursorY=e,this.cursor&&(this.cursor.classList.add("sf-cursor--visible"),this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`)),this.labelElement&&this.labelText&&(this.labelElement.classList.add("sf-cursor-label--visible"),this.labelElement.style.setProperty("--sf-cursor-label-transform",`translate(${t+24}px, ${e+8}px)`)),this.flashlightOverlay&&(this.flashlightOverlay.classList.add("sf-flashlight-overlay--visible"),this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${t}px ${e}px, transparent 0%, rgba(0, 0, 0, 0.4) 100%)`)))}hideCursorElements(){this.cursor&&this.cursor.classList.remove("sf-cursor--visible"),this.labelElement&&this.labelElement.classList.remove("sf-cursor-label--visible"),this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),this.flashlightOverlay&&(this.flashlightOverlay.classList.remove("sf-flashlight-overlay--visible"),this.resetFlashlightOverlay())}resetFlashlightOverlay(){if(!this.flashlightOverlay)return;this.flashlightOverlay.style.setProperty("--sf-flashlight-clip","none");const t=this.lastCursorX,e=this.lastCursorY;this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${t}px ${e}px, transparent 0%, rgba(0, 0, 0, 0.4) 100%)`)}async animate(t){if(this.isAutoplayBlocked())return;if(this.stopAnimation(),this.removeScrollListenersFromParents(),this.currentTargetElement=null,this.isSelectionMode=!1,this.resetFlashlightOverlay(),this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),!(null==t?void 0:t.targetSelector))return void console.warn("CursorManager: No targetSelector provided in animation");if(await new Promise((t=>setTimeout(t,500))),this.isAutoplayBlocked())return;const e=await this.findElementAndScrollIntoView(t.targetSelector,t.expectedElement,t.expectedSize);if(!e)return console.warn("CursorManager: Target element not found in animate:",t.targetSelector),this.setShouldShowCursor(!1),this.hideCursorElements(),void this.waitForElement(t.targetSelector,(()=>this.animate(t)),t.expectedElement,t.expectedSize);this.setShouldShowCursor(!0),this.currentTargetElement=e,this.addScrollListenersToParents(e);const n=e.getBoundingClientRect();this.isFirstAnimation?(this.startX=window.innerWidth-50,this.startY=window.innerHeight-50,this.isFirstAnimation=!1):(this.startX=this.lastCursorX,this.startY=this.lastCursorY);const i={...t,mode:t.mode||"selection"};if(this.isSelectionMode="selection"===i.mode,this.isSelectionMode)return void this.handleSelectionMode(i,n);this.targetX=n.left+n.width/2+this.POINTER_HORIZONTAL_OFFSET,this.targetY=n.top+n.height/2+this.POINTER_VERTICAL_OFFSET,this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),null!==this.targetX&&null!==this.targetY&&null!==this.startX&&null!==this.startY?(this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance)):(this.totalDistance=100,this.animationDuration=this.MIN_ANIMATION_DURATION),this.calculateControlPoint(),this.currentAnimation={...i};const s=null!==this.startX?this.startX:0,r=null!==this.startY?this.startY:0;this.show(s,r),this.animationStartTime=performance.now(),this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this))}handleSelectionMode(t,e){const n=this.getPaddingFromStyles(t.selectionStyles);this.dragStartX=Math.floor(e.left-n),this.dragStartY=Math.floor(e.top-n),this.dragEndX=Math.ceil(e.right+n),this.dragEndY=Math.ceil(e.bottom+n),this.dragPhase="move-to-start",this.targetX=this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.targetY=this.dragStartY+this.SELECTION_VERTICAL_OFFSET,null!==this.targetX&&null!==this.targetY&&null!==this.startX&&null!==this.startY?(this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance)):(this.totalDistance=100,this.animationDuration=this.MIN_ANIMATION_DURATION),this.selectionElement&&(t.selectionStyles&&(t.selectionStyles.borderColor&&this.selectionElement.style.setProperty("--sf-selection-border-color",t.selectionStyles.borderColor),t.selectionStyles.borderWidth&&this.selectionElement.style.setProperty("--sf-selection-border-width",t.selectionStyles.borderWidth),t.selectionStyles.borderRadius&&this.selectionElement.style.setProperty("--sf-selection-border-radius",t.selectionStyles.borderRadius)),this.selectionElement.classList.remove("sf-selection--visible")),this.calculateControlPoint(),this.currentAnimation={...t};const i=null!==this.startX?this.startX:0,s=null!==this.startY?this.startY:0;this.show(i,s),this.animationStartTime=performance.now(),this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this))}updateDragCoordinatesFromElement(){var t;if(!this.currentTargetElement)return;const e=this.currentTargetElement.getBoundingClientRect(),n=this.getPaddingFromStyles(null==(t=this.currentAnimation)?void 0:t.selectionStyles);this.dragStartX=Math.floor(e.left-n),this.dragStartY=Math.floor(e.top-n),this.dragEndX=Math.ceil(e.right+n),this.dragEndY=Math.ceil(e.bottom+n)}updateSelectionRectangle(t,e){if(!this.selectionElement)return;const n=Math.ceil(Math.abs(t-this.SELECTION_HORIZONTAL_OFFSET-this.dragStartX)),i=Math.ceil(Math.abs(e-this.SELECTION_VERTICAL_OFFSET-this.dragStartY)),s=Math.floor(Math.min(this.dragStartX,t-this.SELECTION_HORIZONTAL_OFFSET)),r=Math.floor(Math.min(this.dragStartY,e-this.SELECTION_VERTICAL_OFFSET));this.selectionElement.style.setProperty("--sf-selection-transform",`translate(${s}px, ${r}px)`),this.selectionElement.style.setProperty("--sf-selection-width",`${n}px`),this.selectionElement.style.setProperty("--sf-selection-height",`${i}px`),this.selectionElement.classList.add("sf-selection--visible"),this.updateFlashlightWithCutout(s,r,n,i)}validatePointerState(){return null!==this.animationStartTime&&null!==this.currentAnimation&&null!==this.startX&&null!==this.startY&&null!==this.targetX&&null!==this.targetY&&null!==this.controlPointX&&null!==this.controlPointY}validateSelectionState(){return!(!this.animationStartTime||!this.currentAnimation)&&("move-to-start"===this.dragPhase?null!==this.startX&&null!==this.startY&&null!==this.targetX&&null!==this.targetY&&null!==this.controlPointX&&null!==this.controlPointY:"dragging"!==this.dragPhase||null!==this.dragAnimationStartTime&&null!==this.dragStartX&&null!==this.dragStartY&&null!==this.dragEndX&&null!==this.dragEndY)}completePointerAnimation(){this.show(this.targetX,this.targetY),this.lastCursorX=this.targetX,this.lastCursorY=this.targetY,this.click(),setTimeout((()=>{this.stopAnimation()}),400)}completeMoveToStartPhase(){this.show(this.targetX,this.targetY),this.lastCursorX=this.targetX,this.lastCursorY=this.targetY,this.dragPhase="dragging",this.dragAnimationStartTime=performance.now();const t=this.calculateDistance(this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.dragStartY+this.SELECTION_VERTICAL_OFFSET,this.dragEndX+this.SELECTION_HORIZONTAL_OFFSET,this.dragEndY+this.SELECTION_VERTICAL_OFFSET);if(this.animationDuration=this.calculateAnimationDuration(t),this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%) scale(0.9)`),this.cursor.style.setProperty("--sf-cursor-opacity","0.9")}this.selectionElement&&(this.selectionElement.style.setProperty("--sf-selection-transform",`translate(${this.dragStartX}px, ${this.dragStartY}px)`),this.selectionElement.style.setProperty("--sf-selection-width","0px"),this.selectionElement.style.setProperty("--sf-selection-height","0px"),this.selectionElement.classList.add("sf-selection--visible"))}completeDraggingPhase(){if(this.dragPhase="release",this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`),this.cursor.style.setProperty("--sf-cursor-opacity","1")}null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStartTime=null,this.dragAnimationStartTime=null}handleMoveToStartPhase(t){if(this.currentTargetElement){this.updateDragCoordinatesFromElement();const e={x:this.targetX,y:this.targetY};if(this.targetX=this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.targetY=this.dragStartY+this.SELECTION_VERTICAL_OFFSET,this.animationUtils.hasSignificantPositionChange(e,{x:this.targetX,y:this.targetY})){const e=this.getCurrentCursorPosition();this.startX=e.x,this.startY=e.y,this.calculateControlPoint(),this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance),this.animationStartTime=t}}const e=t-this.animationStartTime;if(e>=this.animationDuration)return void this.completeMoveToStartPhase();const n=this.animationUtils.calculateEasedProgress(e,this.animationDuration),i=this.animationUtils.calculateBezierPoint(n,{x:this.startX,y:this.startY},{x:this.controlPointX,y:this.controlPointY},{x:this.targetX,y:this.targetY});this.show(i.x,i.y)}handleDraggingPhase(t){this.currentTargetElement&&this.updateDragCoordinatesFromElement();const e=t-this.dragAnimationStartTime,n=Math.min(e/this.animationDuration,1),i=.5-.5*Math.cos(n*Math.PI),s=this.dragStartX+(this.dragEndX-this.dragStartX)*i+this.SELECTION_HORIZONTAL_OFFSET,r=this.dragStartY+(this.dragEndY-this.dragStartY)*i+this.SELECTION_VERTICAL_OFFSET;this.show(s,r),this.updateSelectionRectangle(s,r),n>=1&&this.completeDraggingPhase()}handlePointerAnimation(t){if(!this.validatePointerState())return console.warn("CursorManager: Animation frame missing essential data"),void this.stopAnimation();const e=t-this.animationStartTime;if(this.currentTargetElement){const e=this.currentTargetElement.getBoundingClientRect(),n={x:this.targetX,y:this.targetY};if(this.targetX=e.left+e.width/2+this.POINTER_HORIZONTAL_OFFSET,this.targetY=e.top+e.height/2+this.POINTER_VERTICAL_OFFSET,this.animationUtils.hasSignificantPositionChange(n,{x:this.targetX,y:this.targetY})){const e=this.getCurrentCursorPosition();this.startX=e.x,this.startY=e.y,this.calculateControlPoint(),this.totalDistance=this.calculateDistance(this.startX,this.startY,this.targetX,this.targetY),this.animationDuration=this.calculateAnimationDuration(this.totalDistance),this.animationStartTime=t}}if(e>=this.animationDuration)return void this.completePointerAnimation();const n=this.animationUtils.calculateEasedProgress(e,this.animationDuration),i=this.animationUtils.calculateBezierPoint(n,{x:this.startX,y:this.startY},{x:this.controlPointX,y:this.controlPointY},{x:this.targetX,y:this.targetY});this.show(i.x,i.y),this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this))}handleSelectionAnimation(t){if(this.validateSelectionState()){switch(this.dragPhase){case"move-to-start":this.handleMoveToStartPhase(t);break;case"dragging":this.handleDraggingPhase(t)}"release"!==this.dragPhase&&(this.animationFrameId=requestAnimationFrame(this.unifiedAnimationFrame.bind(this)))}else this.stopAnimation()}unifiedAnimationFrame(t){this.animationUtils.validateAnimationState()&&(this.isSelectionMode?this.handleSelectionAnimation(t):this.handlePointerAnimation(t))}updateFlashlightWithCutout(t,e,n,i){if(!this.flashlightOverlay)return;const s=window.innerWidth,r=window.innerHeight,a=`path(evenodd, "M 0 0 L ${s} 0 L ${s} ${r} L 0 ${r} Z M ${t+4} ${e} L ${t+n-4} ${e} A 4 4 0 0 1 ${t+n} ${e+4} L ${t+n} ${e+i-4} A 4 4 0 0 1 ${t+n-4} ${e+i} L ${t+4} ${e+i} A 4 4 0 0 1 ${t} ${e+i-4} L ${t} ${e+4} A 4 4 0 0 1 ${t+4} ${e} Z")`;this.flashlightOverlay.style.setProperty("--sf-flashlight-clip",a);const o=this.lastCursorX,l=this.lastCursorY;this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${o}px ${l}px, transparent 0%, rgba(0, 0, 0, 0.4) 100%)`)}calculateControlPoint(){if(!(this.startX&&this.startY&&this.targetX&&this.targetY))return void console.warn("CursorManager: Missing start or target position for control point calculation",{startX:this.startX,startY:this.startY,targetX:this.targetX,targetY:this.targetY});const t=(this.startX+this.targetX)/2,e=(this.startY+this.targetY)/2,n=Math.sqrt(Math.pow(this.targetX-this.startX,2)+Math.pow(this.targetY-this.startY,2));this.totalDistance=n;const i=.2*n,s=(Math.random()-.5)*i*2,r=this.targetX-this.startX,a=-(this.targetY-this.startY),o=r,l=Math.sqrt(a*a+o*o);if(0===l)this.controlPointX=t+5,this.controlPointY=e+5;else{const n=a/l,i=o/l;this.controlPointX=t+n*s,this.controlPointY=e+i*s}}async moveToElement(t,e,n){if(!this.canShowCursor())return;if(this.stopAnimation(),this.removeScrollListenersFromParents(),this.currentTargetElement=null,this.isSelectionMode=!1,this.resetFlashlightOverlay(),this.isAutoplayBlocked())return;const i=await this.findElementAndScrollIntoView(t);if(!i)return console.warn("CursorManager: Target element not found:",t),this.setShouldShowCursor(!1),this.hideCursorElements(),void this.waitForElement(t,(()=>this.moveToElement(t,e,n)));this.currentTargetElement=i,this.addScrollListenersToParents(i);const s={targetSelector:t,mode:e||"selection",selectionStyles:n};this.animate(s)}click(){if(this.canShowCursor()&&this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%) scale(0.8)`),this.cursor.style.setProperty("--sf-cursor-opacity","0.8"),setTimeout((()=>{if(this.cursor){if(!this.canShowCursor())return void this.hideCursorElements();this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`),this.cursor.style.setProperty("--sf-cursor-opacity","1")}}),300)}}stopAnimation(){if(null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStartTime=null,this.currentAnimation=null,this.controlPointX=null,this.controlPointY=null,this.dragPhase="move-to-start",this.dragAnimationStartTime=null,this.cursor){const t=this.lastCursorX,e=this.lastCursorY;this.cursor.style.setProperty("--sf-cursor-transform",`translate(${t}px, ${e}px) translate(-50%, -50%)`),this.cursor.style.setProperty("--sf-cursor-opacity","1")}this.resetFlashlightOverlay(),this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible")}resetFirstAnimation(){this.isFirstAnimation=!0}reset(){this.stopAnimation(),this.currentAnimation=null,this.animationStartTime=null,this.startX=null,this.startY=null,this.targetX=null,this.targetY=null,this.currentTargetElement=null,this.isFirstAnimation=!0,this.shouldShowCursor=!1,this.cursor&&this.cursor.classList.remove("sf-cursor--visible"),this.isSelectionMode=!1,this.selectionElement&&this.selectionElement.classList.remove("sf-selection--visible"),this.dragStartX=null,this.dragStartY=null,this.dragEndX=null,this.dragEndY=null,this.dragPhase="move-to-start",this.dragAnimationStartTime=null,null!==this.scrollRafId&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null),this.scrollUpdatePending=!1,this.removeScrollListenersFromParents(),this.scrollableParents=[]}async destroy(){this.stopAnimation(),this.boundScrollHandler&&(window.removeEventListener("scroll",this.boundScrollHandler),this.boundScrollHandler=null),this.removeScrollListenersFromParents(),null!==this.scrollRafId&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null),this.scrollUpdatePending=!1,this.cursor&&this.cursor.parentNode&&(this.cursor.remove(),this.cursor=null),this.labelElement&&this.labelElement.parentNode&&(this.labelElement.remove(),this.labelElement=null),this.labelText=null,this.selectionElement&&this.selectionElement.parentNode&&(this.selectionElement.remove(),this.selectionElement=null),this.flashlightOverlay&&this.flashlightOverlay.parentNode&&(this.flashlightOverlay.remove(),this.flashlightOverlay=null),this.isFirstAnimation=!0,this.shouldShowCursor=!1,this.currentTargetElement=null,this.isSelectionMode=!1,this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null),document.documentElement.style.removeProperty("--sf-cursor-x"),document.documentElement.style.removeProperty("--sf-cursor-y")}setColor(t){if(this.cursor){const e=this.cursor.querySelector("svg");if(e){const n=e.querySelector("path");n&&n.setAttribute("fill",t)}}this.selectionElement&&(this.selectionElement.style.setProperty("--sf-selection-color",t),this.selectionElement.style.setProperty("--sf-selection-bg-color",function(t){const e=Wt(t);return e?`rgba(${e.r}, ${e.g}, ${e.b}, 0)`:t}(t))),this.labelElement&&(this.labelElement.style.setProperty("--sf-cursor-label-bg",t),this.labelElement.style.setProperty("--sf-cursor-label-text",function(t){const e=Wt(t);return e&&(299*e.r+587*e.g+114*e.b)/1e3>150?"#333":"#fff"}(t)))}setLabel(t){var e;this.labelText=t,this.labelElement&&(t?(this.labelElement.textContent=t,(null==(e=this.cursor)?void 0:e.classList.contains("sf-cursor--visible"))&&this.labelElement.classList.add("sf-cursor-label--visible")):(this.labelElement.textContent="",this.labelElement.classList.remove("sf-cursor-label--visible")))}}const Zt=["utm_source","utm_medium","utm_campaign","utm_term","utm_content","utm_id","gclid","gclsrc","gad_source","dclid","gbraid","wbraid","fbclid","msclkid","li_fat_id","twclid","ttclid","ref","_ga","_gl"];function Gt(t){if(!t)return t;try{let e;e=t.startsWith("/")||!t.includes("://")?new URL(t,window.location.origin):new URL(t);const n=function(){const t=new Map;try{const e=new URL(window.location.href);for(const n of Zt){const i=e.searchParams.get(n);null!==i&&t.set(n,i)}t.size>0&&(t.size,Array.from(t.keys()).join(", "))}catch(t){}return t}();if(0===n.size)return t;let i=0;for(const[t,s]of n)e.searchParams.has(t)||(e.searchParams.set(t,s),i++);return i>0?e.toString():t}catch(e){return t}}class Kt{constructor(){e(this,"container",null),e(this,"buttons",[]),e(this,"buttonContainer",null),e(this,"scrollIndicator",null),e(this,"storeUnsubscribe",null),e(this,"storageManager",at.getInstance()),e(this,"handleVideo90PercentReached",(t=>{this.showButtonsAt90Percent()}))}create(t){this.container=t,this.storeUnsubscribe=ct.subscribe(((t,e)=>{t.isMinimized!==(null==e?void 0:e.isMinimized)&&this.updateButtonPositions()})),t.addEventListener("video90PercentReached",this.handleVideo90PercentReached)}createButtons(t){if(!this.container)return;this.clearButtons(),this.buttonContainer=document.createElement("div");const e=t.length>4;let n="sf-choice-buttons-container";e&&(n+=" sf-choice-buttons-container--scrollable"),this.buttonContainer.className=n,t.length,this.updateCenterPlayButtonPosition(t.length),this.container.appendChild(this.buttonContainer),e&&(this.scrollIndicator=document.createElement("div"),this.scrollIndicator.className="sf-scroll-indicator",this.scrollIndicator.innerHTML='\n <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">\n <path d="M8 12l-4-4h8l-4 4z"/>\n </svg>\n ',this.container.appendChild(this.scrollIndicator)),t.forEach((t=>{const e=document.createElement("button");e.textContent=t.text,e.dataset.buttonId=t.id,e.className=`sf-choice-button sf-choice-button--${t.action.type}`,t.style&&Object.entries(t.style).forEach((([t,n])=>{e.style.setProperty(`--custom-${t}`,String(n))})),e.addEventListener("click",(async e=>{await this.handleButtonClick(e,t)})),this.buttonContainer&&(this.buttonContainer.appendChild(e),this.buttons.push(e),t.id)})),e&&this.buttonContainer&&this.setupScrollIndicator(this.buttonContainer),dt().isMinimized&&this.buttonContainer.classList.add("sf-hidden")}showButtonsAt90Percent(){this.buttons.length>0&&(this.buttons.forEach(((t,e)=>{t.classList.add("sf-show-button")})),this.scrollIndicator&&this.scrollIndicator.classList.add("sf-show-scroll-indicator"))}setupScrollIndicator(t){this.scrollIndicator&&t.addEventListener("scroll",(()=>{this.scrollIndicator&&(t.scrollHeight-t.scrollTop-t.clientHeight<10?this.scrollIndicator.classList.add("sf-scroll-indicator--hidden"):this.scrollIndicator.classList.remove("sf-scroll-indicator--hidden"))}))}updateCenterPlayButtonPosition(t){if(!this.container)return;const e=this.container.querySelector(".sf-player__center-play-button");if(e)if(t>0){let n;n=t>4?176:36*t+8*(t-1),e.style.setProperty("--sf-button-container-height",`${n}px`),e.classList.add("sf-player__center-play-button--with-buttons")}else e.style.removeProperty("--sf-button-container-height"),e.classList.remove("sf-player__center-play-button--with-buttons")}clearButtons(){this.updateCenterPlayButtonPosition(0),this.buttons.forEach((t=>{t.parentElement&&t.parentElement.removeChild(t)})),this.buttonContainer&&this.buttonContainer.parentElement&&this.buttonContainer.parentElement.removeChild(this.buttonContainer),this.scrollIndicator&&this.scrollIndicator.parentElement&&this.scrollIndicator.parentElement.removeChild(this.scrollIndicator),this.buttons=[],this.buttonContainer=null,this.scrollIndicator=null}updateButtonPositions(){if(this.buttonContainer&&0!==this.buttons.length)return dt().isMinimized?(this.buttonContainer.classList.add("sf-hidden"),void(this.scrollIndicator&&this.scrollIndicator.classList.add("sf-hidden"))):(this.buttonContainer.classList.remove("sf-hidden"),void(this.scrollIndicator&&this.scrollIndicator.classList.remove("sf-hidden")))}async handleButtonClick(t,e){var n,i,s,r,a,o;e.id,t.preventDefault(),t.stopPropagation();const l=dt();switch(e.action.type){case"next":l.play();break;case"goto":if(e.action.url){e.action.target,e.action.url,await this.flushAnalytics();const t=dt();if(t.manifest){ct.setState((t=>{t.currentStepId=e.action.target,t.manifest&&(t.progress[t.manifest.id]={...t.progress[t.manifest.id],lastStepId:e.action.target,lastProgressAt:Date.now(),lastVisited:(new Date).toISOString()})}));try{if(e.action.target,(null==(n=t.config)?void 0:n.token)&&(null==(i=t.user)?void 0:i.id)&&!(null==(s=t.user)?void 0:s.__isAnonymous)){const n=`https://player.saltfish.ai/clients/${t.config.token}/users/${t.user.id}/playlists/${t.manifest.id}`,i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:"in_progress",currentStepId:e.action.target})});i.ok?e.action.target:(i.statusText,i.status)}}catch(t){console.error("InteractionManager: Full error:",t)}if((null==(r=t.playlistOptions)?void 0:r.persistence)??1){const n=null==(a=t.user)?void 0:a.id,i=dt();if(this.storageManager.setProgress(i.progress,n),e.action.target,null==(o=t.user)?void 0:o.__isAnonymous){const n=this.storageManager.getAnonymousUserData();n&&(n.watchedPlaylists=n.watchedPlaylists||{},n.watchedPlaylists[t.manifest.id]={status:"in_progress",currentStepId:e.action.target,timestamp:Date.now(),lastProgressAt:Date.now()},this.storageManager.setAnonymousUserData(n),e.action.target)}}}const l=Gt(e.action.url);window.location.href=l}else e.action.target,l.goToStep(e.action.target);break;case"url":e.action.target,await this.flushAnalytics(),"completedWaitingForInteraction"===l.currentState?(l.completePlaylist(),await new Promise((t=>setTimeout(t,mt)))):(l.goToStep("completed"),await new Promise((t=>setTimeout(t,mt))));const t=Gt(e.action.target);window.open(t,"_blank");const{SaltfishPlayer:c}=await Promise.resolve().then((()=>ve)),d=c.getInstance();d&&d.destroy();break;case"playlist":e.action.target;try{await this.flushAnalytics(),l.completePlaylist(),await new Promise((t=>setTimeout(t,mt)));const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ve)),n=t.getInstance();n&&(e.action.target,await n.startPlaylist(e.action.target))}catch(t){console.error(`InteractionManager: Error starting playlist "${e.action.target}":`,t),e.action.target}break;default:e.action.type}if(l.manifest){const t={buttonId:e.id,actionType:e.action.type,actionTarget:e.action.target};JSON.stringify(t)}}async flushAnalytics(){try{const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ve)),e=t.getInstance(),n=e;if(e&&n.analyticsManager){const t=n.analyticsManager;"function"==typeof t.flush&&await t.flush()}}catch(t){}}reset(){this.clearButtons(),this.buttonContainer=null,this.scrollIndicator=null,this.container&&this.container.removeEventListener("video90PercentReached",this.handleVideo90PercentReached)}destroy(){this.storeUnsubscribe&&(this.storeUnsubscribe(),this.storeUnsubscribe=null),this.container&&this.container.removeEventListener("video90PercentReached",this.handleVideo90PercentReached),this.clearButtons(),this.container=null}}class Jt{constructor(t){e(this,"eventManager",null),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}}class Qt extends Jt{constructor(t){super(t),e(this,"config",null),e(this,"user",null),e(this,"eventQueue",[]),e(this,"isSending",!1),e(this,"flushInterval",null),e(this,"sessionId",null),e(this,"analyticsEnabled",!0),e(this,"boundVisibilityHandler",null)}subscribeToEvents(){this.eventManager&&(this.eventManager.on("playerPaused",(t=>{const e=dt(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerPaused",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("playerResumed",(t=>{const e=dt(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerResumed",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("stepStarted",(t=>{t.step.id,this.trackStepStarted(t.playlist.id,t.step.id)})),this.eventManager.on("stepEnded",(t=>{t.step.id,this.trackStepComplete(t.playlist.id,t.step.id)})),this.eventManager.on("playlistEnded",(t=>{t.playlist.id,this.trackPlaylistComplete(t.playlist.id)})),this.eventManager.on("error",(t=>{t.playlistId&&this.trackError(t.playlistId,t.error,t.stepId,t.errorType,t.videoUrl,t.mediaErrorCode,t.mediaErrorMessage,t.failureReason)})),this.eventManager.on("playerMinimized",(t=>{const e=dt(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerMinimized",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("playerMaximized",(t=>{const e=dt(),n=this.getRunId();(null==e?void 0:e.manifest)&&e.currentStepId&&n&&this.trackEvent({type:"playerMaximized",playlistId:e.manifest.id,stepId:e.currentStepId,runId:n,timestamp:Date.now()})})),this.eventManager.on("bubbleShown",(t=>{t.playlist.id;const e=this.getRunId();e&&this.trackEvent({type:"bubbleShown",playlistId:t.playlist.id,runId:e,timestamp:Date.now()})})),this.eventManager.on("playlistStarted",(t=>{t.playlist.id,this.trackPlaylistStart(t.playlist.id)})))}initialize(t,e){this.config=t,this.analyticsEnabled=!1!==t.enableAnalytics,e&&(this.sessionId=e),this.analyticsEnabled&&(this.flushInterval=window.setInterval((()=>{this.flushEvents()}),3e4),this.boundVisibilityHandler=this.handleVisibilityChange.bind(this),document.addEventListener("visibilitychange",this.boundVisibilityHandler))}setUser(t){this.user=t}trackPlaylistStart(t){if(!this.analyticsEnabled)return;const e=this.getRunId();e&&this.trackEvent({type:"playlistStart",playlistId:t,runId:e,timestamp:Date.now()})}trackPlaylistComplete(t){if(!this.analyticsEnabled)return;const e=this.getRunId();e&&this.trackEvent({type:"playlistComplete",playlistId:t,runId:e,timestamp:Date.now()})}trackStepStarted(t,e){if(!this.analyticsEnabled)return;const n=this.getRunId();n&&this.trackEvent({type:"stepStarted",playlistId:t,stepId:e,runId:n,timestamp:Date.now()})}trackStepComplete(t,e){if(!this.analyticsEnabled)return;const n=this.getRunId();n&&this.trackEvent({type:"stepComplete",playlistId:t,stepId:e,runId:n,timestamp:Date.now()})}trackInteraction(t,e,n){if(!this.analyticsEnabled)return;const i=this.getRunId();i&&this.trackEvent({type:"interaction",playlistId:t,stepId:e,runId:i,timestamp:Date.now(),data:n})}trackError(t,e,n,i,s,r,a,o){if(!this.analyticsEnabled)return;const l=this.getRunId();l&&this.trackEvent({type:"error",playlistId:t,stepId:n,runId:l,timestamp:Date.now(),data:{message:e.message,stack:e.stack,errorType:i||"unknown",videoUrl:s||null,mediaErrorCode:r||null,mediaErrorMessage:a||null,failureReason:o||"unknown"}})}trackEvent(t){this.analyticsEnabled&&(this.eventQueue.push(t),this.eventQueue.length>=10&&this.flushEvents())}async flush(){await this.flushEvents()}async flushEvents(){if(!this.isSending&&0!==this.eventQueue.length&&this.config&&this.analyticsEnabled){this.isSending=!0;try{const t=[...this.eventQueue];this.eventQueue=[];const e={token:this.config.token,sessionId:this.sessionId,user:this.user,events:t},n=await fetch("https://player.saltfish.ai/analytics",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!n.ok)throw this.eventQueue=[...t,...this.eventQueue],new Error(`Failed to send analytics events: ${n.statusText}`)}catch(t){console.error("Failed to send analytics events:",t)}finally{this.isSending=!1}}}handleVisibilityChange(){"hidden"===document.visibilityState&&this.flushWithBeacon()}flushWithBeacon(){if(0===this.eventQueue.length||!this.config||!this.analyticsEnabled)return;const t=[...this.eventQueue];this.eventQueue=[];const e={token:this.config.token,sessionId:this.sessionId,user:this.user,events:t};try{fetch("https://player.saltfish.ai/analytics",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0})}catch(e){console.warn("AnalyticsManager: fetch keepalive failed, events returned to queue"),this.eventQueue=[...t,...this.eventQueue]}}destroy(){this.analyticsEnabled&&this.flushEvents(),null!==this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),this.boundVisibilityHandler&&(document.removeEventListener("visibilitychange",this.boundVisibilityHandler),this.boundVisibilityHandler=null),this.eventManager&&(this.eventManager=null),this.config=null,this.user=null,this.eventQueue=[],this.sessionId=null,this.analyticsEnabled=!0}getRunId(){try{return ye.getInstance().getRunId()}catch(t){return null}}}class te{constructor(t){e(this,"sessionId"),e(this,"currentRunId",null),e(this,"storageManager"),this.storageManager=t||at.getInstance(),this.sessionId=this.getOrCreateSession(),this.sessionId}getOrCreateSession(){if("undefined"==typeof window)return this.generateUniqueId();const t=this.storageManager.getSession();if(t&&Date.now()-t.lastActivity<18e5)return t.sessionId,this.updateSessionActivity(t.sessionId),t.sessionId;const e=this.generateUniqueId();return this.updateSessionActivity(e),e}updateSessionActivity(t){if("undefined"==typeof window)return;const e={sessionId:t,lastActivity:Date.now()};this.storageManager.setSession(e)}generateUniqueId(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(t){const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}))}getSessionId(){return this.updateSessionActivity(this.sessionId),this.sessionId}startNewRun(){return this.currentRunId=this.generateUniqueId(),this.currentRunId,this.updateSessionActivity(this.sessionId),this.currentRunId}getCurrentRunId(){return this.currentRunId}endCurrentRun(){this.currentRunId&&(this.currentRunId,this.currentRunId=null)}expireSession(){"undefined"!=typeof window&&(this.storageManager.clearSession(),this.sessionId),this.sessionId=this.generateUniqueId(),this.updateSessionActivity(this.sessionId),this.currentRunId=null,this.sessionId}destroy(){this.updateSessionActivity(this.sessionId),this.endCurrentRun()}}class ee{constructor(){e(this,"activeTransitions",new Map),e(this,"waitingForInteraction",!1),e(this,"isStateMachineValidating",!1),e(this,"triggerManager",null),e(this,"beforeUnloadHandler",null),e(this,"originalPushState",null),e(this,"originalReplaceState",null),e(this,"handleURLChange",(()=>{if(this.isStateMachineValidating)return;this.triggerManager&&this.triggerManager.clearTriggeredForNonMatchingUrls();const t=Array.from(this.activeTransitions.entries()).filter((([t,e])=>{var n;return"url-path"===(null==(n=e.data)?void 0:n.type)}));let e=!1;if(t.length>0)for(const[n,i]of t)if(i.data&&this.isURLPathMatch(i.data.pattern)){e=!0;break}if(e||this.validateCurrentStepUrl()){if(this.triggerManager&&this.triggerManager.evaluateAllTriggers(),e)for(const[e,n]of t){if(!n.data)continue;const{pattern:t,nextStepId:e}=n.data;if(this.isURLPathMatch(t)){at.getInstance().clearPendingNavigation(),this.triggerTransition(e);break}}}else this.triggerManager&&this.triggerManager.evaluateAllTriggers()})),window.addEventListener("popstate",this.handleURLChange),this.monitorHistoryChanges()}setTriggerManager(t){this.triggerManager=t}monitorHistoryChanges(){this.originalPushState=history.pushState,this.originalReplaceState=history.replaceState,history.pushState=(...t)=>{this.originalPushState.apply(history,t),this.handleURLChange()},history.replaceState=(...t)=>{this.originalReplaceState.apply(history,t),this.handleURLChange()}}setupTransitions(t,e=!1,n=!1){this.cleanupTransitions(),t.id,t.transitions.forEach((t=>{switch(t.type){case"dom-click":this.setupDOMClickTransition(t);break;case"timeout":n||this.setupTimeoutTransition(t,e);break;case"url-path":this.setupURLPathTransition(t);break;case"dom-element-visible":this.setupDOMElementVisibleTransition(t);break;default:t.type}}))}setupDOMClickTransition(t){if(!t.target)return;const e=t.target,n=t.nextStep,i=`dom-click-${e}-${Date.now()}`,s=new Map;let r=null;const a=t=>{0!==t.length&&(t.length,t.forEach((t=>{if(s.has(t))return;const e=async t=>{const e=t.target;this.willCauseHardRefresh(e)?(t.preventDefault(),t.stopImmediatePropagation(),await this.triggerTransitionWithProgress(n)&&this.reDispatchClick(t)):this.triggerTransition(n)};s.set(t,e),t.addEventListener("click",e,{capture:!0})})))},o=t.expectedElement||t.expectedSize?function(t,e,n,i=Bt){const s=document.querySelectorAll(t);if(0===s.length)return[];if(e){const t=function(t,e,n){const i=[];for(const s of t)Ht(s,n)||Rt(s,e)&&i.push(s);return i.length>0?i.length:e.tagName,i}(s,e,i);if(t.length>0)return t;if(!n)return[]}if(n){const t=100*(1-i.tolerance),e=[];for(const r of s)Ht(r,i)||$t(r,n)>=t&&e.push(r);return e.length>0&&e.length,e}const r=[];for(const t of s)Ht(t,i)||r.push(t);return r.length>0?r:Array.from(s)}(e,t.expectedElement,t.expectedSize):Array.from(document.querySelectorAll(e));a(o),r=new MutationObserver((n=>{for(const i of n)"childList"===i.type&&i.addedNodes.forEach((n=>{if(n.nodeType===Node.ELEMENT_NODE){const i=n;i.matches(e)&&(!t.expectedElement&&!t.expectedSize||Xt(i,t.expectedElement,t.expectedSize))&&a([i]);const s=i.querySelectorAll(e);if(s.length>0){const e=t.expectedElement||t.expectedSize?Array.from(s).filter((e=>Xt(e,t.expectedElement,t.expectedSize))):Array.from(s);e.length>0&&(e.length,a(e))}}}))})),r.observe(document.body,{childList:!0,subtree:!0}),this.activeTransitions.set(i,{handlers:s,cleanup:()=>{s.forEach(((t,e)=>{e.removeEventListener("click",t,{capture:!0})})),s.clear(),r&&(r.disconnect(),r=null)},data:{type:"dom-click",pattern:e,nextStepId:n}})}setupTimeoutTransition(t,e){const n=t.nextStep,i=t.timeout||0,s=`timeout-${i}-${Date.now()}`;let r=null;e?this.triggerTransition(n):r=window.setTimeout((()=>{this.triggerTransition(n)}),i),this.activeTransitions.set(s,{handlers:new Map,cleanup:()=>{null!==r&&(clearTimeout(r),r=null)},data:{type:"timeout",pattern:"",nextStepId:n}})}setupURLPathTransition(t){if(!t.target)return;const e=t.target,n=t.nextStep;if(this.savePendingNavigation(e,n),this.setupBeforeUnloadHandler(e,n),this.isURLPathMatch(e)){this.triggerTransition(n);const t=5;let e=0;const i=()=>{if(e>=t)return;e++;const s=dt();"waitingForInteraction"===s.currentState||"playing"===s.currentState?(s.currentState,this.triggerTransition(n)):e<t&&(s.currentState,setTimeout(i,500))};setTimeout(i,500)}const i=`url-path-${Date.now()}`,s=window.setInterval((()=>{this.isURLPathMatch(e)&&(clearInterval(s),at.getInstance().clearPendingNavigation(),this.triggerTransition(n))}),5e3);this.activeTransitions.set(i,{handlers:new Map,cleanup:()=>{clearInterval(s)},data:{type:"url-path",pattern:e,nextStepId:n}})}savePendingNavigation(t,e){const n=dt();n.manifest&&at.getInstance().setPendingNavigation({playlistId:n.manifest.id,nextStepId:e,urlPattern:t,timestamp:Date.now()})}setupBeforeUnloadHandler(t,e){this.removeBeforeUnloadHandler(),this.beforeUnloadHandler=()=>{this.savePendingNavigation(t,e)},window.addEventListener("beforeunload",this.beforeUnloadHandler)}removeBeforeUnloadHandler(){this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null)}isURLPathMatch(t){if(!t)return!1;const e=ft(window.location.href),n=window.location.pathname,i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*"),s=new RegExp(i),r=s.test(e),a=s.test(n);return r||a}handleUrlRequirementFailure(t,e){e.pattern,e.matchType,this.cleanupTransitions();const n=window._saltfishPlayer;n&&"function"==typeof n.closePlaylist?n.closePlaylist():n&&"function"==typeof n.destroy&&n.destroy()}validateCurrentStepUrl(){const t=dt(),e=t.manifest,n=t.currentStepId;if(!e||!n)return!0;const i=e.steps.find((t=>t.id===n));if(!i||!i.urlRequirement)return!0;const s=yt(i.urlRequirement);return s||this.handleUrlRequirementFailure(n,i.urlRequirement),s}triggerTransition(t){var e;const n=dt(),i=n.currentState;n.currentStepId;const s=n.isMinimized;"playing"!==i&&"waitingForInteraction"!==i||s||(this.cleanupTransitions(),n.goToStep?n.goToStep(t):null==(e=n.goToStep)||e.call(n,t))}async triggerTransitionWithProgress(t){const e=dt(),n=e.currentState;e.currentStepId;const i=e.isMinimized;if("playing"!==n&&"waitingForInteraction"!==n)return!1;if(i)return!1;try{return this.triggerTransition(t),await new Promise((t=>setTimeout(t,mt))),!0}catch(t){return!1}}cleanupTransitions(){this.activeTransitions.forEach((t=>{t.cleanup()})),this.activeTransitions.clear(),this.waitingForInteraction=!1,this.removeBeforeUnloadHandler()}setWaitingForInteraction(t){this.waitingForInteraction=t}isWaitingForInteraction(){return this.waitingForInteraction}reset(){this.cleanupTransitions()}startStateMachineValidation(){this.isStateMachineValidating=!0}endStateMachineValidation(){this.isStateMachineValidating=!1}destroy(){this.cleanupTransitions(),window.removeEventListener("popstate",this.handleURLChange),this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=null),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=null)}setupDOMElementVisibleTransition(t){if(!t.target)return;const e=t.target,n=t.nextStep,i=`dom-visible-${e}-${Date.now()}`;let s=null,r=null,a=null,o=null;const l=t=>{s||(a=t,s=new IntersectionObserver((t=>{t.forEach((t=>{var e;if(t.isIntersecting,t.intersectionRatio.toFixed(2),t.target.outerHTML.substring(0,100),t.isIntersecting&&t.target===a){const s=window.getComputedStyle(t.target);if("0"===s.opacity||"none"===s.display||"visible"!==s.visibility||"none"===s.pointerEvents)return;this.triggerTransition(n),null==(e=this.activeTransitions.get(i))||e.cleanup(),this.activeTransitions.delete(i)}else if(t.target===a){const e=t.target.getBoundingClientRect();e.top.toFixed(0),e.left.toFixed(0),e.bottom.toFixed(0),e.right.toFixed(0),e.width.toFixed(0),e.height.toFixed(0)}}))}),{root:null,rootMargin:"0px",threshold:0}),s.observe(t),r&&(r.disconnect(),r=null))},c=t.expectedElement||t.expectedSize?Yt(e,t.expectedElement,t.expectedSize):document.querySelector(e);c?l(c):(r=new MutationObserver((n=>{for(const i of n)if("childList"===i.type&&i.addedNodes.forEach((n=>{if(n.nodeType===Node.ELEMENT_NODE){const i=n;if(i.matches(e)&&(!t.expectedElement&&!t.expectedSize||Xt(i,t.expectedElement,t.expectedSize)))return void l(i);const s=t.expectedElement||t.expectedSize?Yt(e,t.expectedElement,t.expectedSize):i.querySelector(e);if(s)return void l(s)}})),!r)break})),r.observe(document.body,{childList:!0,subtree:!0}),o=window.setInterval((()=>{if(!r)return void(o&&clearInterval(o));const n=t.expectedElement||t.expectedSize?Yt(e,t.expectedElement,t.expectedSize):document.querySelector(e);n&&n.offsetWidth>0&&n.offsetHeight>0&&(o&&clearInterval(o),o=null,l(n))}),1e3)),this.activeTransitions.set(i,{handlers:new Map,cleanup:()=>{s&&(s.disconnect(),s=null),r&&(r.disconnect(),r=null),o&&(clearInterval(o),o=null),a=null},data:{type:"dom-element-visible",pattern:e,nextStepId:n}})}reDispatchClick(t){const e=t.target;if(e&&e instanceof HTMLElement)try{setTimeout((()=>{e.tagName,e.id&&e.id,e.className&&e.className.split(" ").join(".");const n=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window,button:t.button||0,buttons:t.buttons||1,clientX:t.clientX||0,clientY:t.clientY||0,ctrlKey:t.ctrlKey||!1,shiftKey:t.shiftKey||!1,altKey:t.altKey||!1,metaKey:t.metaKey||!1});e.dispatchEvent(n)}),10)}catch(t){}}willCauseHardRefresh(t){try{if("A"===t.tagName&&t.hasAttribute("href")){const e=t.getAttribute("href");if(!e)return!1;const n=new URL(e,window.location.href),i=new URL(window.location.href);if(n.origin!==i.origin)return n.origin,i.origin,!0;const s=t.getAttribute("target");return!(!s||"_self"===s)||("mailto:"===n.protocol||"tel:"===n.protocol||"sms:"===n.protocol||"javascript:"===n.protocol)&&(n.protocol,!0)}const e=t.closest("form");if(e&&e.hasAttribute("action")){const t=e.getAttribute("action");if(t&&"#"!==t&&""!==t)return!1}return t.tagName,!1}catch(t){return!1}}}class ne{constructor(){e(this,"triggeredPlaylists",[]),e(this,"triggeredPlaylistsSet",new Set),e(this,"isMonitoring",!1),e(this,"elementClickedListeners",new Map),e(this,"clickedElements",new Set),e(this,"elementVisibleObservers",new Map),e(this,"visibleElements",new Set)}registerTriggers(t){this.triggeredPlaylists=t.filter((t=>(t.hasTriggers??t.autoStart??!1)&&t.triggers)),this.triggeredPlaylists.length,this.triggeredPlaylists.forEach((t=>{var e,n,i,s;t.id,null==(e=t.triggers)||e.url,null==(n=t.triggers)||n.elementClicked,null==(i=t.triggers)||i.elementVisible,null==(s=t.triggers)||s.maxVisits})),this.setupElementClickListeners(),this.setupElementVisibleObservers()}startMonitoring(){this.isMonitoring||(this.isMonitoring=!0,this.evaluateAllTriggers())}stopMonitoring(){this.isMonitoring=!1}evaluateAllTriggers(){if(this.isMonitoring&&0!==this.triggeredPlaylists.length)for(const t of this.triggeredPlaylists)if(this.evaluatePlaylistTrigger(t)){t.id;break}}evaluatePlaylistTrigger(t){if(!t.triggers)return!1;const{triggers:e}=t,n=t.id;if(this.triggeredPlaylistsSet.has(n))return!1;if(!dt().user)return!1;const i=[],s=this.getWatchedPlaylists(),r=this.evaluateMaxVisitsCondition(e.maxVisits,n,s);i.push(r);const a=this.evaluateURLCondition(e);i.push(a),e.url;const o=this.evaluatePlaylistSeenCondition(e.playlistSeen,s);i.push(o),JSON.stringify(e.playlistSeen);const l=this.evaluatePlaylistNotSeenCondition(e.playlistNotSeen,s);i.push(l),JSON.stringify(e.playlistNotSeen);const c=this.evaluateElementClickCondition(e.elementClicked);i.push(c),e.elementClicked;const d=this.evaluateElementVisibleCondition(e.elementVisible);i.push(d),e.elementVisible;const h=this.evaluateUserAttributesCondition(e.userAttributes);i.push(h),JSON.stringify(e.userAttributes);const u=this.applyOperators(i,e.operators);return(e.operators||["AND"]).join(", "),!!u&&(this.triggerPlaylist(n),!0)}getWatchedPlaylists(){var t,e;const n=dt();if((null==(t=n.userData)?void 0:t.watchedPlaylists)&&Object.keys(n.userData.watchedPlaylists).length>0)return n.userData.watchedPlaylists;const i=at.getInstance().getProgress(null==(e=n.user)?void 0:e.id);if(!i)return{};const s={};for(const t of Object.keys(i))s[t]={status:"in_progress",timestamp:Date.now()};return JSON.stringify(Object.keys(s)),s}evaluateMaxVisitsCondition(t,e,n){if(null===t)return!0;const i=n&&n[e];return((null==i?void 0:i.visitCount)??("completed"===(null==i?void 0:i.status)||"dismissed"===(null==i?void 0:i.status)?1:0))+("in_progress"===(null==i?void 0:i.status)?1:0)<t}normalizeUrl(t){return t.endsWith("/")&&t.lastIndexOf("/")>t.indexOf("://")+2?t.slice(0,-1):t}evaluateURLCondition(t){let e=t.url;if(!e)return!0;const n=this.normalizeUrl(ft(window.location.href.split("#")[0])),i=window.location.pathname;if("regex"===t.urlMatchType)try{const t=new RegExp(e),s=t.test(n),r=t.test(i);return s||r}catch(t){return!1}"contains"!==t.urlMatchType||e.includes("*")||(e="*"+e+"*");const s=e.includes("*");s||t.urlMatchType&&"exact"!==t.urlMatchType&&"contains"!==t.urlMatchType||(e=this.normalizeUrl(e));let r=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*");s||(r="^"+r+"$");const a=new RegExp(r),o=a.test(n),l=a.test(i);return t.url,t.urlMatchType,o||l}evaluatePlaylistSeenCondition(t,e){if(!t||0===t.length)return!0;if(!e)return!1;for(const n of t){if(!e[n])return!1;if(this.isPlaylistCurrentlyActive(n))return!1}return!0}isPlaylistCurrentlyActive(t){var e;const n=dt();return(null==(e=n.manifest)?void 0:e.id)===t&&!["idle","completed","closing","error"].includes(n.currentState)}evaluatePlaylistNotSeenCondition(t,e){if(!t||0===t.length)return!0;if(!e)return!0;for(const n of t){const t=e[n];if(t&&("completed"===t.status||"in_progress"===t.status))return!1}return!0}evaluateElementClickCondition(t){return!t||this.clickedElements.has(t)}evaluateElementVisibleCondition(t){return!t||this.visibleElements.has(t)}evaluateUserAttributesCondition(t){if(!t||0===t.length)return!0;const e=dt().user;if(!e)return!1;for(const n of t){const{attributeKey:t,attributeType:i,operator:s,value:r}=n,a=e[t];if(null==a)return!1;if(!this.compareValues(a,r,i,s))return!1}return!0}compareValues(t,e,n,i){try{switch(n){case"string":{const n=String(t),s=e;return this.applyOperator(n,s,i)}case"boolean":{const n="boolean"==typeof t?t:"true"===String(t).toLowerCase(),s="true"===e.toLowerCase();return"equals"===i?n===s:"notEquals"===i&&n!==s}case"int":{const n="number"==typeof t?t:parseFloat(String(t)),s=parseFloat(e);return!isNaN(n)&&!isNaN(s)&&this.applyOperator(n,s,i)}case"date":{const n=t instanceof Date?t:new Date(String(t)),s=new Date(e);return!isNaN(n.getTime())&&!isNaN(s.getTime())&&this.applyOperator(n.getTime(),s.getTime(),i)}default:return!1}}catch(t){return!1}}applyOperator(t,e,n){switch(n){case"equals":return t===e;case"notEquals":return t!==e;case"greaterThan":return t>e;case"lessThan":return t<e;default:return!1}}setupElementClickListeners(){this.clearElementClickListeners(),this.triggeredPlaylists.forEach((t=>{var e;(null==(e=t.triggers)?void 0:e.elementClicked)&&this.setupElementClickListener(t.id,t.triggers.elementClicked,t.triggers.elementClickedExpectedElement,t.triggers.elementClickedExpectedSize)}))}setupElementClickListener(t,e,n,i){try{const s=n||i?Yt(e,n,i):document.querySelector(e);if(!s)return;if(!this.triggeredPlaylists.find((e=>e.id===t)))return;const r=t=>{t.preventDefault(),t.stopPropagation(),this.clickedElements.add(e),this.evaluateAllTriggers()};s.addEventListener("click",r);const a=`${t}-${e}`;this.elementClickedListeners.set(a,{element:s,listener:r,selector:e})}catch(t){}}clearElementClickListeners(){this.elementClickedListeners.forEach((({element:t,listener:e})=>{try{t.removeEventListener("click",e)}catch(t){console.error("TriggerManager: Error removing element click listener:",t)}})),this.elementClickedListeners.clear()}setupElementVisibleObservers(){this.clearElementVisibleObservers(),this.triggeredPlaylists.forEach((t=>{var e;(null==(e=t.triggers)?void 0:e.elementVisible)&&this.setupElementVisibleObserver(t.id,t.triggers.elementVisible,t.triggers.elementVisibleExpectedElement,t.triggers.elementVisibleExpectedSize)}))}setupElementVisibleObserver(t,e,n,i){try{const s=`${t}-${e}`;if(this.elementVisibleObservers.has(s))return;const r=t=>{const n=new IntersectionObserver((t=>{t.forEach((t=>{if(t.isIntersecting,t.intersectionRatio.toFixed(2),t.isIntersecting){const n=window.getComputedStyle(t.target);if("0"===n.opacity||"none"===n.display||"visible"!==n.visibility||"none"===n.pointerEvents)return;this.visibleElements.add(e),this.evaluateAllTriggers()}else this.visibleElements.has(e)&&this.visibleElements.delete(e)}))}),{root:null,rootMargin:"0px",threshold:0});n.observe(t);const i=this.elementVisibleObservers.get(s);i?(i.mutationObserver&&i.mutationObserver.disconnect(),this.elementVisibleObservers.set(s,{observer:n,mutationObserver:null,selector:e})):this.elementVisibleObservers.set(s,{observer:n,mutationObserver:null,selector:e})},a=n||i?Yt(e,n,i):document.querySelector(e);if(a)r(a);else{const t=new MutationObserver((t=>{for(const s of t)"childList"===s.type&&s.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const s=t;if(s.matches(e))(!n&&!i||Xt(s,n,i))&&r(s);else{const t=n||i?Yt(e,n,i):s.querySelector(e);t&&r(t)}}}))}));t.observe(document.body,{childList:!0,subtree:!0}),this.elementVisibleObservers.set(s,{observer:null,mutationObserver:t,selector:e})}}catch(t){}}clearElementVisibleObservers(){this.elementVisibleObservers.forEach((({observer:t,mutationObserver:e})=>{try{t&&t.disconnect(),e&&e.disconnect()}catch(t){console.error("TriggerManager: Error removing element visibility observer:",t)}})),this.elementVisibleObservers.clear()}applyOperators(t,e){return 0!==t.length&&(1===t.length?t[0]:e&&0!==e.length&&e.includes("OR")?t.some((t=>t)):t.every((t=>t)))}async triggerPlaylist(t){this.triggeredPlaylistsSet.add(t);try{const e=window._saltfishPlayer;e&&"function"==typeof e.startPlaylist&&await e.startPlaylist(t,{_triggeredByTriggerManager:!0})}catch(e){this.triggeredPlaylistsSet.delete(t)}}clearTriggeredForNonMatchingUrls(){var t;if(0===this.triggeredPlaylistsSet.size)return;const e=Array.from(this.triggeredPlaylistsSet);e.length,e.map((t=>t.substring(0,8))).join(", ");for(const n of e){const e=this.triggeredPlaylists.find((t=>t.id===n));(null==(t=null==e?void 0:e.triggers)?void 0:t.url)?this.evaluateURLCondition(e.triggers)?n.substring(0,8):this.triggeredPlaylistsSet.delete(n):n.substring(0,8)}}resetTriggeredPlaylists(){this.triggeredPlaylistsSet.clear()}getTriggeredPlaylists(){return Array.from(this.triggeredPlaylistsSet)}markPlaylistAsTriggered(t){this.triggeredPlaylistsSet.has(t)||this.triggeredPlaylistsSet.add(t)}destroy(){this.stopMonitoring(),this.clearElementClickListeners(),this.clearElementVisibleObservers(),this.triggeredPlaylists=[],this.triggeredPlaylistsSet.clear(),this.clickedElements.clear(),this.visibleElements.clear()}}class ie extends Jt{constructor(t){super(t)}subscribeToEvents(){this.eventManager&&this.eventManager.on("playlistStarted",(t=>{this.trackTestParticipation(t.playlist.id)}))}initializeTests(t){dt().setABTests(t)}assignUserToTests(t,e,n){var i,s,r,a;const o=dt(),l=o.abTests||[],c={...e};for(const e of l){const r=e.testType||"percentage";if("linked"===r)continue;if("userList"!==r&&c[e.id])continue;let a=!1;a="userList"===r?!(!0===(null==(s=null==(i=o.user)?void 0:i.userData)?void 0:s.__isAnonymous))&&!0===(null==n?void 0:n[e.id]):this.isUserInTest(t,e),c[e.id]={testId:e.id,assigned:a,assignedAt:Date.now()},e.name}for(const e of l){if("linked"!==(e.testType||"percentage"))continue;const i=l.find((t=>t.id===e.linkedTestId));if(!i){e.linkedTestId,e.name,c[e.id]={testId:e.id,assigned:!1,assignedAt:Date.now()};continue}let s=!1;const d=i.testType||"percentage";"percentage"===d?s=this.isUserInTestWithParentId(t,i.id,i.percentage||0):"userList"===d&&(s=!(!0===(null==(a=null==(r=o.user)?void 0:r.userData)?void 0:a.__isAnonymous))&&!0===(null==n?void 0:n[i.id])),c[e.id]={testId:e.id,assigned:s,assignedAt:Date.now()},e.name,i.name}return o.setABTestAssignments(c),c}isUserInTest(t,e){if(!e.percentage)return!1;const n=`${t}_${e.id}`;let i=0;for(let t=0;t<n.length;t++)i=(i<<5)-i+n.charCodeAt(t),i|=0;return Math.abs(i)%100<e.percentage}isUserInTestWithParentId(t,e,n){if(!n)return!1;const i=`${t}_${e}`;let s=0;for(let t=0;t<i.length;t++)s=(s<<5)-s+i.charCodeAt(t),s|=0;return Math.abs(s)%100<n}getFilteredPlaylists(t){const e=dt(),n=e.abTests||[],i=e.abTestAssignments||{};if(0===n.length)return t;const s=new Set;for(const t of n){const e=i[t.id];e&&e.assigned||(s.add(t.playlistId),t.playlistId,t.name)}const r=t.filter((t=>!s.has(t.id)));return t.length,r.length,r}trackTestParticipation(t){var e;const n=dt(),i=n.abTests||[],s=n.abTestAssignments||{},r=i.find((e=>e.playlistId===t));if(!r)return;const a=s[r.id];a&&a.assigned&&(r.testType,r.name,this.eventManager&&this.eventManager.trigger("abTestParticipation",{testId:r.id,testName:r.name,testType:r.testType||"percentage",playlistId:t,userId:null==(e=n.user)?void 0:e.id,timestamp:Date.now()}))}getAssignmentsForBackend(){return dt().abTestAssignments||{}}isPlaylistAvailable(t){const e=dt(),n=e.abTests||[],i=e.abTestAssignments||{},s=n.find((e=>e.playlistId===t));if(!s)return!0;const r=i[s.id];return r&&r.assigned}getActiveTestInfo(){const t=dt(),e=t.abTests||[],n=t.abTestAssignments||{};return e.map((t=>{var e;return{testId:t.id,testName:t.name,testType:t.testType||"percentage",assigned:(null==(e=n[t.id])?void 0:e.assigned)||!1}}))}}class se{constructor(){e(this,"listeners",new Map)}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){const n=this.listeners.get(t);return!!n&&n.delete(e)}trigger(t,e){const n=this.listeners.get(t);n&&0!==n.size&&("timestamp"in e||(e.timestamp=Date.now()),n.forEach((n=>{try{n(e)}catch(e){console.error(`Error in ${t} event handler:`,e)}})))}removeAllListeners(){this.listeners.clear()}getListenerCount(t){const e=this.listeners.get(t);return e?e.size:0}}class re{async loadManifest(t){const{manifestPath:e,playlistOptions:n,savedProgress:i}=t;try{const t=await this.fetchManifest(e);this.validateManifest(t);const s=this.determineStartStep(t,n,i);return t.id,{manifest:t,startStepId:s}}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw q("[PlaylistLoader] Failed to load manifest:",t),new Error(`Unable to load playlist manifest: ${e}`)}}async fetchManifest(t){try{const e=await fetch(t);if(e.status,e.statusText,!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);return await e.json()}catch(e){throw q("[PlaylistLoader] Fetch/parse failed:",e),q("[PlaylistLoader] Manifest path:",t),new Error(`Failed to fetch manifest from "${t}": ${e instanceof Error?e.message:"Unknown error"}`)}}validateManifest(t){if(!t)throw new Error("Manifest is null or undefined");if("object"!=typeof t)throw new Error("Manifest must be an object");const e=t,n=["id","startStep","steps"];for(const t of n)if(!(t in e))throw new Error(`Manifest missing required field: ${t}`);if(!Array.isArray(e.steps))throw new Error("Manifest steps must be an array");const i=e.steps;if(0===i.length)throw new Error("Manifest must contain at least one step");if(!i.some((t=>"object"==typeof t&&null!==t&&"id"in t&&t.id===e.startStep)))throw new Error(`Start step '${e.startStep}' not found in steps array`);for(const t of i){if("object"!=typeof t||null===t)throw new Error("Each step must be an object");const e=t;if(!e.id)throw new Error("Each step must have an id");if(!e.transitions||!Array.isArray(e.transitions))throw new Error(`Step '${e.id}' must have transitions array`)}}determineStartStep(t,e,n){const i=e.persistence??t.isPersistent??!0,s=t.id,r=!0===e._triggeredByTriggerManager;let a=t.startStep;const o=this.checkPendingNavigation(t);if(o)return o.nextStepId,o.nextStepId;if(e.startNodeId)t.steps.find((t=>t.id===e.startNodeId))?(e.startNodeId,a=e.startNodeId):e.startNodeId;else if(r)a=t.startStep;else if(i&&n&&n[s]){const e=n[s];if("completed"===e.status)a=t.startStep;else{const{isValid:n,ageMs:i}=ut(e);if(n){const n=e.currentStepId||e.lastStepId;n&&t.steps.find((t=>t.id===n))&&(a=n)}else a=t.startStep}}return a}checkPendingNavigation(t){const e=at.getInstance(),n=e.getPendingNavigation();if(!n)return null;if(n.playlistId!==t.id)return n.playlistId,null;const i=Date.now()-n.timestamp;return i>6e4?(e.clearPendingNavigation(),null):this.isURLPathMatch(n.urlPattern)?t.steps.find((t=>t.id===n.nextStepId))?(n.nextStepId,Math.round(i/1e3),e.clearPendingNavigation(),n):(n.nextStepId,e.clearPendingNavigation(),null):(n.urlPattern,e.clearPendingNavigation(),null)}isURLPathMatch(t){if(!t)return!1;const e=window.location.href,n=window.location.pathname,i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*"),s=new RegExp(i);return s.test(e)||s.test(n)}}class ae extends Jt{constructor(t,n){super(t),e(this,"playlistLoader"),e(this,"storageManager"),this.playlistLoader=new re,this.storageManager=n||at.getInstance()}subscribeToEvents(){this.eventManager&&(this.eventManager.on("playlistStarted",(t=>{t.playlist.id,this.updateWatchedPlaylistStatus(t.playlist.id,"in_progress")})),this.eventManager.on("playlistEnded",(t=>{t.playlist.id,this.updateWatchedPlaylistStatus(t.playlist.id,"completed").catch((e=>{console.error(`PlaylistManager: Error in updateWatchedPlaylistStatus for playlist ${t.playlist.id}:`,e)}))})),this.eventManager.on("playlistDismissed",(t=>{t.playlist.id,this.updateWatchedPlaylistStatus(t.playlist.id,"dismissed")})),this.eventManager.on("stepStarted",(t=>{t.step.id,this.updateWatchedPlaylistStatus(t.playlist.id,"in_progress",t.step.id)})))}async updateWatchedPlaylistStatus(t,e,n){var i,s,r,a,o;const l=dt();l.updateWatchedPlaylist(t,e,n);const c=null==(s=null==(i=l.userData)?void 0:i.watchedPlaylists)?void 0:s[t];if(!(null==(r=null==l?void 0:l.config)?void 0:r.token)||!(null==(a=null==l?void 0:l.user)?void 0:a.id)||(null==(o=null==l?void 0:l.user)?void 0:o.__isAnonymous))return void(c&&this.persistAnonymousWatchedPlaylist(t,c));const d=`https://player.saltfish.ai/clients/${l.config.token}/users/${l.user.id}/playlists/${t}`;try{const t=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:e,currentStepId:(null==c?void 0:c.currentStepId)??null})});if(!t.ok)throw new Error(`Failed to update watched playlist status: ${t.statusText} (${t.status})`)}catch(e){console.error(`PlaylistManager: Error updating watched playlist status for ${t}:`,e)}}persistAnonymousWatchedPlaylist(t,e){if("undefined"==typeof window)return;const n=this.storageManager.getAnonymousUserData()||{userId:"anonymous",userData:{},watchedPlaylists:{},timestamp:Date.now()};n.watchedPlaylists||(n.watchedPlaylists={}),n.watchedPlaylists[t]=e,n.timestamp=Date.now(),this.storageManager.setAnonymousUserData(n),e.status}async load(t,e){var n;try{const i=dt();if(!i)throw new Error("Store not available");const s=(null==(n=i.userData)?void 0:n.watchedPlaylists)||i.progress,r=await this.playlistLoader.loadManifest({manifestPath:t,playlistOptions:e,savedProgress:s}),{manifest:a,startStepId:o}=r,l=a.steps.find((t=>t.id===o));i.setManifest(a,o),l&&i.sendStateMachineEvent({type:"MANIFEST_LOADED",step:l})}catch(t){const e=dt(),n=t instanceof Error?t:new Error("Unknown error loading manifest");e?e.setError(n):console.error("[PlaylistManager] Cannot set error: Store not available",n)}}destroy(){this.eventManager&&(this.eventManager=null)}}class oe{constructor(t){e(this,"button"),e(this,"playerElement"),this.playerElement=t,this.button=document.createElement("button"),this.button.className="sf-player__minimize-button",this.button.innerHTML=Ot(20),this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(dt().isMinimized)}handleClick(){const t=dt(),e=!t.isMinimized;e?t.minimize():t.maximize(),e?this.minimize():this.maximize()}minimize(){this.button.innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'}maximize(){this.button.innerHTML=Ot(20)}updateVisibility(t){t?this.button.classList.add("sf-hidden"):this.button.classList.remove("sf-hidden")}destroy(){this.button.removeEventListener("click",this.handleClick.bind(this)),this.button.remove()}}class le{constructor(t,n){e(this,"playButton"),e(this,"container"),e(this,"videoManager",null),this.container=t,this.videoManager=n||null,this.createButton()}createButton(){this.playButton=document.createElement("button"),this.playButton.className="sf-controls-container__play-button",this.playButton.innerHTML='<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 5v14l11-7z" fill="currentColor"/></svg>',this.playButton.addEventListener("click",this.handlePlayClick.bind(this)),this.container.appendChild(this.playButton)}handlePlayClick(t){t&&t.stopPropagation();const e=dt();if("autoplayBlocked"===e.currentState)if(this.videoManager){this.videoManager.markUserInteraction(),this.videoManager.setMuted(!1);const t=this.videoManager.getVideoElement();t&&(t.loop=!1,t.currentTime=0)}else{const t=this.playButton.closest(".sf-player");if(t){const e=t.querySelector(".sf-video-container__video");e&&(e.muted=!1,e.loop=!1,e.currentTime=0)}}else this.videoManager?this.videoManager.markUserInteraction():console.warn("PlayPauseButton: VideoManager not available, falling back to store play");"paused"!==e.currentState&&"waitingForInteraction"!==e.currentState&&"autoplayBlocked"!==e.currentState||e.play()}destroy(){this.playButton.removeEventListener("click",this.handlePlayClick.bind(this)),this.playButton.remove()}}class ce{constructor(t){e(this,"button"),e(this,"playerElement"),this.playerElement=t,this.button=document.createElement("button"),this.button.className="sf-player__exit-button",this.button.innerHTML='<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>',this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(dt().isMinimized)}handleClick(t){t.stopPropagation(),dt().sendStateMachineEvent({type:"EXIT"})}updateVisibility(t){t?this.button.classList.remove("sf-hidden"):this.button.classList.add("sf-hidden")}destroy(){this.button.removeEventListener("click",this.handleClick.bind(this)),this.button.remove()}}class de{constructor(t,n={}){e(this,"errorOverlay"),e(this,"container"),e(this,"options"),e(this,"isVisible",!1),this.container=t,this.options=n,this.createErrorDisplay()}createErrorDisplay(){this.errorOverlay=document.createElement("div"),this.errorOverlay.className="sf-error-display",this.errorOverlay.classList.add("sf-hidden");const t=document.createElement("div");t.className="sf-error-display__content";const e=document.createElement("p");e.className=st,e.textContent=this.options.message||"Unable to load content",t.appendChild(e),this.errorOverlay.appendChild(t),this.container.appendChild(this.errorOverlay)}show(t){t&&this.updateOptions(t),this.errorOverlay.classList.remove("sf-hidden"),this.isVisible=!0,requestAnimationFrame((()=>{this.errorOverlay.classList.add(it)}))}hide(){this.isVisible&&(this.errorOverlay.classList.remove(it),setTimeout((()=>{this.errorOverlay.classList.add("sf-hidden"),this.isVisible=!1}),300))}updateOptions(t){if(this.options={...this.options,...t},void 0!==t.message){const e=this.errorOverlay.querySelector(`.${st}`);e&&(e.textContent=t.message||"Unable to load content")}}static getErrorMessage(t,e){const n=(t instanceof Error?t.message:t).toLowerCase();return"video"===e||n.includes("video")||n.includes("cannot load video")?n.includes("no video url")||n.includes("video url provided")?"This step doesn't have a video to play":"Unable to load video content":"network"===e||n.includes("network")||n.includes("fetch")?"Connection issue detected":"playlist"===e||n.includes("playlist")?"Unable to load playlist":"initialization"===e||n.includes("token")||n.includes("initialize")?"Setup issue detected":"Unable to load content"}isShowing(){return this.isVisible}destroy(){this.errorOverlay&&this.errorOverlay.remove()}}class he{constructor(t){e(this,"container"),e(this,"spinnerElement",null),this.container=t}show(){this.spinnerElement?this.spinnerElement.classList.remove("sf-hidden"):(this.spinnerElement=document.createElement("div"),this.spinnerElement.className="sf-loading-spinner",this.spinnerElement.innerHTML='\n <div class="sf-loading-spinner__content">\n <div class="sf-loading-spinner__icon"><svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><g transform="translate(10, 10) scale(0.656)"><g clip-path="url(#saltfish-clip)"><path d="M61.0002 30.1906C61.0002 46.8644 47.4834 60.3812 30.8097 60.3812C14.136 60.3812 27.1659 46.8644 27.1659 30.1906C27.1659 13.5168 14.136 0 30.8097 0C47.4834 0 61.0002 13.5168 61.0002 30.1906Z" fill="black" fill-opacity="0.9"/><path d="M24.13 29.8618C24.13 40.3565 15.6978 48.8642 5.29602 48.8642C-5.10576 48.8642 3.02294 40.3565 3.02294 29.8618C3.02294 19.3671 -5.10576 10.8594 5.29602 10.8594C15.6978 10.8594 24.13 19.3671 24.13 29.8618Z" fill="black" fill-opacity="0.9"/></g><defs><clipPath id="saltfish-clip"><rect width="61" height="61" fill="white"/></clipPath></defs></g><circle cx="30" cy="30" r="28" stroke="black" stroke-width="2" fill="none" stroke-linecap="round" stroke-dasharray="8 6" stroke-opacity="0.3"><animateTransform attributeName="transform" type="rotate" values="0 30 30;360 30 30" dur="2s" repeatCount="indefinite"/></circle></svg></div>\n <div class="sf-loading-spinner__text">Loading playlist...</div>\n </div>\n ',this.container.appendChild(this.spinnerElement))}hide(){this.spinnerElement&&this.spinnerElement.classList.add("sf-hidden")}updateMessage(t){if(this.spinnerElement){const e=this.spinnerElement.querySelector(".sf-loading-spinner__text");e&&(e.textContent=t)}}destroy(){this.spinnerElement&&(this.spinnerElement.remove(),this.spinnerElement=null)}}class ue{constructor(t){e(this,"shadowDOMManager"),e(this,"playerRoot",null),e(this,"playerElement",null),e(this,"minimizeButton",null),e(this,"exitButton",null),e(this,"playPauseButton",null),e(this,"errorDisplay",null),e(this,"loadingSpinner",null),e(this,"compactLabel",null),e(this,"playbackButtonsVisible",!1),e(this,"playButton",null),e(this,"centerPlayButton",null),e(this,"videoManager",null),e(this,"storeUnsubscribe",null),this.shadowDOMManager=t}createPlayerUI(t,e,n){if(this.videoManager=t,this.playerElement&&this.reset(),!this.playerRoot&&(this.shadowDOMManager.create(),this.playerRoot=this.shadowDOMManager.getRootElement(),!this.playerRoot))return void console.error("Failed to create player root element");this.playerElement=this.createPlayerElement(this.playerRoot),this.minimizeButton=new oe(this.playerElement),this.exitButton=new ce(this.playerElement),t.create(this.playerElement);const i=this.createControlsContainer(this.playerElement);this.playPauseButton=new le(i,t),this.createSaltfishLogo(this.playerElement),this.createAiBadge(this.playerElement),this.setupVideoContainerClickHandler(),e.create(),n.create(this.playerElement),this.initializeButtonManagement();const s=dt();this.handleMinimizeStateChange(s.isMinimized)}setupVideoContainerClickHandler(){var t;const e=null==(t=this.playerElement)?void 0:t.querySelector(".sf-video-container");e&&e.addEventListener("click",(t=>{var e;const n=dt();if(n.isMinimized)return t.stopPropagation(),void this.handleMinimizeClick();const i=t.target;if("BUTTON"===i.tagName||i.closest("button")||i.closest(".sf-controls-container"))return;const s=null==(e=this.playerElement)?void 0:e.classList.contains("sf-player--compact");"playing"===n.currentState?n.pause():!s||"idleMode"!==n.currentState&&"autoplayBlocked"!==n.currentState&&"paused"!==n.currentState||(this.handleAutoplayFallbackInteraction("compact bubble click"),n.play())}))}updatePosition(){var t;if(!this.playerRoot||!this.playerElement)return void console.warn("UIManager: updatePosition called but playerRoot or playerElement is null",{playerRoot:!!this.playerRoot,playerElement:!!this.playerElement});const e=dt();let n=(null==(t=e.playlistOptions)?void 0:t.position)||"bottom-right";if(e.currentStepId&&e.manifest){const t=e.manifest.steps.find((t=>t.id===e.currentStepId));(null==t?void 0:t.position)&&(n=t.position)}"bottom-left"!==n&&"bottom-right"!==n&&(console.warn(`UIManager: Invalid position "${n}", defaulting to bottom-right`),n="bottom-right"),this.playerRoot.classList.remove("sf-player-root--bottom-left","sf-player-root--bottom-right"),"bottom-left"===n?this.playerRoot.classList.add("sf-player-root--bottom-left"):this.playerRoot.classList.add("sf-player-root--bottom-right"),e.isMinimized?this.playerElement.classList.add(et):this.playerElement.classList.remove(et)}handleMinimizeClick(){if(!this.playerElement)return;const t=dt(),e=!t.isMinimized;e?t.minimize():t.maximize(),e?this.minimizeButton.minimize():this.minimizeButton.maximize()}handleMinimizeStateChange(t){this.exitButton&&this.exitButton.updateVisibility(t),this.minimizeButton&&this.minimizeButton.updateVisibility(t)}getPlayerElement(){return this.playerElement}getPlayerRoot(){return this.playerRoot}showError(t,e,n){if(!this.playerElement)return void console.warn("UIManager: Cannot show error display - player element not available");const i=de.getErrorMessage(t,e);this.errorDisplay||(this.errorDisplay=new de(this.playerElement,{message:i,...n})),this.errorDisplay.show({message:i,...n})}hideError(){this.errorDisplay&&this.errorDisplay.hide()}isErrorDisplayVisible(){var t;return(null==(t=this.errorDisplay)?void 0:t.isShowing())||!1}showLoading(t){this.playerElement?(this.loadingSpinner||(this.loadingSpinner=new he(this.playerElement)),this.loadingSpinner.show(),t&&this.loadingSpinner.updateMessage(t)):console.warn("UIManager: Cannot show loading spinner - player element not available")}hideLoading(){this.loadingSpinner&&this.loadingSpinner.hide()}updateLoadingMessage(t){this.loadingSpinner&&this.loadingSpinner.updateMessage(t)}showPlayer(){this.playerElement&&this.playerElement.classList.add("sf-player--visible")}createPlayerElement(t){const e=document.createElement("div");return e.className="sf-player",t.appendChild(e),e}createControlsContainer(t){const e=document.createElement("div");return e.className="sf-controls-container",t.appendChild(e),e}createSaltfishLogo(t){var e;if(!1===(null==(e=dt().config)?void 0:e.showLogo))return;const n=document.createElement("div");n.className="sf-player__bottom-bar",t.appendChild(n);const i=document.createElement("div");i.className="sf-player__logo",i.innerHTML='\n <svg viewBox="0 0 59 14" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M20.5011 11.1967C19.8292 11.1967 19.2433 11.0697 18.7434 10.8156C18.2435 10.5616 17.8461 10.2133 17.5511 9.77082C17.2643 9.32012 17.0963 8.79977 17.0471 8.20976L18.1534 8.13601C18.2108 8.57032 18.3378 8.93907 18.5345 9.24227C18.7311 9.54547 18.9933 9.77492 19.3211 9.93061C19.6571 10.0863 20.0586 10.1642 20.5257 10.1642C20.9355 10.1642 21.2837 10.1109 21.5705 10.0044C21.8573 9.89783 22.0745 9.74214 22.222 9.53727C22.3777 9.33241 22.4555 9.08248 22.4555 8.78747C22.4555 8.51705 22.39 8.27941 22.2589 8.07455C22.136 7.86149 21.8942 7.66892 21.5337 7.49683C21.1813 7.31655 20.6568 7.14037 19.9603 6.96829C19.2884 6.7962 18.7516 6.60773 18.3501 6.40286C17.9567 6.198 17.6699 5.94807 17.4896 5.65306C17.3176 5.35806 17.2315 4.9934 17.2315 4.55909C17.2315 4.06742 17.3462 3.63721 17.5757 3.26845C17.8133 2.8915 18.1493 2.6006 18.5836 2.39573C19.0179 2.18267 19.5342 2.07615 20.1324 2.07615C20.7716 2.07615 21.3206 2.19906 21.7795 2.4449C22.2384 2.68254 22.603 3.01032 22.8735 3.42824C23.1439 3.84617 23.3119 4.32145 23.3774 4.85409L22.2712 4.92785C22.222 4.57548 22.1073 4.26409 21.927 3.99367C21.7549 3.71505 21.5173 3.4979 21.2141 3.3422C20.9109 3.18651 20.5421 3.10866 20.1078 3.10866C19.567 3.10866 19.1368 3.23977 18.8172 3.502C18.4976 3.75603 18.3378 4.092 18.3378 4.50992C18.3378 4.78034 18.3992 5.00569 18.5222 5.18597C18.6533 5.35806 18.8827 5.51376 19.2105 5.65306C19.5383 5.78417 20.0095 5.92758 20.6241 6.08328C21.3534 6.26356 21.9311 6.48071 22.3572 6.73474C22.7915 6.98058 23.0988 7.26739 23.2791 7.59517C23.4676 7.92295 23.5618 8.2958 23.5618 8.71372C23.5618 9.22178 23.4307 9.66429 23.1685 10.0412C22.9062 10.41 22.5457 10.6968 22.0868 10.9017C21.6279 11.0983 21.0993 11.1967 20.5011 11.1967ZM26.7873 11.1475C26.1154 11.1475 25.5787 10.9918 25.1771 10.6804C24.7838 10.369 24.5871 9.93471 24.5871 9.37748C24.5871 8.82025 24.751 8.38184 25.0788 8.06226C25.4066 7.74267 25.9269 7.51732 26.6398 7.38621L28.9507 6.95599C28.9507 6.40696 28.8196 5.99723 28.5574 5.72681C28.3033 5.45639 27.9182 5.32118 27.4019 5.32118C26.9512 5.32118 26.5948 5.42362 26.3325 5.62848C26.0703 5.82515 25.89 6.11196 25.7917 6.48891L24.6977 6.40286C24.8207 5.78827 25.1157 5.2925 25.5827 4.91555C26.058 4.53041 26.6644 4.33784 27.4019 4.33784C28.2378 4.33784 28.877 4.57548 29.3195 5.05076C29.762 5.51785 29.9832 6.16522 29.9832 6.99287V9.68478C29.9832 9.83228 30.0078 9.93881 30.057 10.0044C30.1143 10.0617 30.2045 10.0904 30.3274 10.0904H30.5855V11C30.5527 11.0082 30.4995 11.0123 30.4257 11.0123C30.352 11.0205 30.2741 11.0246 30.1922 11.0246C29.8972 11.0246 29.6554 10.9795 29.467 10.8894C29.2867 10.791 29.1556 10.6435 29.0736 10.4469C28.9917 10.242 28.9507 9.97568 28.9507 9.6479L29.0736 9.67248C29.0163 9.9511 28.877 10.2051 28.6557 10.4346C28.4344 10.6558 28.1599 10.832 27.8322 10.9631C27.5044 11.086 27.1561 11.1475 26.7873 11.1475ZM26.8857 10.2379C27.32 10.2379 27.6887 10.156 27.9919 9.99207C28.3033 9.81999 28.541 9.59054 28.7049 9.30373C28.8688 9.00873 28.9507 8.68095 28.9507 8.32039V7.8533L26.8365 8.24663C26.394 8.32858 26.0867 8.4556 25.9146 8.62768C25.7507 8.79157 25.6688 9.00873 25.6688 9.27915C25.6688 9.58234 25.7753 9.81999 25.9884 9.99207C26.2096 10.156 26.5087 10.2379 26.8857 10.2379ZM32.6507 11C32.2738 11 31.9665 10.9017 31.7288 10.705C31.4912 10.5083 31.3724 10.1969 31.3724 9.77082V2.27281H32.4049V9.68478C32.4049 9.81589 32.4377 9.91832 32.5032 9.99207C32.577 10.0576 32.6794 10.0904 32.8105 10.0904H33.3759V11H32.6507ZM36.3546 11C35.7646 11 35.3262 10.8648 35.0394 10.5944C34.7608 10.324 34.6215 9.90193 34.6215 9.32831V2.96116H35.654V9.30373C35.654 9.59873 35.7195 9.8036 35.8506 9.91832C35.9817 10.033 36.1825 10.0904 36.4529 10.0904H37.3871V11H36.3546ZM33.6627 5.39493V4.48534H37.3871V5.39493H33.6627ZM38.6952 11V3.89533C38.6952 3.41186 38.8345 3.02261 39.1132 2.72761C39.3918 2.42441 39.8261 2.27281 40.4161 2.27281H41.4486V3.18241H40.4898C40.2358 3.18241 40.0432 3.25206 39.9121 3.39137C39.7892 3.53068 39.7277 3.72325 39.7277 3.96908V11H38.6952ZM37.8102 5.39493V4.48534H41.3626V5.39493H37.8102ZM42.7147 11V4.48534H43.7472V11H42.7147ZM42.6901 3.46512V2.26052H43.7717V3.46512H42.6901ZM47.6594 11.1475C47.0776 11.1475 46.5818 11.0533 46.1721 10.8648C45.7706 10.6763 45.4551 10.4182 45.2256 10.0904C45.0044 9.75443 44.8774 9.37338 44.8446 8.94727L45.9263 8.87352C45.9918 9.26685 46.1598 9.58234 46.4302 9.81999C46.7007 10.0494 47.1104 10.1642 47.6594 10.1642C48.1019 10.1642 48.4543 10.0945 48.7165 9.9552C48.9869 9.80769 49.1221 9.57415 49.1221 9.25456C49.1221 9.08248 49.0812 8.93907 48.9992 8.82435C48.9173 8.70963 48.7575 8.61129 48.5198 8.52935C48.2822 8.43921 47.9298 8.35316 47.4627 8.27122C46.84 8.15649 46.3483 8.01719 45.9877 7.8533C45.6354 7.68121 45.3813 7.47225 45.2256 7.22641C45.0781 6.97238 45.0044 6.67328 45.0044 6.32911C45.0044 5.7473 45.2174 5.27202 45.6436 4.90326C46.0697 4.52631 46.6761 4.33784 47.4627 4.33784C47.9954 4.33784 48.442 4.43617 48.8026 4.63284C49.1713 4.82132 49.4581 5.07535 49.663 5.39493C49.876 5.70633 50.0153 6.0505 50.0809 6.42745L48.9992 6.5012C48.9501 6.27175 48.8599 6.07098 48.7288 5.8989C48.5977 5.71862 48.4256 5.57931 48.2125 5.48098C47.9995 5.37445 47.7455 5.32118 47.4505 5.32118C46.9834 5.32118 46.6392 5.41132 46.4179 5.5916C46.1967 5.77188 46.0861 6.00133 46.0861 6.27994C46.0861 6.493 46.1352 6.66919 46.2336 6.80849C46.3401 6.93961 46.5081 7.05023 46.7375 7.14037C46.967 7.22232 47.2743 7.29607 47.6594 7.36162C48.3232 7.47635 48.8394 7.61565 49.2082 7.77955C49.5769 7.94344 49.8351 8.1442 49.9826 8.38184C50.1301 8.61949 50.2038 8.91039 50.2038 9.25456C50.2038 9.6561 50.0891 10.0003 49.8596 10.2871C49.6384 10.5657 49.3352 10.7787 48.9501 10.9262C48.5731 11.0738 48.1429 11.1475 47.6594 11.1475ZM51.3058 11V2.27281H52.3383V5.92348L52.2154 5.8989C52.2973 5.53834 52.4366 5.24334 52.6333 5.01389C52.8299 4.78444 53.0717 4.61645 53.3585 4.50992C53.6453 4.3952 53.9608 4.33784 54.305 4.33784C54.7721 4.33784 55.1654 4.44437 55.485 4.65743C55.8128 4.86229 56.0586 5.1532 56.2225 5.53014C56.3946 5.8989 56.4806 6.32501 56.4806 6.80849V11H55.4481V7.1035C55.4481 6.47252 55.3334 6.00543 55.1039 5.70223C54.8827 5.39903 54.5426 5.24743 54.0837 5.24743C53.5593 5.24743 53.1372 5.40723 52.8177 5.72681C52.4981 6.0464 52.3383 6.50939 52.3383 7.11579V11H51.3058Z" fill="white"/>\n <rect width="13.1858" height="13.1858" rx="0.670462" fill="white"/>\n <path d="M10.2634 6.59634C10.2634 8.62107 8.62202 10.2624 6.59729 10.2624C4.57256 10.2624 6.15483 8.62107 6.15483 6.59634C6.15483 4.57161 4.57256 2.93024 6.59729 2.93024C8.62202 2.93024 10.2634 4.57161 10.2634 6.59634Z" fill="black"/>\n <path d="M5.78564 6.55629C5.78564 7.83069 4.76169 8.86379 3.49858 8.86379C2.23547 8.86379 3.22255 7.83069 3.22255 6.55629C3.22255 5.28189 2.23547 4.24878 3.49858 4.24878C4.76169 4.24878 5.78564 5.28189 5.78564 6.55629Z" fill="black"/>\n </svg>\n ',t.appendChild(i),i.addEventListener("click",(t=>{var e;t.stopPropagation();const n=dt();"playing"===n.currentState&&n.pause();const i=null==(e=n.config)?void 0:e.token;i?window.open(`https://www.saltfish.ai/?utm_source=player&utm_medium=logo&clientId=${i}`,"_blank"):(console.warn("UIManager: No token available, falling back to saltfish.ai homepage"),window.open("https://www.saltfish.ai/?utm_source=player&utm_medium=logo","_blank"))}))}createAiBadge(t){const e="Contains AI-generated content";t.setAttribute("data-ai-generated","true");const n=document.createElement("div");n.className="sf-player__ai-badge",n.setAttribute("role","img"),n.setAttribute("aria-label",e),n.innerHTML='\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">\n <circle cx="12" cy="12" r="11" fill="#ffffff" stroke="rgba(0, 0, 0, 0.4)" stroke-width="1"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M9.4 8 L11.5 8 L14 16 L11.7 16 L11.28 14.55 L9.62 14.55 L9.2 16 L6.9 16 Z M10.45 10.2 L11.15 12.85 L9.75 12.85 Z" fill="#1d1d1b"/>\n <path d="M14.8 8h2.3v8h-2.3z" fill="#1d1d1b"/>\n </svg>\n ';const i=document.createElement("span");let s;i.className="sf-player__ai-badge-label",i.textContent=e,i.setAttribute("aria-hidden","true"),n.appendChild(i),n.addEventListener("click",(t=>{t.stopPropagation();const e=i.classList.toggle(nt);window.clearTimeout(s),e&&(s=window.setTimeout((()=>{i.classList.remove(nt)}),3e3))})),t.appendChild(n)}initializeButtonManagement(){this.playerElement&&this.videoManager?(this.storeUnsubscribe=ct.subscribe((t=>{this.updatePlayPauseButton(t.currentState)})),this.playButton=this.playerElement.querySelector(".sf-controls-container__play-button"),this.centerPlayButton=this.playerElement.querySelector(".sf-player__center-play-button"),this.centerPlayButton||this.createCenterPlayButton(),this.playButton||console.error("UIManager: Failed to find play button during initialization"),this.centerPlayButton):console.error("UIManager: Cannot initialize button management - missing player element or video manager")}displayPlaybackButtons(t){this.playbackButtonsVisible!==t&&(this.playbackButtonsVisible=t)}updatePlayPauseButton(t){this.playButton&&this.playButton.classList.add("sf-hidden"),!this.centerPlayButton&&this.playerElement&&(this.centerPlayButton=this.playerElement.querySelector(".sf-player__center-play-button"),this.centerPlayButton||this.createCenterPlayButton()),this.centerPlayButton&&("playing"===t||"completed"===t?(this.centerPlayButton.classList.remove("sf-player__center-play-button--visible"),this.centerPlayButton.classList.remove("sf-player__center-play-button--prominent")):(this.centerPlayButton.classList.add("sf-player__center-play-button--visible"),"autoplayBlocked"===t||"idleMode"===t?this.centerPlayButton.classList.add("sf-player__center-play-button--prominent"):this.centerPlayButton.classList.remove("sf-player__center-play-button--prominent")))}handleAutoplayFallbackInteraction(t){var e;const n=dt();if("autoplayBlocked"===n.currentState||"idleMode"===n.currentState)if(n.currentState,this.videoManager){this.videoManager.markUserInteraction(),this.videoManager.setMuted(!1);const t=this.videoManager.getVideoElement();t&&(t.loop=!1,t.currentTime=0)}else{const t=null==(e=this.playerElement)?void 0:e.querySelector(".sf-video-container__video");t&&(t.muted=!1,t.loop=!1,t.currentTime=0)}else this.videoManager&&this.videoManager.markUserInteraction()}createCenterPlayButton(){this.playerElement&&(this.centerPlayButton=document.createElement("button"),this.centerPlayButton.className="sf-player__center-play-button",this.centerPlayButton.innerHTML='\n <svg class="sf-player__center-play-button__play-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M8 5v14l11-7z" fill="currentColor"/>\n </svg>\n <svg class="sf-player__center-play-button__pause-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z" fill="currentColor"/>\n </svg>\n <svg class="sf-player__center-play-button__replay-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z" fill="currentColor"/>\n </svg>\n ',this.playerElement.appendChild(this.centerPlayButton),this.centerPlayButton.addEventListener("click",(t=>{t.stopPropagation(),t.preventDefault();const e=dt();this.handleAutoplayFallbackInteraction("center play button"),"paused"===e.currentState||"waitingForInteraction"===e.currentState||"completedWaitingForInteraction"===e.currentState||"autoplayBlocked"===e.currentState||"idleMode"===e.currentState||"error"===e.currentState?e.play():"playing"===e.currentState&&e.pause()})))}showCompactLabel(t){var e;if(!this.playerRoot||!t)return;this.hideCompactLabel();const n=dt();let i=(null==(e=n.playlistOptions)?void 0:e.position)||"bottom-right";if(n.currentStepId&&n.manifest){const t=n.manifest.steps.find((t=>t.id===n.currentStepId));(null==t?void 0:t.position)&&(i=t.position)}const s="bottom-right"===i?"sf-compact-label--left":"sf-compact-label--right";this.compactLabel=document.createElement("div"),this.compactLabel.className=`sf-compact-label ${s}`,this.compactLabel.textContent=t,this.compactLabel.classList.add("sf-compact-label--clickable"),this.compactLabel.addEventListener("click",(t=>{t.stopPropagation(),t.preventDefault();const e=dt();this.handleAutoplayFallbackInteraction("compact label"),"paused"!==e.currentState&&"waitingForInteraction"!==e.currentState&&"completedWaitingForInteraction"!==e.currentState&&"autoplayBlocked"!==e.currentState&&"idleMode"!==e.currentState&&"error"!==e.currentState||e.play()})),this.playerRoot.appendChild(this.compactLabel)}hideCompactLabel(){this.compactLabel&&this.compactLabel.parentNode&&(this.compactLabel.parentNode.removeChild(this.compactLabel),this.compactLabel=null)}reset(){this.minimizeButton&&(this.minimizeButton.destroy(),this.minimizeButton=null),this.exitButton&&(this.exitButton.destroy(),this.exitButton=null),this.playPauseButton&&(this.playPauseButton.destroy(),this.playPauseButton=null),this.errorDisplay&&(this.errorDisplay.destroy(),this.errorDisplay=null),this.loadingSpinner&&(this.loadingSpinner.destroy(),this.loadingSpinner=null),this.hideCompactLabel(),this.playerElement&&this.playerElement.parentNode&&this.playerElement.parentNode.removeChild(this.playerElement),this.playerRoot=null,this.playerElement=null}enablePlayButtonProminent(){this.centerPlayButton&&this.centerPlayButton.classList.add("sf-player__center-play-button--prominent")}disablePlayButtonProminent(){this.centerPlayButton&&this.centerPlayButton.classList.remove("sf-player__center-play-button--prominent")}destroy(){this.minimizeButton&&(this.minimizeButton.destroy(),this.minimizeButton=null),this.exitButton&&(this.exitButton.destroy(),this.exitButton=null),this.playPauseButton&&(this.playPauseButton.destroy(),this.playPauseButton=null),this.errorDisplay&&(this.errorDisplay.destroy(),this.errorDisplay=null),this.loadingSpinner&&(this.loadingSpinner.destroy(),this.loadingSpinner=null),this.storeUnsubscribe&&(this.storeUnsubscribe(),this.storeUnsubscribe=null),this.playbackButtonsVisible=!1,this.playButton=null,this.centerPlayButton=null,this.videoManager=null,this.shadowDOMManager.remove(),this.playerRoot=null,this.playerElement=null}}const pe=class t{constructor(t){e(this,"currentStepId",null),e(this,"stepTimeoutId",null),e(this,"destroyCallback",null),this.destroyCallback=t}update(t){const{currentStepId:e,currentState:n}=t;if(this.currentStepId,"playing"!==n&&"waitingForInteraction"!==n&&"paused"!==n&&"autoplayBlocked"!==n)return this.stepTimeoutId,void this.clearStepTimeout();const i=e!==this.currentStepId,s=null===this.stepTimeoutId;(i||s)&&(i&&this.currentStepId,this.setStepTimeout(e))}setStepTimeout(e){this.clearStepTimeout(),e&&(this.currentStepId=e,this.stepTimeoutId=window.setTimeout((()=>{this.destroyPlayer()}),t.STEP_TIMEOUT_MS))}clearStepTimeout(){null!==this.stepTimeoutId&&(this.currentStepId,window.clearTimeout(this.stepTimeoutId),this.stepTimeoutId=null)}setDestroyCallback(t){this.destroyCallback=t}destroyPlayer(){if(this.destroyCallback)try{this.destroyCallback()}catch(t){}}reset(){this.clearStepTimeout(),this.currentStepId=null}destroy(){this.clearStepTimeout(),this.currentStepId=null,this.destroyCallback=null}};e(pe,"STEP_TIMEOUT_MS",12e4);let ge=pe;class me{createManagers(){const t=at.getInstance(),e=new te(t),n=new Ct,i=new Ut,s=new se,r=new Qt(s),a=new ae(s,t),o=new ie(s),l=new qt,c=new Kt,d=new ee,h=new ne,u=new ge((()=>{}));return d.setTriggerManager(h),{shadowDOMManager:n,videoManager:i,cursorManager:l,interactionManager:c,analyticsManager:r,sessionManager:e,transitionManager:d,triggerManager:h,abTestManager:o,eventManager:s,playlistManager:a,stepTimeoutManager:u,uiManager:new ue(n),storageManager:t}}resetManagers(t){try{t.videoManager.reset&&t.videoManager.reset(),t.cursorManager.reset&&t.cursorManager.reset(),t.interactionManager.reset&&t.interactionManager.reset(),t.transitionManager.reset&&t.transitionManager.reset(),t.uiManager.reset&&t.uiManager.reset(),t.stepTimeoutManager.reset&&t.stepTimeoutManager.reset()}catch(t){console.error("ManagerFactory: Error resetting managers:",t)}}destroyManagers(t){try{t.transitionManager.destroy(),t.triggerManager.destroy(),t.videoManager.destroy(),t.cursorManager.destroy(),t.interactionManager.destroy(),t.analyticsManager.destroy(),t.sessionManager.destroy(),t.playlistManager.destroy(),t.stepTimeoutManager.destroy(),t.uiManager.destroy()}catch(t){console.error("ManagerFactory: Error destroying managers:",t)}}}const fe=class t{constructor(){if(e(this,"playerInitializationService"),e(this,"userManagementService"),e(this,"playlistOrchestrator"),e(this,"stateMachineActionHandler"),e(this,"managerOrchestrator"),e(this,"managerFactory"),e(this,"isInitialized",!1),e(this,"initializationPromise",null),t.instance)throw new Error("SaltfishPlayer is a singleton. Use getInstance()");this.managerFactory=new me;const n=this.managerFactory.createManagers();this.playerInitializationService=new vt(n),this.userManagementService=new wt(n),this.playlistOrchestrator=new Et(n),this.stateMachineActionHandler=new Mt(n),this.managerOrchestrator=new Pt(n),this.userManagementService.setPlayerInitializationService(this.playerInitializationService),this.playerInitializationService.setUserManagementService(this.userManagementService),this.playerInitializationService.setPlaylistOrchestrator(this.playlistOrchestrator),this.playlistOrchestrator.setUserManagementService(this.userManagementService),this.playlistOrchestrator.setManagerOrchestrator(this.managerOrchestrator),this.playlistOrchestrator.setPlayerInitializationService(this.playerInitializationService),this.playlistOrchestrator.setStateMachineActionHandler(this.stateMachineActionHandler),this.stateMachineActionHandler.setDestroyCallback((()=>this.destroy())),n.stepTimeoutManager.setDestroyCallback((()=>this.destroy())),ct.subscribe((()=>this.managerOrchestrator.handleStoreChanges())),this.stateMachineActionHandler.registerStateMachineActions()}static getInstance(){return t.instance||(t.instance=new t),t.instance}getSessionId(){return this.managerOrchestrator.getManagers().sessionManager.getSessionId()}getRunId(){return this.managerOrchestrator.getManagers().sessionManager.getCurrentRunId()}async initialize(t){if(!this.isInitialized)return this.initializationPromise||(this.initializationPromise=(async()=>{try{await this.playerInitializationService.initialize(t),this.isInitialized=!0,this.managerOrchestrator.setInitialized(!0),"undefined"!=typeof window&&(window._saltfishPlayer=this,window._cursorManager=this.getManagers().cursorManager)}catch(t){throw this.initializationPromise=null,t}})()),this.initializationPromise;console.warn("Saltfish playlist Player is already initialized")}async identifyUser(t,e){this.initializationPromise&&await this.initializationPromise,this.userManagementService.identifyUser(t,e)}async identifyAnonymous(t){this.initializationPromise&&await this.initializationPromise,await this.userManagementService.identifyAnonymous(t)}async startPlaylist(t,e){await this.playlistOrchestrator.startPlaylist(t,e)}resetPlaylist(){this.playlistOrchestrator.resetPlaylist()}closePlaylist(){this.managerOrchestrator.cleanupPlaylist(),ct.getState().resetForNewPlaylist()}destroy(){if(this.isInitialized)try{this.managerOrchestrator.destroyAll(),this.isInitialized=!1}catch(t){console.error("SaltfishPlayer: Error during destruction:",t),this.isInitialized=!1}else console.warn("Saltfish playlist Player is not initialized")}on(t,e){this.managerOrchestrator.getManagers().eventManager.on(t,e)}off(t,e){return this.managerOrchestrator.getManagers().eventManager.off(t,e)}get videoManager(){return this.managerOrchestrator.getManagers().videoManager}getManagers(){return this.managerOrchestrator.getManagers()}getServices(){return{playerInitializationService:this.playerInitializationService,userManagementService:this.userManagementService,playlistOrchestrator:this.playlistOrchestrator,stateMachineActionHandler:this.stateMachineActionHandler,managerOrchestrator:this.managerOrchestrator}}};e(fe,"instance",null);let ye=fe;const ve=Object.freeze(Object.defineProperty({__proto__:null,SaltfishPlayer:ye},Symbol.toStringTag,{value:"Module"})),be=function(){const t=ye.getInstance();let e=!1,n=!1,i=null;const s=[],r={init:r=>{if(n)return j("Saltfish already initialized"),Promise.resolve();if(e&&i)return i;const a={enableAnalytics:!0,..."string"==typeof r?{token:r}:r};return j(`Saltfish initialized: analytics=${a.enableAnalytics}`),e=!0,i=t.initialize(a).then((()=>(n=!0,e=!1,(async()=>{if(0!==s.length)for(;s.length>0;){const t=s.shift();if(t)try{await t()}catch(t){q("Error executing queued command:",t)}}})()))).catch((t=>{throw e=!1,t("Saltfish initialization failed:",t),t})),i},identify:(i,r)=>{n||!e?t.identifyUser(i,r):s.push((async()=>{t.identifyUser(i,r)}))},identifyAnonymous:i=>{n||!e?t.identifyAnonymous(i):s.push((async()=>{t.identifyAnonymous(i)}))},startPlaylist:(r,a)=>!n&&e?new Promise(((e,n)=>{s.push((async()=>{try{await t.startPlaylist(r,a),e()}catch(t){n(t)}})),i&&i.catch(n)})):t.startPlaylist(r,a),on:(e,n)=>{t.on(e,n)},off:(e,n)=>t.off(e,n),resetPlaylist:()=>{n||e?n||!e?t.resetPlaylist():s.push((async()=>{t.resetPlaylist()})):W("Cannot reset playlist - Saltfish not initialized")},destroy:()=>{n||e?(e||(n=!1,e=!1,i=null,s.length=0),t.destroy(),n=!1,e=!1,i=null):W("Cannot destroy - Saltfish not initialized")},getSessionId:()=>t.getSessionId(),getRunId:()=>t.getRunId(),version:()=>"0.3.93"};return r.__dev__={getDeviceInfo:()=>_t.getDeviceInfo()},r}();if("undefined"!=typeof window&&"undefined"!=typeof document&&!document.querySelector('meta[name="saltfish-player-loaded"]')){const t=document.createElement("meta");t.name="saltfish-player-loaded",t.content="true",document.head.appendChild(t)}return"undefined"!=typeof window&&(window.saltfish=be),be}));