saltfish 0.3.12 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/player.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* Saltfish playlist Player v0.3.
|
|
3
|
+
* Saltfish playlist Player v0.3.13
|
|
4
4
|
* (c) 2025
|
|
5
5
|
* Released under the MIT License.
|
|
6
6
|
|
|
7
7
|
*/
|
|
8
|
-
!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={},i=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};var s=Symbol.for("immer-nothing"),r=Symbol.for("immer-draftable"),a=Symbol.for("immer-state");function o(t,...e){throw new Error(`[Immer] minified error nr: ${t}. Full error at: https://bit.ly/3cXEKWf`)}var l=Object.getPrototypeOf;function c(t){return!!t&&!!t[a]}function d(t){var e;return!!t&&(u(t)||Array.isArray(t)||!!t[r]||!!(null==(e=t.constructor)?void 0:e[r])||y(t)||v(t))}var h=Object.prototype.constructor.toString();function u(t){if(!t||"object"!=typeof t)return!1;const e=l(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)===h}function p(t,e){0===g(t)?Reflect.ownKeys(t).forEach((n=>{e(n,t[n],t)})):t.forEach(((n,i)=>e(i,n,t)))}function g(t){const e=t[a];return e?e.type_:Array.isArray(t)?1:y(t)?2:v(t)?3:0}function m(t,e){return 2===g(t)?t.has(e):Object.prototype.hasOwnProperty.call(t,e)}function f(t,e,n){const i=g(t);2===i?t.set(e,n):3===i?t.add(n):t[e]=n}function y(t){return t instanceof Map}function v(t){return t instanceof Set}function b(t){return t.copy_||t.base_}function S(t,e){if(y(t))return new Map(t);if(v(t))return new Set(t);if(Array.isArray(t))return Array.prototype.slice.call(t);const n=u(t);if(!0===e||"class_only"===e&&!n){const e=Object.getOwnPropertyDescriptors(t);delete e[a];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(l(t),e)}{const e=l(t);if(null!==e&&n)return{...t};const i=Object.create(e);return Object.assign(i,t)}}function w(t,e=!1){return M(t)||c(t)||!d(t)||(g(t)>1&&(t.set=t.add=t.clear=t.delete=E),Object.freeze(t),e&&Object.entries(t).forEach((([t,e])=>w(e,!0)))),t}function E(){o(2)}function M(t){return Object.isFrozen(t)}var I,P={};function x(t){const e=P[t];return e||o(0),e}function C(){return I}function T(t,e){e&&(x("Patches"),t.patches_=[],t.inversePatches_=[],t.patchListener_=e)}function k(t){_(t),t.drafts_.forEach(z),t.drafts_=null}function _(t){t===I&&(I=t.parent_)}function A(t){return I={drafts_:[],parent_:I,immer_:t,canAutoFreeze_:!0,unfinalizedDrafts_:0}}function z(t){const e=t[a];0===e.type_||1===e.type_?e.revoke_():e.revoked_=!0}function L(t,e){e.unfinalizedDrafts_=e.drafts_.length;const n=e.drafts_[0];return void 0!==t&&t!==n?(n[a].modified_&&(k(e),o(4)),d(t)&&(t=O(e,t),e.parent_||D(e,t)),e.patches_&&x("Patches").generateReplacementPatches_(n[a].base_,t,e.patches_,e.inversePatches_)):t=O(e,n,[]),k(e),e.patches_&&e.patchListener_(e.patches_,e.inversePatches_),t!==s?t:void 0}function O(t,e,n){if(M(e))return e;const i=e[a];if(!i)return p(e,((s,r)=>V(t,i,e,s,r,n))),e;if(i.scope_!==t)return e;if(!i.modified_)return D(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),p(s,((s,a)=>V(t,i,e,s,a,n,r))),D(t,e,!1),n&&t.patches_&&x("Patches").generatePatches_(i,n,t.patches_,t.inversePatches_)}return i.copy_}function V(t,e,n,i,s,r,a){if(c(s)){const a=O(t,s,r&&e&&3!==e.type_&&!m(e.assigned_,i)?r.concat(i):void 0);if(f(n,i,a),!c(a))return;t.canAutoFreeze_=!1}else a&&n.add(s);if(d(s)&&!M(s)){if(!t.immer_.autoFreeze_&&t.unfinalizedDrafts_<1)return;O(t,s),e&&e.scope_.parent_||"symbol"==typeof i||!Object.prototype.propertyIsEnumerable.call(n,i)||D(t,s)}}function D(t,e,n=!1){!t.parent_&&t.immer_.autoFreeze_&&t.canAutoFreeze_&&w(e,n)}var B={get(t,e){if(e===a)return t;const n=b(t);if(!m(n,e))return function(t,e,n){var i;const s=R(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_||!d(i)?i:i===U(t.base_,e)?(H(t),t.copy_[e]=Y(i,t)):i},has:(t,e)=>e in b(t),ownKeys:t=>Reflect.ownKeys(b(t)),set(t,e,n){const i=R(b(t),e);if(null==i?void 0:i.set)return i.set.call(t.draft_,n),!0;if(!t.modified_){const i=U(b(t),e),o=null==i?void 0:i[a];if(o&&o.base_===n)return t.copy_[e]=n,t.assigned_[e]=!1,!0;if(((s=n)===(r=i)?0!==s||1/s==1/r:s!=s&&r!=r)&&(void 0!==n||m(t.base_,e)))return!0;H(t),N(t)}var s,r;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,H(t),N(t)):delete t.assigned_[e],t.copy_&&delete t.copy_[e],!0),getOwnPropertyDescriptor(t,e){const n=b(t),i=Reflect.getOwnPropertyDescriptor(n,e);return i?{writable:!0,configurable:1!==t.type_||"length"!==e,enumerable:i.enumerable,value:n[e]}:i},defineProperty(){o(11)},getPrototypeOf:t=>l(t.base_),setPrototypeOf(){o(12)}},F={};function U(t,e){const n=t[a];return(n?b(n):t)[e]}function R(t,e){if(!(e in t))return;let n=l(t);for(;n;){const t=Object.getOwnPropertyDescriptor(n,e);if(t)return t;n=l(n)}}function N(t){t.modified_||(t.modified_=!0,t.parent_&&N(t.parent_))}function H(t){t.copy_||(t.copy_=S(t.base_,t.scope_.immer_.useStrictShallowCopy_))}p(B,((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 B.set.call(this,t[0],e,n,t[0])};function Y(t,e){const n=y(t)?x("MapSet").proxyMap_(t,e):v(t)?x("MapSet").proxySet_(t,e):function(t,e){const n=Array.isArray(t),i={type_:n?1:0,scope_:e?e.scope_:C(),modified_:!1,finalized_:!1,assigned_:{},parent_:e,base_:t,draft_:null,copy_:null,revoke_:null,isManual_:!1};let s=i,r=B;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_:C()).drafts_.push(n),n}function $(t){if(!d(t)||M(t))return t;const e=t[a];let n;if(e){if(!e.modified_)return e.base_;e.finalized_=!0,n=S(t,e.scope_.immer_.useStrictShallowCopy_)}else n=S(t,!0);return p(n,((t,e)=>{f(n,t,$(e))})),e&&(e.finalized_=!1),n}var X=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 i;if("function"!=typeof e&&o(6),void 0!==n&&"function"!=typeof n&&o(7),d(t)){const s=A(this),r=Y(t,void 0);let a=!0;try{i=e(r),a=!1}finally{a?k(s):_(s)}return T(s,n),L(i,s)}if(!t||"object"!=typeof t){if(i=e(t),void 0===i&&(i=t),i===s&&(i=void 0),this.autoFreeze_&&w(i,!0),n){const e=[],s=[];x("Patches").generateReplacementPatches_(t,i,e,s),n(e,s)}return i}o(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){d(t)||o(8),c(t)&&(t=function(t){c(t)||o(10);return $(t)}(t));const e=A(this),n=Y(t,void 0);return n[a].isManual_=!0,_(e),n}finishDraft(t,e){const n=t&&t[a];n&&n.isManual_||o(9);const{scope_:i}=n;return T(i,e),L(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=x("Patches").applyPatches_;return c(t)?i(t,e):this.produce(t,(t=>i(t,e)))}},j=X.produce;X.produceWithPatches.bind(X),X.setAutoFreeze.bind(X),X.setUseStrictShallowCopy.bind(X),X.applyPatches.bind(X),X.createDraft.bind(X),X.finishDraft.bind(X);const W=t=>(e,n,i)=>(i.setState=(t,n,...i)=>{const s="function"==typeof t?j(t):t;return e(s,n,...i)},t(i.setState,n,i));function q(t,e){void 0!==e?console.info(t,e):console.info(t)}function Z(t,e){console.warn(t)}function K(t,e){void 0!==e?console.error(t,e):console.error(t)}class J{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.setupDefaultActions(),this.runEntryActions(this.currentState)}setupDefaultActions(){this.actionHandlers={...this.actionHandlers,logStateEntry:t=>{this.currentState},logErrorEvent:(t,e)=>{"ERROR"===(null==e?void 0:e.type)&&e.error.message},logStepTransition:(t,e)=>{"TRANSITION_TO_STEP"===(null==e?void 0:e.type)&&e.step.id},logErrorRecovery:()=>{}}}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];if(!e)return t.type,this.currentState,this.currentState;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;return this.currentState=e.target,this.runEntryActions(this.currentState),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"}},entry:["logStateEntry"]},loading:{on:{MANIFEST_LOADED:{target:"paused"},ERROR:{target:"error",actions:["logErrorEvent"]}},entry:["logStateEntry","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",actions:["logStepTransition"]},ERROR:{target:"error"},COMPLETE_PLAYLIST:{target:"completed"},COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION:{target:"completedWaitingForInteraction"}},entry:["logStateEntry","startVideoPlayback","showVideoControls","hidePlayButton"],exit:["pauseVideoPlayback"]},paused:{on:{PLAY:{target:"playing"},START_IDLE_MODE:{target:"idleMode"},MINIMIZE:{target:"minimized"},TRANSITION_TO_STEP:{target:"playing",actions:["logStepTransition"]}},entry:["logStateEntry","pauseVideoPlayback","showPlayButton"]},minimized:{on:{MAXIMIZE:{target:"paused"},EXIT:{target:"closing"}},entry:["logStateEntry","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",actions:["logStepTransition"]}},entry:["logStateEntry","showPlayButton"]},autoplayBlocked:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["logStateEntry","startMutedLoopedVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls"]},idleMode:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["logStateEntry","startIdleModeVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls"]},error:{on:{INITIALIZE:{target:"idle"},PLAY:{target:"playing",actions:["logErrorRecovery"]},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"}},entry:["logStateEntry","handleError","showPlayButton"]},completedWaitingForInteraction:{on:{COMPLETE_PLAYLIST:{target:"completed"},INITIALIZE:{target:"idle"},TRANSITION_TO_STEP:{target:"playing",actions:["logStepTransition"]},PLAY:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["logStateEntry","showPlayButton"]},completed:{on:{INITIALIZE:{target:"idle"}},entry:["logStateEntry","trackPlaylistComplete"]},closing:{on:{},entry:["logStateEntry","triggerPlaylistDismissed"]}}},Q="saltfish_progress",tt="saltfish_session",et="saltfish_anonymous_user_data",nt=12e4,it=18e5,st="https://player.saltfish.ai",rt="sf-player",at="sf-player--minimized",ot="sf-controls-container",lt="sf-player__logo",ct="sf-error-display",dt="sf-error-display--visible",ht="sf-error-display__content",ut="sf-error-display__message",pt="sf-loading-spinner",gt=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(i){}}return!1}}safeClearItem(t){if(this.isLocalStorageAvailable)try{localStorage.removeItem(t)}catch(e){}}clearOldData(){this.safeClearItem(tt)}getProgress(t){const e=this.safeGetItem(Q);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(Q,n)}clearProgress(){this.safeClearItem(Q)}getSession(){return this.safeGetItem(tt)}setSession(t){return this.safeSetItem(tt,t)}clearSession(){this.safeClearItem(tt)}getAnonymousUserData(){return this.safeGetItem(et)}setAnonymousUserData(t){return this.safeSetItem(et,t)}clearAnonymousUserData(){this.safeClearItem(et)}getAnonymousUserId(){const t=this.getAnonymousUserData();return(null==t?void 0:t.userId)||null}clearAll(){this.clearProgress(),this.clearSession(),this.clearAnonymousUserData()}isStorageAvailable(){return this.isLocalStorageAvailable}getStorageInfo(){const t=[];if(this.isLocalStorageAvailable)try{for(let e=0;e<localStorage.length;e++){const n=localStorage.key(e);n&&n.startsWith("saltfish_")&&t.push(n)}}catch(e){}return{available:this.isLocalStorageAvailable,keys:t}}};e(gt,"instance",null);let mt=gt;const ft=mt.getInstance(),yt=i(W(((t,e)=>{let n=new J(G,{currentStep:null,error:null});const i=t=>n.send(t);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}))},setUserData:e=>{t((t=>{t.userData=e}))},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:s}=e();if("completed"!==n){if(s&&s.steps.some((t=>t.id===n))){const e=s.steps.find((t=>t.id===n));t((t=>{var r,a,o;t.currentStepId=n,e&&(t.currentState=i({type:"TRANSITION_TO_STEP",step:e}),(t.position||(null==(r=t.playlistOptions)?void 0:r.position))&&(t.position={x:0,y:0})),t.progress[s.id]={...t.progress[s.id],lastStepId:n,lastVisited:(new Date).toISOString()};if((null==(a=t.playlistOptions)?void 0:a.persistence)??!0){const e=null==(o=t.user)?void 0:o.id;ft.setProgress(t.progress,e)}}))}}else t((t=>{t.currentState=i({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 J(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:()=>{t((t=>{t.currentState=i({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 J(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:e=>{t((t=>{t.currentState=i(e)}))},updateProgressWithCompletion:(e,n)=>{t((t=>{var s,r;t.currentState=i({type:"COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION"}),t.progress[e]={...t.progress[e],lastStepId:n,lastVisited:(new Date).toISOString(),completedWaitingForInteraction:!0};if((null==(s=t.playlistOptions)?void 0:s.persistence)??!0){const e=null==(r=t.user)?void 0:r.id;ft.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 e of i){const t=s[e.id];t&&t.assigned||r.add(e.playlistId)}return n.filter((t=>!r.has(t.id)))}}}))),vt={getState:()=>yt.getState(),setState:yt.setState,subscribe:yt.subscribe,destroy:yt.destroy};function bt(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 St(t,e=6e3){const n=bt(t);if(!n)return{isValid:!1,ageMs:null,timestampMs:null};const i=Date.now()-n;return{isValid:i<=e,ageMs:i,timestampMs:n}}class wt{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{vt.getState().setError(t)}catch(e){console.error("Failed to update store with error:",e)}}static triggerErrorEvent(t,e,n){var i,s;try{const r=vt.getState();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(r){console.error("Failed to trigger error event:",r)}}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){if(t.message.includes("fetch")||t.message.includes("network")||t.message.includes("timeout"))return!0;return[/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(i){return this.handle(i,e,n),null}}}e(wt,"DEFAULT_OPTIONS",{severity:"error",shouldLog:!0,shouldThrow:!1,shouldUpdateStore:!1,shouldTriggerEvent:!1,shouldDestroy:!1});class Et{constructor(t){e(this,"managers"),e(this,"userManagementService"),e(this,"playlistOrchestrator"),e(this,"lastConfig",null),this.managers=t}setUserManagementService(t){this.userManagementService=t}setPlaylistOrchestrator(t){this.playlistOrchestrator=t}getLastConfig(){return this.lastConfig}async initialize(t){var e;try{const n=await fetch(`${st}/validate-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t.token,playerVersion:"0.2.73"})}),i=await n.json();if(!i.isValid)throw wt.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=vt.getState();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 wt.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(n){throw wt.handleInitializationError(n,{component:"PlayerInitializationService",method:"initialize"})}}async fetchUserData(t,e){var n;try{const i=vt.getState();if(!(null==(n=i.config)?void 0:n.token))return void wt.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){await s.text();return s.status,void s.statusText}const r=await s.json();if(r.success){i.setUserData({watchedPlaylists:r.watchedPlaylists||{},language:r.language});const e=r.userListAssignments||{},n=r.abTestAssignments||{};this.managers.abTestManager.assignUserToTests(t,n,e),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:r.watchedPlaylists||{}}}),this.userManagementService&&this.userManagementService.resolveUserDataLoaded();await this.checkAndResumeInProgressPlaylist(r.watchedPlaylists||{})||this.managers.triggerManager.startMonitoring()}else this.userManagementService&&this.userManagementService.resolveUserDataLoaded()}catch(i){wt.handleNetworkError(i,{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);vt.getState().setUserData({watchedPlaylists:s.watchedPlaylists||{},language:null==e?void 0:e.language}),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:s.watchedPlaylists||{}}});const r=s.watchedPlaylists||{};await this.checkAndResumeInProgressPlaylist(r)||this.managers.triggerManager.startMonitoring()}catch(n){wt.handleNetworkError(n,{component:"PlayerInitializationService",method:"loadAnonymousUserData",userId:t})}}async checkAndResumeInProgressPlaylist(t){var e;if(!t)return!1;const n=vt.getState(),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}=St(e);return!!n}));if(r){const[t,e]=r;bt(e);try{if(this.playlistOrchestrator)return await this.playlistOrchestrator.startPlaylist(t),!0}catch(a){return!1}}return!1}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}destroy(){this.lastConfig=null}}function Mt(t){if(!t)return;if("auto"===t){return function(){try{const t=navigator.language||navigator.userLanguage;if(!t)return;return t.split("-")[0].toLowerCase()}catch(t){return}}()}return t.split("-")[0].toLowerCase()}class It{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=Mt(e.language);n={...e,language:t},e.language}this.lastUserIdentification={userId:t,userData:n};const i=vt.getState();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=Mt(t.language);e={...t,language:n},t.language}const n=this.playerInitializationService.getOrCreateAnonymousUserId();this.lastUserIdentification={userId:n,userData:e};vt.getState().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=vt.getState(),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(n){}}resolveUserDataLoaded(){this.userDataLoadedResolve&&(this.userDataLoadedResolve(),this.userDataLoadedResolve=null,this.userDataLoadedPromise=null)}destroy(){this.userDataLoadedPromise=null,this.userDataLoadedResolve=null,this.lastUserIdentification=null}}class Pt{async validatePlaylistStart(t){const{playlistId:e,options:n,eventManager:i}=t;try{const t=vt.getState();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}}const s=t.backendPlaylists;if(!s||0===s.length)return wt.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 wt.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"};const a=(null==r?void 0:r.hasTriggers)??(null==r?void 0:r.autoStart)??!1,o=!0===(null==n?void 0:n._triggeredByTriggerManager);if(a&&o){const t=await this.validateTriggerConditions(e,r,i);if(!t.isValid)return t}let l=n;if(null==n?void 0:n.once){const t=await this.validateOnceOptionConditions(e,n,i);if(!t.isValid)return t;l=t.updatedOptions||n}const c=await this.validateDeviceCompatibility(r,e);return c.isValid?{isValid:!0,manifestPath:r.path,updatedOptions:l}:c}catch(s){const t=s instanceof Error?s.message:"Unknown validation error";return wt.handlePlaylistError(`Playlist validation failed: ${t}`,{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,additionalData:{error:s}}),{isValid:!1,error:t}}}async validateTriggerConditions(t,e,n){var i,s;const r=vt.getState();if(!r.user)return wt.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=vt.getState().userData)?void 0:i.watchedPlaylists)||{},o=e.hasTriggers??e.autoStart??!1,l=a[t];return o&&(null==(s=e.triggers)?void 0:s.once)&&l&&("completed"===l.status||"dismissed"===l.status)?(q(`Playlist ${t} has hasTriggers enabled with once:true and has already been ${l.status}. Skipping playlist start.`,{watchedPlaylists:a,triggers:e.triggers}),{isValid:!1,error:`Playlist already ${l.status} with once=true policy`}):{isValid:!0}}async validateOnceOptionConditions(t,e,n){var i;const s=vt.getState();if(!s.user)return wt.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=vt.getState().userData)?void 0:i.watchedPlaylists)||{},a=r[t];if(a&&("completed"===a.status||"dismissed"===a.status))return q(`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`};if(a&&"in_progress"===a.status&&!(null==e?void 0:e.startNodeId)&&a.currentStepId){return{isValid:!0,updatedOptions:{...e,startNodeId:a.currentStepId}}}return{isValid:!0}}async validateDeviceCompatibility(t,e){try{const n=t.deviceType||"both",{isDeviceCompatible:i}=await Promise.resolve().then((()=>Ot));return i(n)?{isValid:!0}:(wt.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 wt.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),vt.getState(),e()};t.on("userDataLoaded",s)}))}}class xt{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 l=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.identifyUser(t.userId,t.userData),this.resetManagers(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()}catch(o){throw wt.handleInitializationError(`Failed to reinitialize player: ${o instanceof Error?o.message:"Unknown error"}`,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,additionalData:{reinitError:o}})}}l&&(this.resetManagers(),this.managers.transitionManager.setTriggerManager(this.managers.triggerManager),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions());const c=vt.getState();if(!c.config){if(!(null==(i=this.playerInitializationService)?void 0:i.getLastConfig()))throw wt.createError("Saltfish Player must be initialized at least once before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t});throw wt.createError("Saltfish Player must be initialized before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t})}c.manifest&&("playing"===c.currentState||"paused"===c.currentState||"loading"===c.currentState||"waitingForInteraction"===c.currentState||"autoplayBlocked"===c.currentState||"minimized"===c.currentState)&&(this.managerOrchestrator&&this.managerOrchestrator.cleanupCurrentPlaylist(),c.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()),"completed"!==c.currentState&&"closing"!==c.currentState||(c.currentState,c.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions());this.managers.sessionManager.startNewRun();const d=null==(s=this.userManagementService)?void 0:s.getUserDataLoadedPromise();if(d&&await d,this.userManagementService&&await this.userManagementService.recordABTestAttempt(t),!this.managers.abTestManager.isPlaylistAvailable(t))return;const h=new Pt,u=await h.validatePlaylistStart({playlistId:t,options:e,eventManager:this.managers.eventManager});if(!u.isValid)return;e=u.updatedOptions||e;const p=u.manifestPath,g=e||{};g?(c.setPlaylistOptions(g),g.position||c.setPlaylistOptions({...g,position:"bottom-right"})):c.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(),c.sendStateMachineEvent({type:"LOAD_MANIFEST"});const m=null==e?void 0:e.persistence;if("undefined"!=typeof window){const e=null==(r=c.user)?void 0:r.id,n=this.managers.storageManager.getProgress(e);if(n&&n[t])c.loadPlaylistProgress(t,n[t]);else if(c.progress[t]){const e={...c.progress};delete e[t],vt.setState((t=>{t.progress=e}))}}this.managers.analyticsManager.trackPlaylistStart(t),this.managers.cursorManager.resetFirstAnimation(),await this.managers.playlistManager.load(p,{...g,persistence:m});const f=vt.getState();if(f.manifest){const t=g.persistence??f.manifest.isPersistent??!0,e=f.playlistOptions||{};f.setPlaylistOptions({...e,...g,persistence:t})}if(g.startNodeId&&f.manifest){f.manifest.steps.find((t=>t.id===g.startNodeId))?f.goToStep(g.startNodeId):console.warn(`[PlaylistOrchestrator] startNodeId '${g.startNodeId}' not found in manifest steps. Starting from default step.`)}if(f.manifest){f.manifest.cursorColor&&this.managers.cursorManager.setColor(f.manifest.cursorColor);const t=!0===g._triggeredByTriggerManager,e=f.currentStepId===(null==(a=f.manifest.steps[0])?void 0:a.id);if(f.manifest.compactFirstStep&&e&&t){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.add("sf-player--compact")}f.manifest.idleMode&&t?c.setIdleMode():c.play()}else c.play();q(`Playlist started: ${t}${f.manifest?` (${f.manifest.name})`:""}`)}catch(l){this.managers.uiManager.hideLoading();vt.getState().sendStateMachineEvent({type:"ERROR",error:l instanceof Error?l:new Error(String(l))}),wt.handlePlaylistError(l,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,errorType:"playlist_load_failed"})}}resetPlaylist(){const t=vt.getState();t.manifest&&t.goToStep(t.manifest.startStep)}isInitialized(){return!!vt.getState().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 Ct{constructor(t){e(this,"managers"),e(this,"destroyCallback",null),this.managers=t}setDestroyCallback(t){this.destroyCallback=t}registerStateMachineActions(){vt.getState().registerStateMachineActions({startVideoPlayback:t=>{this.handleStartVideoPlayback(t)},pauseVideoPlayback:()=>{this.handlePauseVideoPlayback()},startMutedLoopedVideo:()=>{this.handleStartMutedLoopedVideo()},startIdleModeVideo:t=>{this.handleStartIdleModeVideo(t)},trackPlaylistComplete:()=>{this.handleTrackPlaylistComplete()},handleError:t=>{this.handleError(t)},showLoadingState:()=>{this.handleShowLoadingState()},hideLoadingState:()=>{this.handleHideLoadingState()},hideVideoControls:()=>{this.handleHideVideoControls()},showVideoControls:()=>{this.handleShowVideoControls()},showPlayButton:()=>{this.handleShowPlayButton()},hidePlayButton:()=>{this.handleHidePlayButton()},enablePlayButtonProminent:()=>{this.handleEnablePlayButtonProminent()},disablePlayButtonProminent:()=>{this.handleDisablePlayButtonProminent()},triggerPlaylistDismissed:()=>{this.handleTriggerPlaylistDismissed()},scheduleDestroy:()=>{this.handleScheduleDestroy()}})}getVideoUrl(t){var e;const n=null==(e=vt.getState().userData)?void 0:e.language;let i;if(n&&t.translations&&t.translations[n]){i=t.translations[n].videoUrl}else i=t.compressedUrl||t.videoUrl;return i&&""!==i.trim()||!t.audioUrl||""===t.audioUrl.trim()?i:(t.id,t.audioUrl)}isUsingAudioFallback(t){var e;const n=null==(e=vt.getState().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=vt.getState();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(){}async validateStepUrlRequirement(t){if(!t.urlRequirement)return!0;const{pattern:e,matchType:n}=t.urlRequirement;if(!e)return!0;const i=()=>{const t=window.location.href,i=window.location.pathname;let s=!1;if("regex"===n)try{const n=new RegExp(e);s=n.test(t)||n.test(i)}catch(r){}else s="contains"===n?t.includes(e)||i.includes(e):t===e||i===e;return s};for(let r=0;r<3;r++){if(i())return!0;if(r<2){await new Promise((t=>setTimeout(t,100)));if(!window._saltfishPlayer)return!1}}t.id;const s=window._saltfishPlayer;return s&&"function"==typeof s.destroy&&s.destroy(),!1}async handleStartVideoPlayback(t){if(!t.currentStep)return;const e=t.currentStep;if(e.urlRequirement){e.id;if(!(await this.validateStepUrlRequirement(e)))return}this.managers.uiManager.updatePosition();const n=this.managers.uiManager.getPlayerElement();null==n||n.classList.remove("sf-player--compact"),this.managers.uiManager.showPlayer();const i=this.getVideoUrl(e),s=this.isUsingAudioFallback(e);if(s){const t=vt.getState().manifest,n=e.gifUrl,i=null==t?void 0:t.avatarThumbnailUrl;this.managers.videoManager.showAudioFallbackOverlay(n,i)}else this.managers.videoManager.hideAudioFallbackOverlay();try{this.managers.interactionManager.clearButtons(),this.managers.interactionManager.clearDOMInteractions(),e.domInteractions&&this.managers.interactionManager.setupDOMInteractions(e.domInteractions),e.buttons&&this.managers.interactionManager.createButtons(e.buttons),e.id,e.cursorAnimations&&e.cursorAnimations.length,e.cursorAnimations&&e.cursorAnimations.length>0?(e.id,this.managers.cursorManager.setShouldShowCursor(!0),e.id,e.cursorAnimations[0].targetSelector,this.managers.cursorManager.animate(e.cursorAnimations[0])):(e.id,this.managers.cursorManager.setShouldShowCursor(!1));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)),n=t?"manual":"auto";t&&this.managers.transitionManager.setupTransitions(e,!1,!0),this.managers.videoManager.setCompletionPolicy(n,(()=>{var n;const i=vt.getState();if(t){const t=e.transitions.find((t=>"timeout"===t.type)),s=null==(n=e.buttons)?void 0:n.some((t=>"goto"===t.action.type||"next"===t.action.type));if(t&&!s){const n=t.timeout||0;t.nextStep,setTimeout((()=>{var n;const i=vt.getState();i.currentStepId!==e.id||"waitingForInteraction"!==i.currentState&&"playing"!==i.currentState?i.currentState:(t.nextStep,null==(n=i.goToStep)||n.call(i,t.nextStep))}),n),i.sendStateMachineEvent({type:"VIDEO_FINISHED_WAIT",step:e})}else i.sendStateMachineEvent({type:"VIDEO_FINISHED_WAIT",step:e})}else{this.managers.transitionManager.setupTransitions(e,!0);e.transitions.some((t=>i.manifest.steps.some((e=>e.id===t.nextStep))))||i.sendStateMachineEvent({type:"COMPLETE_PLAYLIST"})}}));const r=()=>{var t,n;const i=vt.getState(),s=(null==(t=i.manifest)?void 0:t.captions)??!0,r=null==(n=i.userData)?void 0:n.language;let a=e.transcript;if(r&&e.translations&&e.translations[r]){const t=e.translations[r].transcript;t&&(a=t,e.id)}a?(e.id,this.managers.videoManager.loadTranscript(a,s)):(e.id,this.managers.videoManager.loadTranscript(null,!0))};this.managers.videoManager.loadVideo(i).then((()=>{r(),s?this.managers.videoManager.startAudioVisualization():this.managers.videoManager.initializeAudioForVideo(),this.managers.videoManager.play();const t=this.findNextVideoUrl(e);t&&this.managers.videoManager.preloadNextVideo(t)})).catch((t=>{var n;this.managers.uiManager.showError(t instanceof Error?t:new Error(`Failed to load video: ${t}`),"video");const i=vt.getState(),s=t instanceof Error?t:new Error(`Failed to load video: ${t}`),r=t;this.managers.eventManager.trigger("error",{timestamp:Date.now(),playlistId:(null==(n=i.manifest)?void 0:n.id)||void 0,stepId:e.id,error:s,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})}))}catch(r){}}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);if(this.managers.uiManager.showPlayer(),i){const t=vt.getState().manifest,n=e.gifUrl,i=null==t?void 0:t.avatarThumbnailUrl;this.managers.videoManager.showAudioFallbackOverlay(n,i)}else this.managers.videoManager.hideAudioFallbackOverlay();this.managers.videoManager.loadVideo(n).then((()=>{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=vt.getState();if(n.manifest&&this.managers.eventManager){const i=n.manifest.id;this.managers.eventManager.trigger("playlistEnded",{timestamp:Date.now(),playlist:{id:i,title:n.manifest.name}});if(((null==(t=n.playlistOptions)?void 0:t.persistence)??!0)&&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=vt.getState();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"})}}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()}handleTriggerPlaylistDismissed(){const t=vt.getState();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)}}function Tt(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 vt.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){if(!n)return;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}}))}function kt(t){let e=null,n=null,i=null,s=null;const r=vt.subscribe((r=>{var a;if(e===r.currentState&&i===r.isMinimized&&s===r.currentStepId)return;const o=e,l=n,c=i,d=s;n=e,e=r.currentState,i=r.isMinimized,s=r.currentStepId;const h={prevPreviousState:l,previousState:o,currentState:r.currentState,currentStepId:r.currentStepId,isMinimized:r.isMinimized};null==(a=r.manifest)||a.id,function(t,e,n){const{prevPreviousState:i,previousState:s,currentState:r,currentStepId:a}=t;if("playing"===r&&"paused"===s&&"loading"===i&&e.manifest&&a){if(a===e.manifest.startStep)return e.manifest.id,void n.trigger("playlistStarted",{timestamp:Date.now(),playlist:{id:e.manifest.id,title:e.manifest.name}})}"paused"===s&&"playing"===r?n.trigger("playerResumed",{timestamp:Date.now(),previousState:s,currentState:r}):"playing"===s&&"paused"===r&&n.trigger("playerPaused",{timestamp:Date.now(),previousState:s,currentState:r})}(h,r,t),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})}(h,0,t,c),function(t,e,n,i){var s,r,a;const{prevPreviousState:o,previousState:l,currentStepId:c,currentState:d}=t,h=e.currentStepId?((null==(s=e.manifest)?void 0:s.steps)||[]).find((t=>t.id===e.currentStepId)):null;null==h||h.id,null==(r=e.manifest)||r.id,e.manifest;const u=i&&e.manifest&&(i!==c||"waitingForInteraction"===d||"completed"===d);if(e.manifest,u){const t=((null==(a=e.manifest)?void 0:a.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 p=c!==i&&"playing"===d,g="autoplayBlocked"===l&&"playing"===d&&i===c,m="loading"===o&&"paused"===l&&"playing"===d&&c,f=h&&e.manifest&&(p||g||m);null==h||h.id,e.manifest,f&&(h.id,n.trigger("stepStarted",{timestamp:Date.now(),step:{id:h.id,title:h.title||h.id},playlist:{id:e.manifest.id,title:e.manifest.name}}))}(h,r,t,d),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"})}(h,r,t)}));return r}const _t=class t{constructor(t){e(this,"managers"),e(this,"uiUpdaterUnsubscribe",null),e(this,"eventUpdaterUnsubscribe",null),e(this,"isInitialized",!1),this.managers=t}setInitialized(t){this.isInitialized=t}setupUpdaters(){this.uiUpdaterUnsubscribe&&this.uiUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe&&this.eventUpdaterUnsubscribe();const t=this.managers.uiManager.getPlayerElement();t&&(this.uiUpdaterUnsubscribe=Tt(t,this.managers.cursorManager)),this.eventUpdaterUnsubscribe=kt(this.managers.eventManager);const e=vt.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=vt.getState();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.managers.cursorManager.animate(n.cursorAnimations[0]))}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.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.interactionManager.clearDOMInteractions()),this.managers.uiManager.reset()}catch(t){wt.handleCleanupError(t,{component:"ManagerOrchestrator",method:"cleanupCurrentPlaylist"})}}cleanupPlaylist(){var t;if(this.isInitialized)try{const e=vt.getState();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,this.uiUpdaterUnsubscribe&&(this.uiUpdaterUnsubscribe(),this.uiUpdaterUnsubscribe=null),this.managers.transitionManager.destroy(),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(e){wt.handleCleanupError(e,{component:"ManagerOrchestrator",method:"cleanupPlaylist"})}else console.warn("Saltfish playlist Player is not initialized")}destroyAll(){var t;if(this.isInitialized)try{const e=vt.getState();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,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(e){wt.handleCleanupError(e,{component:"ManagerOrchestrator",method:"destroyAll"});try{this.isInitialized=!1;vt.getState().reset()}catch(n){wt.handleCleanupError(n,{component:"ManagerOrchestrator",method:"destroyAll",additionalData:{originalError:e}})}}else console.warn("Saltfish playlist Player is not initialized")}getManagers(){return this.managers}destroy(){this.destroyAll()}};e(_t,"prevState",{currentState:"idle",currentStepId:null,isMinimized:!1});let At=_t;class zt{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(e){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(){if(!this.shadowRoot)return null;return this.shadowRoot.getElementById("sf-player-root")}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(e){console.warn("ShadowDOMManager: Failed to append to adoptedStyleSheet:",e)}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-lg);\n box-shadow: 0 25px 50px rgba(0, 0, 0, 0.45), 0 10px 20px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(255, 255, 255, 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/* Dark gradient overlay at bottom of player */\n.sf-player::before {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of player 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: 8px;\n}\n\n/* Hide gradient overlay when minimized */\n.sf-player--minimized::before {\n display: none;\n}\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.35), 0 5px 15px rgba(0, 0, 0, 0.25), 0 0 0 2px rgba(255, 255, 255, 0.08);\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.35), 0 5px 15px rgba(0, 0, 0, 0.25), 0 0 0 2px rgba(255, 255, 255, 0.08);\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/* Adjust play button size in compact mode */\n.sf-player--compact .sf-player__center-play-button {\n width: var(--sf-play-button-compact-size);\n height: var(--sf-play-button-compact-size);\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 */\n.sf-player--compact::before {\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: 6px;\n width: var(--sf-minimize-button-size);\n height: var(--sf-minimize-button-size);\n background-color: transparent;\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: 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 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);\n backdrop-filter: blur(3px);\n -webkit-backdrop-filter: blur(3px);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.5), 0 5px 15px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(255, 255, 255, 0.08);\n pointer-events: auto; /* Enable pointer events to capture clicks */\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 background-color: rgba(0, 0, 0, 0.7);\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 adjustment for 3+ buttons */\n.sf-player__center-play-button--with-many-buttons {\n transform: translate(-50%, -85%) !important; /* Move up by adjusting Y offset */\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: 20px;\n height: 20px;\n background-color: var(--sf-button-bg);\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 box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35);\n}\n\n/* Exit button hover state */\n.sf-player__exit-button:hover {\n transform: scale(1.1);\n background-color: var(--sf-button-hover-bg);\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}\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: 10%; /* Default minimum height */\n background-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 /* 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}\n\n/* Video blur effect (for end-of-video transitions) */\n.sf-video-container__video--blurred {\n filter: blur(3px);\n transition: filter 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 .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 .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}\n\n.sf-player--minimized .sf-video-container__video {\n border-radius: var(--sf-border-radius-circle);\n object-fit: cover;\n width: 100%;\n height: 100%;\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 width: 100%;\n height: 3px;\n background-color: rgba(255, 255, 255, 0.25);\n z-index: var(--sf-z-index-controls);\n border-radius: var(--sf-border-radius-md) var(--sf-border-radius-md) 0 0;\n cursor: pointer;\n}\n\n/* Show slightly thicker progress bar on hover for better UX */\n.sf-video-container__controls:hover {\n height: 5px;\n}\n\n/* Progress indicator */\n.sf-video-container__progress {\n height: 100%;\n background: rgba(255, 255, 255, 0.8);\n width: 0%;\n transition: width 0.1s linear;\n border-radius: var(--sf-border-radius-md) 0 0 0;\n cursor: pointer;\n transform-origin: left;\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: 6px;\n width: var(--sf-mute-button-size);\n height: var(--sf-mute-button-size);\n background-color: transparent;\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: 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 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: 6px;\n width: var(--sf-cc-button-size);\n height: var(--sf-cc-button-size);\n background-color: transparent;\n border-radius: 50%; /* Ensure perfect circle */\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.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/* 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 4+ buttons */\n.sf-choice-buttons-container--scrollable {\n max-height: 132px; /* Show ~3 buttons with gaps (3 * 36px button + 3 * 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;\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;\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-overlay);\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}\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 */\n.sf-transcript__word-container {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 0; /* Remove flex gap - spacing handled by margin on preview word */\n min-height: 60px;\n padding: 0;\n}\n\n/* Individual word styling */\n.sf-transcript__word {\n color: rgba(255, 255, 255, 0.9);\n font-size: var(--sf-font-size-lg);\n font-weight: 600;\n line-height: 1.2;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateY(0);\n filter: blur(0px);\n opacity: 1;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);\n}\n\n/* Active word (currently speaking) */\n.sf-transcript__word--active {\n opacity: 1;\n filter: blur(0px);\n transform: translateY(0) scale(1);\n color: rgba(255, 255, 255, 1);\n font-weight: 600;\n}\n\n/* Preview word (clean, unblurred when shown) */\n.sf-transcript__word--preview {\n opacity: 0.8;\n filter: blur(0px);\n transform: translateY(0) scale(0.98);\n color: rgba(255, 255, 255, 0.8);\n font-weight: 400;\n margin-left: 0.2em; /* Minimal spacing - just enough for a natural gap */\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: 50px; /* More space on mobile */\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: var(--sf-spacing-sm);\n gap: var(--sf-spacing-xs);\n }\n \n .sf-transcript__word {\n font-size: var(--sf-font-size-md);\n font-weight: 500;\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 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 /* \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 Lt{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(e){console.warn("DeviceDetector: Error in device change handler:",e)}};return window.addEventListener("orientationchange",e),window.addEventListener("resize",e),()=>{window.removeEventListener("orientationchange",e),window.removeEventListener("resize",e)}}}e(Lt,"cachedDeviceInfo",null);const Ot=Object.freeze(Object.defineProperty({__proto__:null,DeviceDetector:Lt,isDeviceCompatible:t=>{if(!t||"both"===t)return!0;const e=Lt.getDeviceInfo();return"mobile"===t?e.isMobile||e.isTablet:"desktop"===t&&e.isDesktop}},Symbol.toStringTag,{value:"Module"})),Vt=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)}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.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.hideTranscript(),this.updateCCButtonState(!!this.currentTranscript),this.isVisible)}handleCCButtonClick(t){t.preventDefault(),t.stopPropagation(),this.toggleVisibility()}handleTimeUpdate(t){if(!this.currentTranscript||!this.isVisible||!this.videoElement||0===this.chunks.length)return;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)}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){if(this.chunks[e+1].start-t<.1)return e+1;return t-this.chunks[e].end<.1?e:e+1}return-1}handleStateChange(t){this.currentTranscript,this.chunks.length,this.currentTranscript&&0!==this.chunks.length&&("waitingForInteraction"!==t&&"completedWaitingForInteraction"!==t?this.isVisible?(this.isVisible,this.showTranscript()):(this.isVisible,this.hideTranscript()):this.transcriptContent&&(this.transcriptContent.innerHTML=""))}shouldShowTwoWords(t){if(t<0||t>=this.chunks.length)return!1;const e=this.chunks[t];if(!this.chunks[t+1])return!1;const n=e.text.trim();return!(n.endsWith(".")||n.endsWith("!")||n.endsWith("?"))&&(!(t>=this.chunks.length-1)&&!(n.length>10))}updateIntelligentWordDisplay(t){if(!this.transcriptContent)return;const e=this.shouldShowTwoWords(t),n=t>=0&&t<this.chunks.length?this.chunks[t]:null,i=e&&t+1<this.chunks.length?this.chunks[t+1]:null;if(this.transcriptContent.innerHTML="",!n)return;const s=document.createElement("div");s.className="sf-transcript__word-container";const r=document.createElement("span");if(r.className="sf-transcript__word sf-transcript__word--active",r.textContent=n.text,s.appendChild(r),i){const t=document.createElement("span");t.className="sf-transcript__word sf-transcript__word--preview",t.textContent=i.text,s.appendChild(t)}this.transcriptContent.appendChild(s)}createTranscriptUI(){var t;if(this.transcriptContainer)return;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.transcriptContent&&(this.transcriptContent.innerHTML=""),this.currentTranscript=null,this.chunks=[],this.isNewVideo=!1,this.firstWordForceDisplayUntil=0,this.isVisible&&this.hideTranscript(),this.updateCCButtonState(!1),this.transcriptContainer=null,this.transcriptContent=null}static resetUserPreference(){t.userCaptionPreference=null}async destroy(){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(Vt,"userCaptionPreference",null);let Dt=Vt;class Bt{constructor(t){e(this,"deviceInfo"),this.deviceInfo=t}updateDeviceInfo(t){this.deviceInfo=t}}class Ft extends Bt{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(i){console.warn(`MobilePlaybackHandler: Failed to set attribute ${e}:`,i)}})),Object.entries(e.styles).forEach((([e,n])=>{try{t.style.setProperty(e,n)}catch(i){console.warn(`MobilePlaybackHandler: Failed to set style ${e}:`,i)}}))}configureControlElement(t){const e=this.getControlsConfig();t.style.setProperty("min-width",e.buttonMinSize.width),t.style.setProperty("min-height",e.buttonMinSize.height)}async handlePlayAttempt(t,e){const n=vt.getState().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(i){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(e){console.error("MobilePlaybackHandler: All autoplay attempts failed")}}destroy(){}getProgressUpdateFrequency(t){return t?500:16}}class Ut extends Bt{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,Object.entries(e.styles).forEach((([e,n])=>{t.style.setProperty(e,n)}))}configureControlElement(t){}async handlePlayAttempt(t,e){const n=vt.getState().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(i){return t.muted,await this.handleAutoplayFallback(t),!1}}async handleAutoplayFallback(t){t.muted=!0,t.loop=!0;try{await t.play()}catch(e){throw console.error("DesktopPlaybackHandler: All autoplay attempts failed"),new Error("Desktop autoplay completely blocked")}}getProgressUpdateFrequency(t){return 16}destroy(){}}class Rt{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;if(this.lastTimeupdateEvent=Date.now(),this.progressBar&&!1===(null==(t=this.videoElement)?void 0:t.paused)&&this.progressBar.style.setProperty("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("transition","none"),this.updateProgress())})),e(this,"handleSeeked",(()=>{this.progressBar&&this.videoElement&&(this.videoElement.paused||(this.updateProgress(),this.progressBar.offsetWidth,this.progressBar.style.setProperty("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("transition","none"),this.progressBar.style.setProperty("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='\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="none"></polygon>\n <path d="M15 9c0.8 0.8 1.5 1.9 1.5 3s-0.7 2.2-1.5 3" stroke="currentColor"></path>\n <path d="M19 7c1.6 1.6 2.5 3.8 2.5 6s-0.9 4.4-2.5 6" stroke="currentColor"></path>\n </svg>\n ',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),t&&(t.addEventListener("seeking",this.handleSeeking),t.addEventListener("seeked",this.handleSeeked),t.addEventListener("timeupdate",this.handleDetailedTimeUpdate))}updateVideoElement(t){this.videoElement&&(this.videoElement.removeEventListener("seeking",this.handleSeeking),this.videoElement.removeEventListener("seeked",this.handleSeeked),this.videoElement.removeEventListener("timeupdate",this.handleDetailedTimeUpdate)),this.videoElement=t,t&&(t.addEventListener("seeking",this.handleSeeking),t.addEventListener("seeked",this.handleSeeked),t.addEventListener("timeupdate",this.handleDetailedTimeUpdate))}reset(){this.stopProgressTracking(),this.buttonsShownAt90Percent=!1,this.lastTimeupdateEvent=0,this.progressBar&&(this.progressBar.style.setProperty("transition","none"),this.progressBar.style.setProperty("width","0%"))}reset90PercentTrigger(){this.buttonsShownAt90Percent=!1}destroy(){if(this.stopProgressTracking(),this.videoElement&&(this.videoElement.removeEventListener("seeking",this.handleSeeking),this.videoElement.removeEventListener("seeked",this.handleSeeked),this.videoElement.removeEventListener("timeupdate",this.handleDetailedTimeUpdate)),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("transition","none"),this.progressBar.style.setProperty("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("transition"),s=Date.now()-this.lastTimeupdateEvent;this.progressBar.style.setProperty("transition","none"),this.progressBar.style.setProperty("width",`${n}%`),this.progressBar.offsetWidth,this.videoElement.ended?this.progressBar.style.setProperty("transition","width 0.2s ease-out"):!this.videoElement.paused&&!this.videoElement.seeking&&i&&s<500&&this.progressBar.style.setProperty("transition","width 0.1s linear")}}setMuted(t){vt.getState().setMuted(t),this.updateMuteButtonIcon()}toggleMute(){const t=!vt.getState().isMuted;this.setMuted(t),this.callbacks.onMuteToggle()}getMuted(){return vt.getState().isMuted}updateMuteButtonIcon(){if(!this.muteButton)return;const t=vt.getState().isMuted;this.muteButton.innerHTML=t?'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n </svg>\n ':'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n </svg>\n '}updateCCButtonIcon(t){this.ccButton&&(this.ccButton.innerHTML=t?'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n </svg>\n ':'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n <line x1="48" y1="48" x2="208" y2="208" stroke="currentColor" stroke-width="16" stroke-linecap="round"/>\n </svg>\n ')}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("transition","none"),this.progressBar.style.setProperty("width","0%"),this.progressBar.offsetWidth,this.progressBar.style.setProperty("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 Nt{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(e){console.warn("AudioVisualizationManager: Web Audio API failed, using fallback animation",e),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 a=0;a<e;a++){let t=0;const e=a*s,r=e+s;for(let n=e;n<r&&n<i;n++)t+=this.dataArray[n];const o=t/s/255;n.push(o)}const r=[...n].reverse();r.pop();return r.concat(n)}getFallbackBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let i=0;i<t;i++){let t=.3+(.3*Math.sin(.003*this.fallbackTime+.5*i)+.2*Math.sin(.005*this.fallbackTime+.3*i)+.15*Math.sin(.002*this.fallbackTime+.7*i));t=Math.max(0,Math.min(1,t)),e.push(t)}const n=[...e].reverse();n.pop();return n.concat(e)}getFlatBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let i=0;i<t;i++)e.push(.1);const n=[...e].reverse();n.pop();return n.concat(e)}getAverageAmplitude(){if(this.useFallbackMode||!this.analyser||!this.dataArray)return.5+.3*Math.sin(.002*this.fallbackTime);this.analyser.getByteFrequencyData(this.dataArray);let t=0;for(let n=0;n<this.dataArray.length;n++)t+=this.dataArray[n];const e=t/this.dataArray.length/255;return 0===e?.5+.3*Math.sin(.002*this.fallbackTime):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)}))}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 Ht{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=vt.getState();"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;console.error("VideoManager: Video error",e.error)})),e(this,"handleAutoVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()})),e(this,"handleManualVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()}));const t=Lt.getDeviceInfo();this.deviceHandler=function(t){return t.isMobile?new Ft(t):new Ut(t)}(t),this.transcriptManager=new Dt,this.audioVisualizationManager=new Nt,this.deviceChangeCleanup=Lt.onDeviceChange((t=>{this.deviceHandler.updateDeviceInfo(t)}))}getDeviceInfo(){return Lt.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);vt.getState().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)},on90PercentReached:()=>{if(this.container){const t=new CustomEvent("video90PercentReached",{bubbles:!0,detail:{timestamp:Date.now()}});this.container.dispatchEvent(t)}}};if(this.controls=new Rt(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}swapVideos(){const t=this.getActiveVideo(),e=this.getInactiveVideo();if(!t||!e)return;t.pause();const n=vt.getState();e.muted=n.isMuted,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)return;if(!t||""===t.trim())throw new Error("Cannot load video: No video URL provided for this step");this.controls&&this.controls.reset90PercentTrigger();const i=vt.getState();n.muted=i.isMuted;try{this.controls&&this.controls.reset();const i=(null==(e=vt.getState().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}i&&this.currentVideoUrl&&n.currentTime>0&&this.playbackPositions.set(this.currentVideoUrl,n.currentTime);if(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(s){if(console.error("VideoManager: Failed to load video:",s),s&&"object"==typeof s&&"videoUrl"in s)throw s;const e=new Error("Failed to load video");throw e.videoUrl=t,e.mediaErrorCode=null,e.mediaErrorMessage=null,e.failureReason="load_error",e}}preloadNextVideo(t){if(!t||this.preloadedVideos.has(t))return;if(this.currentVideoUrl===t)return;if(this.nextVideoUrl===t)return;const e=this.getInactiveVideo();if(e){this.nextVideoUrl=t,e.src=t,e.load(),e.preload="auto";const n=vt.getState();e.muted=n.isMuted}else 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=vt.getState();if(((null==(t=n.playlistOptions)?void 0:t.persistence)??!0)&&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");vt.getState().setAutoplayFallback()}))}pause(){const t=this.getActiveVideo();t&&(t.paused||(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,null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null),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(),null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null),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(){const t=this.currentVideo,e=this.nextVideo;t&&(t.addEventListener("ended",this.handleVideoEnded),t.addEventListener("error",this.handleVideoError)),e&&(e.addEventListener("ended",this.handleVideoEnded),e.addEventListener("error",this.handleVideoError))}removeEventListeners(){const t=this.currentVideo,e=this.nextVideo;t&&(t.removeEventListener("ended",this.handleVideoEnded),t.removeEventListener("error",this.handleVideoError)),e&&(e.removeEventListener("ended",this.handleVideoEnded),e.removeEventListener("error",this.handleVideoError))}setMuted(t){this.currentVideo&&(this.currentVideo.muted=t),this.nextVideo&&(this.nextVideo.muted=t),this.controls&&this.controls.setMuted(t)}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,null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null))}hasUserInteractedWith(){return this.hasUserInteracted}resetUserInteraction(){this.hasUserInteracted=!1,null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null)}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)=>{if(!this.soundbarElement)return;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.height=`${r}%`;const a=180+Math.abs(n-5)/5*120;s.style.backgroundColor=`hsla(${a}, 70%, 60%, 1)`}))}))}catch(e){console.error("VideoManager: Failed to initialize audio visualization",e)}}initializeAudioForVideo(){const t=this.getActiveVideo();if(t)try{this.audioVisualizationManager.initialize(t)}catch(e){console.error("VideoManager: Failed to initialize audio for video",e)}}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 Yt=3e4,$t=500,Xt=100,jt=5e3,Wt=500,qt=10;class Zt{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,"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){this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null),this.targetMutationObserver=new MutationObserver((async(n,i)=>{if(this.isAutoplayBlocked())return i.disconnect(),void(this.targetMutationObserver=null);const s=await this.findElementAndScrollIntoView(t);s&&(i.disconnect(),this.targetMutationObserver=null,e(s))})),this.targetMutationObserver.observe(document.body,{childList:!0,subtree:!0});const n=setInterval((()=>{if(!this.targetMutationObserver||this.isAutoplayBlocked())return clearInterval(n),void(this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null));const i=this.findElement(t);i&&(clearInterval(n),this.targetMutationObserver.disconnect(),this.targetMutationObserver=null,e(i))}),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){const e=document.querySelectorAll(t);if(0===e.length)return null;if(1===e.length)return e[0];for(const a of e)if(this.isElementInViewport(a))return a.getBoundingClientRect(),a;const n=window.innerWidth/2,i=window.innerHeight/2;let s=e[0],r=1/0;for(const a of e){const t=a.getBoundingClientRect(),e=t.left+t.width/2,o=t.top+t.height/2,l=Math.sqrt(Math.pow(e-n,2)+Math.pow(o-i,2));l<r&&(r=l,s=a)}return s.getBoundingClientRect(),s}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 r of s){const t=r.getBoundingClientRect();if(!(e.top>=t.top&&e.bottom<=t.bottom&&e.left>=t.left&&e.right<=t.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){const e=this.findElement(t);return e?(this.isElementInViewport(e)||await this.scrollElementIntoView(e),e):null}create(){this.injectCursorStyles(),this.cursor=document.createElement("div"),this.cursor.className="sf-cursor",this.cursor.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#ff7614" stroke-width="2">\n <path d="M3 3L10.5 21L13.5 13.5L21 10.5L3 3Z" fill="#ff7614" />\n </svg>\n ',this.selectionElement=document.createElement("div"),this.selectionElement.className="sf-selection",document.body.appendChild(this.cursor),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})}injectCursorStyles(){const t="\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 /* 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.1));\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 ";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"===yt.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.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.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,$t))),this.isAutoplayBlocked())return;const e=await this.findElementAndScrollIntoView(t.targetSelector);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)));this.setShouldShowCursor(!0),this.currentTargetElement=e,this.addScrollListenersToParents(e);const n=e.getBoundingClientRect();this.isFirstAnimation?(this.startX=50,this.startY=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};this.targetX=this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.targetY=this.dragStartY+this.SELECTION_VERTICAL_OFFSET;if(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=`\n polygon(\n 0% 0%, /* Top-left of screen */\n 100% 0%, /* Top-right of screen */\n 100% 100%, /* Bottom-right of screen */\n 0% 100%, /* Bottom-left of screen */\n 0% ${e}px, /* Begin cutout: bottom-left of cutout */\n ${t}px ${e}px, /* Bottom-left of cutout */\n ${t}px ${e+i}px, /* Top-left of cutout */\n ${t+n}px ${e+i}px, /* Top-right of cutout */\n ${t+n}px ${e}px, /* Bottom-right of cutout */\n 0% ${e}px /* Close cutout path */\n )\n `;this.flashlightOverlay.style.setProperty("--sf-flashlight-clip",s);const r=this.lastCursorX,a=this.lastCursorY;this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${r}px ${a}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.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){e.setAttribute("stroke",t);const n=e.querySelector("path");n?n.setAttribute("fill",t):console.warn("[CursorManager.setColor] No path found in SVG")}else console.warn("[CursorManager.setColor] No SVG found in cursor")}else console.warn("[CursorManager.setColor] No cursor element");if(this.selectionElement){this.selectionElement.style.setProperty("--sf-selection-color",t);const e=this.colorToRgba(t,.1);this.selectionElement.style.setProperty("--sf-selection-bg-color",e)}}colorToRgba(t,e){const n=document.createElement("div");n.style.color=t,document.body.appendChild(n);const i=window.getComputedStyle(n).color;document.body.removeChild(n);const s=i.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);if(s){return`rgba(${s[1]}, ${s[2]}, ${s[3]}, ${e})`}return t}}class Kt{constructor(){e(this,"container",null),e(this,"buttons",[]),e(this,"buttonContainer",null),e(this,"scrollIndicator",null),e(this,"domEventListeners",new Map),e(this,"storeUnsubscribe",null),e(this,"storageManager",mt.getInstance()),e(this,"handleVideo90PercentReached",(t=>{this.showButtonsAt90Percent()}))}create(t){this.container=t,this.storeUnsubscribe=vt.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>=3,n=t.length>3;let i="sf-choice-buttons-container";n&&(i+=" sf-choice-buttons-container--scrollable"),this.buttonContainer.className=i,t.length,this.updateCenterPlayButtonPosition(e),this.container.appendChild(this.buttonContainer),n&&(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)})),n&&this.buttonContainer&&this.setupScrollIndicator(this.buttonContainer);vt.getState().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){if(!this.scrollIndicator)return;t.addEventListener("scroll",(()=>{if(!this.scrollIndicator)return;t.scrollHeight-t.scrollTop-t.clientHeight<qt?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");e&&(t?e.classList.add("sf-player__center-play-button--with-many-buttons"):e.classList.remove("sf-player__center-play-button--with-many-buttons"))}clearButtons(){this.updateCenterPlayButtonPosition(!1),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;if(vt.getState().isMinimized)return this.buttonContainer.classList.add("sf-hidden"),void(this.scrollIndicator&&this.scrollIndicator.classList.add("sf-hidden"));this.buttonContainer.classList.remove("sf-hidden"),this.scrollIndicator&&this.scrollIndicator.classList.remove("sf-hidden"),this.buttonContainer.className="sf-choice-buttons-container"}setupDOMInteractions(t){this.clearDOMInteractions(),t.forEach(((t,e)=>{try{const n=document.querySelectorAll(t.selector);if(0===n.length)return void t.selector;n.length,t.selector,n.forEach(((n,i)=>{const s=n,r=`dom-interaction-${e}-${i}-${Date.now()}`,a=e=>{this.handleDOMInteraction(e,t)};s.addEventListener(t.action,a),this.domEventListeners.set(r,{element:s,listener:a,type:t.action}),t.action,t.selector}))}catch(n){console.error(`InteractionManager: Error setting up DOM interaction for selector "${t.selector}":`,n)}}))}clearDOMInteractions(){this.domEventListeners.forEach((({element:t,listener:e,type:n})=>{try{t.removeEventListener(n,e)}catch(i){console.error("InteractionManager: Error removing event listener:",i)}})),this.domEventListeners.clear()}async handleButtonClick(t,e){var n,i,s,r,a,o;e.id,t.preventDefault(),t.stopPropagation();const l=vt.getState();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=vt.getState();if(t.manifest){vt.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(c){console.error("InteractionManager: Full error:",c)}if((null==(r=t.playlistOptions)?void 0:r.persistence)??!0){const n=null==(a=t.user)?void 0:a.id,i=vt.getState();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,lastProgressAt:Date.now()},this.storageManager.setAnonymousUserData(n),e.action.target)}}}e.action.url,window.location.href=e.action.url}else e.action.target,l.goToStep(e.action.target);break;case"url":if(e.action.target,await this.flushAnalytics(),"completedWaitingForInteraction"===l.currentState)l.completePlaylist(),await new Promise((t=>setTimeout(t,Xt)));else{this.isCurrentStepLast(l)&&(l.goToStep("completed"),await new Promise((t=>setTimeout(t,Xt))))}window.open(e.action.target,"_blank");const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ye)),d=t.getInstance();d&&d.destroy();break;case"playlist":e.action.target;try{await this.flushAnalytics(),l.completePlaylist(),await new Promise((t=>setTimeout(t,Xt)));const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ye)),n=t.getInstance();n&&(e.action.target,await n.startPlaylist(e.action.target))}catch(c){console.error(`InteractionManager: Error starting playlist "${e.action.target}":`,c),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)}}handleDOMInteraction(t,e){if(e.action,e.selector,e.waitFor&&(t.preventDefault(),t.stopPropagation(),e.selector),"input"===e.action&&e.value){const n=t.target;n&&(n.value=e.value,e.value)}if(vt.getState().manifest){const t={selector:e.selector,action:e.action,value:e.value};JSON.stringify(t)}}isCurrentStepLast(t){if(!t.manifest||!t.currentStepId||!t.manifest.steps)return!1;const e=t.manifest.steps;return e.findIndex((e=>e.id===t.currentStepId))===e.length-1}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.clearDOMInteractions(),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.clearDOMInteractions(),this.container=null}}function Jt(){try{return vt.getState()}catch(t){return null}}class Gt{constructor(t){e(this,"config",null),e(this,"user",null),e(this,"eventQueue",[]),e(this,"isSending",!1),e(this,"flushInterval",null),e(this,"eventManager",null),e(this,"sessionId",null),e(this,"analyticsEnabled",!0),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}subscribeToEvents(){this.eventManager&&(this.eventManager.on("playerPaused",(t=>{const e=Jt(),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=Jt(),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=Jt(),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=Jt(),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()})})))}initialize(t,e){this.config=t,this.analyticsEnabled=!1!==t.enableAnalytics,e&&(this.sessionId=e),this.analyticsEnabled&&(this.flushInterval=window.setInterval((()=>{this.flushEvents()}),Yt))}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}}}destroy(){this.analyticsEnabled&&this.flushEvents(),null!==this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=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||mt.getInstance(),this.sessionId=this.getOrCreateSession(),this.sessionId}getOrCreateSession(){if("undefined"==typeof window)return this.generateUniqueId();const t=this.storageManager.getSession();if(t){if(Date.now()-t.lastActivity<it)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,"triggerManager",null),e(this,"handleURLChange",(()=>{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){if(!this.validateCurrentStepUrl())return}if(this.triggerManager&&this.triggerManager.evaluateAllTriggers(),e)for(const[n,i]of t){if(!i.data)continue;const{pattern:t,nextStepId:e}=i.data;if(this.isURLPathMatch(t)){this.triggerTransition(e);break}}})),window.addEventListener("popstate",this.handleURLChange),this.monitorHistoryChanges()}setTriggerManager(t){this.triggerManager=t}monitorHistoryChanges(){const t=history.pushState,e=history.replaceState;history.pushState=(...e)=>{t.apply(history,e),this.handleURLChange()},history.replaceState=(...t)=>{e.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;if(this.willCauseHardRefresh(e)){t.preventDefault(),t.stopImmediatePropagation();await this.triggerTransitionWithProgress(n)&&this.reDispatchClick(t)}else this.triggerTransition(n)};s.set(t,e),t.addEventListener("click",e,{capture:!0})})))},o=document.querySelectorAll(e);a(o),r=new MutationObserver((t=>{for(const n of t)"childList"===n.type&&n.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;n.matches(e)&&a([n]);const i=n.querySelectorAll(e);i.length>0&&(i.length,a(i))}}))})),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.isURLPathMatch(e)){this.triggerTransition(n);const t=5;let e=0;const i=()=>{if(e>=t)return;e++;const s=vt.getState();"waitingForInteraction"===s.currentState||"playing"===s.currentState?(s.currentState,this.triggerTransition(n)):e<t&&(s.currentState,setTimeout(i,Wt))};setTimeout(i,Wt)}const i=`url-path-${Date.now()}`,s=window.setInterval((()=>{this.isURLPathMatch(e)&&(clearInterval(s),this.triggerTransition(n))}),jt);this.activeTransitions.set(i,{handlers:new Map,cleanup:()=>{clearInterval(s)},data:{type:"url-path",pattern:e,nextStepId:n}})}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),r=s.test(e),a=s.test(n);return r||a}validateUrlRequirement(t){const{pattern:e,matchType:n}=t;if(!e)return!0;const i=window.location.href,s=window.location.pathname;if("regex"===n)try{const t=new RegExp(e),n=t.test(i),r=t.test(s),a=n||r;return a}catch(r){return!1}if("contains"===n){return i.includes(e)||s.includes(e)}return i===e||s===e}handleUrlRequirementFailure(t,e){e.pattern,e.matchType,this.cleanupTransitions();const n=window._saltfishPlayer;n&&"function"==typeof n.destroy&&n.destroy()}validateCurrentStepUrl(){const t=vt.getState(),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=this.validateUrlRequirement(i.urlRequirement);return s||this.handleUrlRequirementFailure(n,i.urlRequirement),s}triggerTransition(t){var e;const n=vt.getState(),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=vt.getState(),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,Xt))),!0}catch(s){return!1}}cleanupTransitions(){this.activeTransitions.forEach((t=>{t.cleanup()})),this.activeTransitions.clear(),this.waitingForInteraction=!1}setWaitingForInteraction(t){this.waitingForInteraction=t}isWaitingForInteraction(){return this.waitingForInteraction}reset(){this.cleanupTransitions()}destroy(){this.cleanupTransitions(),window.removeEventListener("popstate",this.handleURLChange)}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=document.querySelector(e);c?l(c):(r=new MutationObserver((t=>{for(const n of t)if("childList"===n.type&&n.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;if(n.matches(e))return void l(n);const i=n.querySelector(e);if(i)return void l(i)}})),!r)break})),r.observe(document.body,{childList:!0,subtree:!0}),o=window.setInterval((()=>{if(!r)return void(o&&clearInterval(o));const t=document.querySelector(e);t&&t.offsetWidth>0&&t.offsetHeight>0&&(o&&clearInterval(o),o=null,l(t))}),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(n){}}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(e){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.once})),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)this.evaluatePlaylistTrigger(t)}evaluatePlaylistTrigger(t){var e,n,i;if(!t.triggers)return;const{triggers:s}=t,r=t.id;if(this.triggeredPlaylistsSet.has(r))return;const a=vt.getState();if(!a.user)return;const o=[],l=this.evaluateOnceCondition(s.once,r,(null==(e=a.userData)?void 0:e.watchedPlaylists)||{});o.push(l);const c=this.evaluateURLCondition(s);o.push(c),s.url;const d=this.evaluatePlaylistSeenCondition(s.playlistSeen,(null==(n=a.userData)?void 0:n.watchedPlaylists)||{});o.push(d),JSON.stringify(s.playlistSeen);const h=this.evaluatePlaylistNotSeenCondition(s.playlistNotSeen,(null==(i=a.userData)?void 0:i.watchedPlaylists)||{});o.push(h),JSON.stringify(s.playlistNotSeen);const u=this.evaluateElementClickCondition(s.elementClicked);o.push(u),s.elementClicked;const p=this.evaluateElementVisibleCondition(s.elementVisible);o.push(p),s.elementVisible;const g=this.applyOperators(o,s.operators);s.operators.join(", "),g&&this.triggerPlaylist(r)}evaluateOnceCondition(t,e,n){if(!t)return!0;return!(n&&n[e])}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(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(c){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&&"in_progress"!==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){if(!t)return!0;return this.clickedElements.has(t)}evaluateElementVisibleCondition(t){if(!t)return!0;return this.visibleElements.has(t)}setupElementClickListeners(){this.clearElementClickListeners(),this.triggeredPlaylists.forEach((t=>{var e;(null==(e=t.triggers)?void 0:e.elementClicked)&&this.setupElementClickListener(t.id,t.triggers.elementClicked)}))}setupElementClickListener(t,e){try{const n=document.querySelector(e);if(!n)return;if(!this.triggeredPlaylists.find((e=>e.id===t)))return;const i=t=>{t.preventDefault(),t.stopPropagation(),this.clickedElements.add(e),this.evaluateAllTriggers()};n.addEventListener("click",i);const s=`${t}-${e}`;this.elementClickedListeners.set(s,{element:n,listener:i,selector:e})}catch(n){}}clearElementClickListeners(){this.elementClickedListeners.forEach((({element:t,listener:e})=>{try{t.removeEventListener("click",e)}catch(n){console.error("TriggerManager: Error removing element click listener:",n)}})),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)}))}setupElementVisibleObserver(t,e){try{const n=`${t}-${e}`;if(this.elementVisibleObservers.has(n))return;const i=t=>{const i=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});i.observe(t);const s=this.elementVisibleObservers.get(n);s?(s.mutationObserver&&s.mutationObserver.disconnect(),this.elementVisibleObservers.set(n,{observer:i,mutationObserver:null,selector:e})):this.elementVisibleObservers.set(n,{observer:i,mutationObserver:null,selector:e})},s=document.querySelector(e);if(s)i(s);else{const t=new MutationObserver((t=>{for(const n of t)"childList"===n.type&&n.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;if(n.matches(e))i(n);else{const t=n.querySelector(e);t&&i(t)}}}))}));t.observe(document.body,{childList:!0,subtree:!0}),this.elementVisibleObservers.set(n,{observer:null,mutationObserver:t,selector:e})}}catch(n){}}clearElementVisibleObservers(){this.elementVisibleObservers.forEach((({observer:t,mutationObserver:e})=>{try{t&&t.disconnect(),e&&e.disconnect()}catch(n){console.error("TriggerManager: Error removing element visibility observer:",n)}})),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)}}resetTriggeredPlaylists(){this.triggeredPlaylistsSet.clear()}getTriggeredPlaylists(){return Array.from(this.triggeredPlaylistsSet)}destroy(){this.stopMonitoring(),this.clearElementClickListeners(),this.clearElementVisibleObservers(),this.triggeredPlaylists=[],this.triggeredPlaylistsSet.clear(),this.clickedElements.clear(),this.visibleElements.clear()}}class ne{constructor(t){e(this,"eventManager",null),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}subscribeToEvents(){this.eventManager&&this.eventManager.on("playlistStarted",(t=>{this.trackTestParticipation(t.playlist.id)}))}initializeTests(t){vt.getState().setABTests(t)}assignUserToTests(t,e,n){var i,s;const r=vt.getState(),a=r.abTests||[],o={...e};for(const l of a){const e=l.testType||"percentage";if("userList"!==e&&o[l.id])continue;let a=!1;if("userList"===e){a=!(!0===(null==(s=null==(i=r.user)?void 0:i.userData)?void 0:s.__isAnonymous))&&!0===(null==n?void 0:n[l.id])}else a=this.isUserInTest(t,l);o[l.id]={testId:l.id,assigned:a,assignedAt:Date.now()},l.name}return r.setABTestAssignments(o),o}isUserInTest(t,e){if(!e.percentage)return!1;const n=`${t}_${e.id}`;let i=0;for(let s=0;s<n.length;s++){i=(i<<5)-i+n.charCodeAt(s),i|=0}return Math.abs(i)%100<e.percentage}getFilteredPlaylists(t){const e=vt.getState(),n=e.abTests||[],i=e.abTestAssignments||{};if(0===n.length)return t;const s=new Set;for(const a of n){const t=i[a.id];t&&t.assigned||(s.add(a.playlistId),a.playlistId,a.name)}const r=t.filter((t=>!s.has(t.id)));return t.length,r.length,r}trackTestParticipation(t){var e;const n=vt.getState(),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 vt.getState().abTestAssignments||{}}isPlaylistAvailable(t){const e=vt.getState(),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=vt.getState(),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(i){console.error(`Error in ${t} event handler:`,i)}})))}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(s){const t=s instanceof Error?s.message:"Unknown error";throw K("[PlaylistLoader] Failed to load manifest:",s),new Error(`Unable to load playlist manifest: ${t}`)}}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 K("[PlaylistLoader] Fetch/parse failed:",e),K("[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 s of n)if(!(s in e))throw new Error(`Manifest missing required field: ${s}`);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 s of i){if("object"!=typeof s||null===s)throw new Error("Each step must be an object");const t=s;if(!t.id)throw new Error("Each step must have an id");if(!t.transitions||!Array.isArray(t.transitions))throw new Error(`Step '${t.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;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}=St(e);if(n){const n=e.currentStepId||e.lastStepId;if(n){t.steps.find((t=>t.id===n))&&(a=n)}}else a=t.startStep}}return a}}class re{constructor(t,n){e(this,"eventManager",null),e(this,"isUpdatingWatchedPlaylists",!1),e(this,"playlistLoader"),e(this,"storageManager"),this.playlistLoader=new se,this.storageManager=n||mt.getInstance(),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}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,l;if(!this.isUpdatingWatchedPlaylists){this.isUpdatingWatchedPlaylists=!0;try{const d=Jt();if(!d)return;const h=d.userData||{},u=h.watchedPlaylists||{},p={status:e,currentStepId:"completed"===e?null:n||d.currentStepId||null,timestamp:Date.now(),lastProgressAt:Date.now()},g={...u,[t]:p};if(d.setUserData({...h,watchedPlaylists:g}),!(null==(i=null==d?void 0:d.config)?void 0:i.token)||!(null==(s=null==d?void 0:d.user)?void 0:s.id)||(null==(r=null==d?void 0:d.user)?void 0:r.__isAnonymous))return null==(a=null==d?void 0:d.config)||a.token,null==(o=null==d?void 0:d.user)||o.id,null==(l=null==d?void 0:d.user)||l.__isAnonymous,void this.updateAnonymousUserWatchedPlaylists(t,e,n||d.currentStepId||null);const m=`https://player.saltfish.ai/clients/${d.config.token}/users/${d.user.id}/playlists/${t}`;try{const t=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:e,currentStepId:n||d.currentStepId||null})});if(!t.ok)throw new Error(`Failed to update watched playlist status: ${t.statusText} (${t.status})`)}catch(c){console.error(`PlaylistManager: Error updating watched playlist status for ${t}:`,c)}}finally{this.isUpdatingWatchedPlaylists=!1}}}updateAnonymousUserWatchedPlaylists(t,e,n){if("undefined"==typeof window)return;let i=this.storageManager.getAnonymousUserData()||{userId:"anonymous",userData:{},watchedPlaylists:{},timestamp:Date.now()};i.watchedPlaylists||(i.watchedPlaylists={}),i.watchedPlaylists[t]={status:e,currentStepId:n||null,timestamp:Date.now(),lastProgressAt:Date.now()},i.timestamp=Date.now(),this.storageManager.setAnonymousUserData(i)}async load(t,e){var n;try{const i=Jt();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(i){const t=Jt(),e=i instanceof Error?i:new Error("Unknown error loading manifest");t?t.setError(e):console.error("[PlaylistManager] Cannot set error: Store not available",e)}}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='\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 ',this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(vt.getState().isMinimized)}handleClick(){const t=vt.getState(),e=!t.isMinimized;e?t.minimize():t.maximize(),e?this.minimize():this.maximize()}minimize(){this.button.innerHTML='\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 '}maximize(){this.button.innerHTML='\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 '}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='\n <svg 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 ',this.playButton.addEventListener("click",this.handlePlayClick.bind(this)),this.container.appendChild(this.playButton)}handlePlayClick(t){t&&t.stopPropagation();const e=vt.getState();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='\n <svg width="18" height="18" 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 ',this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(vt.getState().isMinimized)}handleClick(t){t.stopPropagation();vt.getState().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=ct,this.errorOverlay.classList.add("sf-hidden");const t=document.createElement("div");t.className=ht;const e=document.createElement("p");e.className=ut,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(dt)}))}hide(){this.isVisible&&(this.errorOverlay.classList.remove(dt),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(`.${ut}`);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=`${pt}`,this.spinnerElement.innerHTML='\n <div class="sf-loading-spinner__content">\n <div class="sf-loading-spinner__icon">\n <svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">\n \x3c!-- Static Saltfish logo in center --\x3e\n <g transform="translate(10, 10) scale(0.656)">\n <g clip-path="url(#saltfish-clip)">\n <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"/>\n <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"/>\n </g>\n <defs>\n <clipPath id="saltfish-clip">\n <rect width="61" height="61" fill="white"/>\n </clipPath>\n </defs>\n </g>\n \n \x3c!-- Animated circular ring around logo --\x3e\n <circle cx="30" cy="30" r="28" \n stroke="black" stroke-width="2" \n fill="none" stroke-linecap="round"\n stroke-dasharray="8 6" stroke-opacity="0.3">\n <animateTransform attributeName="transform" \n type="rotate" \n values="0 30 30;360 30 30" \n dur="2s" \n repeatCount="indefinite"/>\n </circle>\n </svg>\n </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,"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=vt.getState();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=>{const e=vt.getState();if(e.isMinimized)return t.stopPropagation(),void this.handleMinimizeClick();const n=t.target;"BUTTON"===n.tagName||n.closest("button")||n.closest(".sf-controls-container")||"playing"===e.currentState&&e.pause()}))}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=vt.getState();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(at):this.playerElement.classList.remove(at)}handleMinimizeClick(){if(!this.playerElement)return;const t=vt.getState(),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=rt,t.appendChild(e),e}createControlsContainer(t){const e=document.createElement("div");return e.className=ot,t.appendChild(e),e}createSaltfishLogo(t){var e;if(!1===(null==(e=vt.getState().config)?void 0:e.showLogo))return;const n=document.createElement("div");n.className=lt,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=vt.getState();"playing"===n.currentState&&n.pause();const i=null==(e=n.config)?void 0:e.token;i?window.open(`https://www.saltfish.ai/demos?clientId=${i}`,"_blank"):(console.warn("UIManager: No token available, falling back to saltfish.ai homepage"),window.open("https://www.saltfish.ai/","_blank"))}))}initializeButtonManagement(){this.playerElement&&this.videoManager?(this.storeUnsubscribe=vt.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")))}createCenterPlayButton(){this.playerElement&&(this.centerPlayButton=document.createElement("button"),this.centerPlayButton.className="sf-player__center-play-button",this.centerPlayButton.innerHTML='\n <svg 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 ',this.playerElement.appendChild(this.centerPlayButton),this.centerPlayButton.addEventListener("click",(t=>{var e;t.stopPropagation(),t.preventDefault();const n=vt.getState();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();"paused"!==n.currentState&&"waitingForInteraction"!==n.currentState&&"completedWaitingForInteraction"!==n.currentState&&"autoplayBlocked"!==n.currentState&&"idleMode"!==n.currentState&&"error"!==n.currentState||n.play()})))}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.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;this.currentStepId;if(!("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",nt);let pe=ue;class ge{createManagers(){const t=mt.getInstance(),e=new Qt(t),n=new zt,i=new Ht,s=new ie,r=new Gt(s),a=new re(s,t),o=new ne(s),l=new Zt,c=new Kt,d=new te,h=new ee,u=new pe((()=>{}));d.setTriggerManager(h);return{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(e){console.error("ManagerFactory: Error resetting managers:",e)}}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(e){console.error("ManagerFactory: Error destroying managers:",e)}}}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),t.instance)throw new Error("SaltfishPlayer is a singleton. Use getInstance()");this.managerFactory=new ge;const n=this.managerFactory.createManagers();this.playerInitializationService=new Et(n),this.userManagementService=new It(n),this.playlistOrchestrator=new xt(n),this.stateMachineActionHandler=new Ct(n),this.managerOrchestrator=new At(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())),vt.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)console.warn("Saltfish playlist Player is already initialized");else 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(e){throw e}}identifyUser(t,e){this.userManagementService.identifyUser(t,e)}async identifyAnonymous(t){await this.userManagementService.identifyAnonymous(t)}async startPlaylist(t,e){await this.playlistOrchestrator.startPlaylist(t,e)}resetPlaylist(){this.playlistOrchestrator.resetPlaylist()}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="0.3.12";const be=function(){const t=fe.getInstance();let e=!1,n=!1,i=null;const s=[],r={init:r=>{if(n)return q("Saltfish already initialized"),Promise.resolve();if(e&&i)return i;const a={enableAnalytics:!0,..."string"==typeof r?{token:r}:r};return q(`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 e=s.shift();if(e)try{await e()}catch(t){K("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(i){n(i)}})),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()})):Z("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):Z("Cannot destroy - Saltfish not initialized")},getSessionId:()=>t.getSessionId(),getRunId:()=>t.getRunId(),version:()=>ve};return r.__dev__={getDeviceInfo:()=>Lt.getDeviceInfo()},r}();return"undefined"!=typeof window&&(window.saltfish=be),be}));
|
|
8
|
+
!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={},i=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};var s=Symbol.for("immer-nothing"),r=Symbol.for("immer-draftable"),a=Symbol.for("immer-state");function o(t,...e){throw new Error(`[Immer] minified error nr: ${t}. Full error at: https://bit.ly/3cXEKWf`)}var l=Object.getPrototypeOf;function c(t){return!!t&&!!t[a]}function d(t){var e;return!!t&&(u(t)||Array.isArray(t)||!!t[r]||!!(null==(e=t.constructor)?void 0:e[r])||y(t)||v(t))}var h=Object.prototype.constructor.toString();function u(t){if(!t||"object"!=typeof t)return!1;const e=l(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)===h}function p(t,e){0===g(t)?Reflect.ownKeys(t).forEach((n=>{e(n,t[n],t)})):t.forEach(((n,i)=>e(i,n,t)))}function g(t){const e=t[a];return e?e.type_:Array.isArray(t)?1:y(t)?2:v(t)?3:0}function m(t,e){return 2===g(t)?t.has(e):Object.prototype.hasOwnProperty.call(t,e)}function f(t,e,n){const i=g(t);2===i?t.set(e,n):3===i?t.add(n):t[e]=n}function y(t){return t instanceof Map}function v(t){return t instanceof Set}function b(t){return t.copy_||t.base_}function S(t,e){if(y(t))return new Map(t);if(v(t))return new Set(t);if(Array.isArray(t))return Array.prototype.slice.call(t);const n=u(t);if(!0===e||"class_only"===e&&!n){const e=Object.getOwnPropertyDescriptors(t);delete e[a];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(l(t),e)}{const e=l(t);if(null!==e&&n)return{...t};const i=Object.create(e);return Object.assign(i,t)}}function w(t,e=!1){return M(t)||c(t)||!d(t)||(g(t)>1&&(t.set=t.add=t.clear=t.delete=E),Object.freeze(t),e&&Object.entries(t).forEach((([t,e])=>w(e,!0)))),t}function E(){o(2)}function M(t){return Object.isFrozen(t)}var I,P={};function x(t){const e=P[t];return e||o(0),e}function C(){return I}function T(t,e){e&&(x("Patches"),t.patches_=[],t.inversePatches_=[],t.patchListener_=e)}function k(t){_(t),t.drafts_.forEach(z),t.drafts_=null}function _(t){t===I&&(I=t.parent_)}function A(t){return I={drafts_:[],parent_:I,immer_:t,canAutoFreeze_:!0,unfinalizedDrafts_:0}}function z(t){const e=t[a];0===e.type_||1===e.type_?e.revoke_():e.revoked_=!0}function L(t,e){e.unfinalizedDrafts_=e.drafts_.length;const n=e.drafts_[0];return void 0!==t&&t!==n?(n[a].modified_&&(k(e),o(4)),d(t)&&(t=O(e,t),e.parent_||D(e,t)),e.patches_&&x("Patches").generateReplacementPatches_(n[a].base_,t,e.patches_,e.inversePatches_)):t=O(e,n,[]),k(e),e.patches_&&e.patchListener_(e.patches_,e.inversePatches_),t!==s?t:void 0}function O(t,e,n){if(M(e))return e;const i=e[a];if(!i)return p(e,((s,r)=>V(t,i,e,s,r,n))),e;if(i.scope_!==t)return e;if(!i.modified_)return D(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),p(s,((s,a)=>V(t,i,e,s,a,n,r))),D(t,e,!1),n&&t.patches_&&x("Patches").generatePatches_(i,n,t.patches_,t.inversePatches_)}return i.copy_}function V(t,e,n,i,s,r,a){if(c(s)){const a=O(t,s,r&&e&&3!==e.type_&&!m(e.assigned_,i)?r.concat(i):void 0);if(f(n,i,a),!c(a))return;t.canAutoFreeze_=!1}else a&&n.add(s);if(d(s)&&!M(s)){if(!t.immer_.autoFreeze_&&t.unfinalizedDrafts_<1)return;O(t,s),e&&e.scope_.parent_||"symbol"==typeof i||!Object.prototype.propertyIsEnumerable.call(n,i)||D(t,s)}}function D(t,e,n=!1){!t.parent_&&t.immer_.autoFreeze_&&t.canAutoFreeze_&&w(e,n)}var B={get(t,e){if(e===a)return t;const n=b(t);if(!m(n,e))return function(t,e,n){var i;const s=R(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_||!d(i)?i:i===U(t.base_,e)?(H(t),t.copy_[e]=Y(i,t)):i},has:(t,e)=>e in b(t),ownKeys:t=>Reflect.ownKeys(b(t)),set(t,e,n){const i=R(b(t),e);if(null==i?void 0:i.set)return i.set.call(t.draft_,n),!0;if(!t.modified_){const i=U(b(t),e),o=null==i?void 0:i[a];if(o&&o.base_===n)return t.copy_[e]=n,t.assigned_[e]=!1,!0;if(((s=n)===(r=i)?0!==s||1/s==1/r:s!=s&&r!=r)&&(void 0!==n||m(t.base_,e)))return!0;H(t),N(t)}var s,r;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,H(t),N(t)):delete t.assigned_[e],t.copy_&&delete t.copy_[e],!0),getOwnPropertyDescriptor(t,e){const n=b(t),i=Reflect.getOwnPropertyDescriptor(n,e);return i?{writable:!0,configurable:1!==t.type_||"length"!==e,enumerable:i.enumerable,value:n[e]}:i},defineProperty(){o(11)},getPrototypeOf:t=>l(t.base_),setPrototypeOf(){o(12)}},F={};function U(t,e){const n=t[a];return(n?b(n):t)[e]}function R(t,e){if(!(e in t))return;let n=l(t);for(;n;){const t=Object.getOwnPropertyDescriptor(n,e);if(t)return t;n=l(n)}}function N(t){t.modified_||(t.modified_=!0,t.parent_&&N(t.parent_))}function H(t){t.copy_||(t.copy_=S(t.base_,t.scope_.immer_.useStrictShallowCopy_))}p(B,((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 B.set.call(this,t[0],e,n,t[0])};function Y(t,e){const n=y(t)?x("MapSet").proxyMap_(t,e):v(t)?x("MapSet").proxySet_(t,e):function(t,e){const n=Array.isArray(t),i={type_:n?1:0,scope_:e?e.scope_:C(),modified_:!1,finalized_:!1,assigned_:{},parent_:e,base_:t,draft_:null,copy_:null,revoke_:null,isManual_:!1};let s=i,r=B;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_:C()).drafts_.push(n),n}function $(t){if(!d(t)||M(t))return t;const e=t[a];let n;if(e){if(!e.modified_)return e.base_;e.finalized_=!0,n=S(t,e.scope_.immer_.useStrictShallowCopy_)}else n=S(t,!0);return p(n,((t,e)=>{f(n,t,$(e))})),e&&(e.finalized_=!1),n}var X=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 i;if("function"!=typeof e&&o(6),void 0!==n&&"function"!=typeof n&&o(7),d(t)){const s=A(this),r=Y(t,void 0);let a=!0;try{i=e(r),a=!1}finally{a?k(s):_(s)}return T(s,n),L(i,s)}if(!t||"object"!=typeof t){if(i=e(t),void 0===i&&(i=t),i===s&&(i=void 0),this.autoFreeze_&&w(i,!0),n){const e=[],s=[];x("Patches").generateReplacementPatches_(t,i,e,s),n(e,s)}return i}o(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){d(t)||o(8),c(t)&&(t=function(t){c(t)||o(10);return $(t)}(t));const e=A(this),n=Y(t,void 0);return n[a].isManual_=!0,_(e),n}finishDraft(t,e){const n=t&&t[a];n&&n.isManual_||o(9);const{scope_:i}=n;return T(i,e),L(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=x("Patches").applyPatches_;return c(t)?i(t,e):this.produce(t,(t=>i(t,e)))}},j=X.produce;X.produceWithPatches.bind(X),X.setAutoFreeze.bind(X),X.setUseStrictShallowCopy.bind(X),X.applyPatches.bind(X),X.createDraft.bind(X),X.finishDraft.bind(X);const W=t=>(e,n,i)=>(i.setState=(t,n,...i)=>{const s="function"==typeof t?j(t):t;return e(s,n,...i)},t(i.setState,n,i));function q(t,e){void 0!==e?console.info(t,e):console.info(t)}function Z(t,e){console.warn(t)}function K(t,e){void 0!==e?console.error(t,e):console.error(t)}class J{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.setupDefaultActions(),this.runEntryActions(this.currentState)}setupDefaultActions(){this.actionHandlers={...this.actionHandlers,logStateEntry:t=>{this.currentState},logErrorEvent:(t,e)=>{"ERROR"===(null==e?void 0:e.type)&&e.error.message},logStepTransition:(t,e)=>{"TRANSITION_TO_STEP"===(null==e?void 0:e.type)&&e.step.id},logErrorRecovery:()=>{}}}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];if(!e)return t.type,this.currentState,this.currentState;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;return this.currentState=e.target,this.runEntryActions(this.currentState),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"}},entry:["logStateEntry"]},loading:{on:{MANIFEST_LOADED:{target:"paused"},ERROR:{target:"error",actions:["logErrorEvent"]}},entry:["logStateEntry","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",actions:["logStepTransition"]},ERROR:{target:"error"},COMPLETE_PLAYLIST:{target:"completed"},COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION:{target:"completedWaitingForInteraction"}},entry:["logStateEntry","startVideoPlayback","showVideoControls","hidePlayButton"],exit:["pauseVideoPlayback"]},paused:{on:{PLAY:{target:"playing"},START_IDLE_MODE:{target:"idleMode"},MINIMIZE:{target:"minimized"},TRANSITION_TO_STEP:{target:"playing",actions:["logStepTransition"]}},entry:["logStateEntry","pauseVideoPlayback","showPlayButton"]},minimized:{on:{MAXIMIZE:{target:"paused"},EXIT:{target:"closing"}},entry:["logStateEntry","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",actions:["logStepTransition"]}},entry:["logStateEntry","showPlayButton"]},autoplayBlocked:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["logStateEntry","startMutedLoopedVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls"]},idleMode:{on:{PLAY:{target:"playing"},TRANSITION_TO_STEP:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["logStateEntry","startIdleModeVideo","hideVideoControls","showPlayButton","enablePlayButtonProminent"],exit:["disablePlayButtonProminent","showVideoControls"]},error:{on:{INITIALIZE:{target:"idle"},PLAY:{target:"playing",actions:["logErrorRecovery"]},AUTOPLAY_FALLBACK:{target:"autoplayBlocked"}},entry:["logStateEntry","handleError","showPlayButton"]},completedWaitingForInteraction:{on:{COMPLETE_PLAYLIST:{target:"completed"},INITIALIZE:{target:"idle"},TRANSITION_TO_STEP:{target:"playing",actions:["logStepTransition"]},PLAY:{target:"playing"},MINIMIZE:{target:"minimized"}},entry:["logStateEntry","showPlayButton"]},completed:{on:{INITIALIZE:{target:"idle"}},entry:["logStateEntry","trackPlaylistComplete"]},closing:{on:{},entry:["logStateEntry","triggerPlaylistDismissed"]}}},Q="saltfish_progress",tt="saltfish_session",et="saltfish_anonymous_user_data",nt=12e4,it=18e5,st="https://player.saltfish.ai",rt="sf-player",at="sf-player--minimized",ot="sf-controls-container",lt="sf-player__logo",ct="sf-error-display",dt="sf-error-display--visible",ht="sf-error-display__content",ut="sf-error-display__message",pt="sf-loading-spinner",gt=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(i){}}return!1}}safeClearItem(t){if(this.isLocalStorageAvailable)try{localStorage.removeItem(t)}catch(e){}}clearOldData(){this.safeClearItem(tt)}getProgress(t){const e=this.safeGetItem(Q);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(Q,n)}clearProgress(){this.safeClearItem(Q)}getSession(){return this.safeGetItem(tt)}setSession(t){return this.safeSetItem(tt,t)}clearSession(){this.safeClearItem(tt)}getAnonymousUserData(){return this.safeGetItem(et)}setAnonymousUserData(t){return this.safeSetItem(et,t)}clearAnonymousUserData(){this.safeClearItem(et)}getAnonymousUserId(){const t=this.getAnonymousUserData();return(null==t?void 0:t.userId)||null}clearAll(){this.clearProgress(),this.clearSession(),this.clearAnonymousUserData()}isStorageAvailable(){return this.isLocalStorageAvailable}getStorageInfo(){const t=[];if(this.isLocalStorageAvailable)try{for(let e=0;e<localStorage.length;e++){const n=localStorage.key(e);n&&n.startsWith("saltfish_")&&t.push(n)}}catch(e){}return{available:this.isLocalStorageAvailable,keys:t}}};e(gt,"instance",null);let mt=gt;const ft=mt.getInstance(),yt=i(W(((t,e)=>{let n=new J(G,{currentStep:null,error:null});const i=t=>n.send(t);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}))},setUserData:e=>{t((t=>{t.userData=e}))},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:s}=e();if("completed"!==n){if(s&&s.steps.some((t=>t.id===n))){const e=s.steps.find((t=>t.id===n));t((t=>{var r,a,o;t.currentStepId=n,e&&(t.currentState=i({type:"TRANSITION_TO_STEP",step:e}),(t.position||(null==(r=t.playlistOptions)?void 0:r.position))&&(t.position={x:0,y:0})),t.progress[s.id]={...t.progress[s.id],lastStepId:n,lastVisited:(new Date).toISOString()};if((null==(a=t.playlistOptions)?void 0:a.persistence)??!0){const e=null==(o=t.user)?void 0:o.id;ft.setProgress(t.progress,e)}}))}}else t((t=>{t.currentState=i({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 J(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:()=>{t((t=>{t.currentState=i({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 J(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:e=>{t((t=>{t.currentState=i(e)}))},updateProgressWithCompletion:(e,n)=>{t((t=>{var s,r;t.currentState=i({type:"COMPLETE_PLAYLIST_WAITING_FOR_INTERACTION"}),t.progress[e]={...t.progress[e],lastStepId:n,lastVisited:(new Date).toISOString(),completedWaitingForInteraction:!0};if((null==(s=t.playlistOptions)?void 0:s.persistence)??!0){const e=null==(r=t.user)?void 0:r.id;ft.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 e of i){const t=s[e.id];t&&t.assigned||r.add(e.playlistId)}return n.filter((t=>!r.has(t.id)))}}}))),vt={getState:()=>yt.getState(),setState:yt.setState,subscribe:yt.subscribe,destroy:yt.destroy};function bt(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 St(t,e=6e3){const n=bt(t);if(!n)return{isValid:!1,ageMs:null,timestampMs:null};const i=Date.now()-n;return{isValid:i<=e,ageMs:i,timestampMs:n}}class wt{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{vt.getState().setError(t)}catch(e){console.error("Failed to update store with error:",e)}}static triggerErrorEvent(t,e,n){var i,s;try{const r=vt.getState();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(r){console.error("Failed to trigger error event:",r)}}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){if(t.message.includes("fetch")||t.message.includes("network")||t.message.includes("timeout"))return!0;return[/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(i){return this.handle(i,e,n),null}}}e(wt,"DEFAULT_OPTIONS",{severity:"error",shouldLog:!0,shouldThrow:!1,shouldUpdateStore:!1,shouldTriggerEvent:!1,shouldDestroy:!1});class Et{constructor(t){e(this,"managers"),e(this,"userManagementService"),e(this,"playlistOrchestrator"),e(this,"lastConfig",null),this.managers=t}setUserManagementService(t){this.userManagementService=t}setPlaylistOrchestrator(t){this.playlistOrchestrator=t}getLastConfig(){return this.lastConfig}async initialize(t){var e;try{const n=await fetch(`${st}/validate-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t.token,playerVersion:"0.2.73"})}),i=await n.json();if(!i.isValid)throw wt.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=vt.getState();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 wt.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(n){throw wt.handleInitializationError(n,{component:"PlayerInitializationService",method:"initialize"})}}async fetchUserData(t,e){var n;try{const i=vt.getState();if(!(null==(n=i.config)?void 0:n.token))return void wt.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){await s.text();return s.status,void s.statusText}const r=await s.json();if(r.success){i.setUserData({watchedPlaylists:r.watchedPlaylists||{},language:r.language});const e=r.userListAssignments||{},n=r.abTestAssignments||{};this.managers.abTestManager.assignUserToTests(t,n,e),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:r.watchedPlaylists||{}}}),this.userManagementService&&this.userManagementService.resolveUserDataLoaded();await this.checkAndResumeInProgressPlaylist(r.watchedPlaylists||{})||this.managers.triggerManager.startMonitoring()}else this.userManagementService&&this.userManagementService.resolveUserDataLoaded()}catch(i){wt.handleNetworkError(i,{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);vt.getState().setUserData({watchedPlaylists:s.watchedPlaylists||{},language:null==e?void 0:e.language}),this.managers.eventManager.trigger("userDataLoaded",{timestamp:Date.now(),userId:t,userData:{watchedPlaylists:s.watchedPlaylists||{}}});const r=s.watchedPlaylists||{};await this.checkAndResumeInProgressPlaylist(r)||this.managers.triggerManager.startMonitoring()}catch(n){wt.handleNetworkError(n,{component:"PlayerInitializationService",method:"loadAnonymousUserData",userId:t})}}async checkAndResumeInProgressPlaylist(t){var e;if(!t)return!1;const n=vt.getState(),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}=St(e);return!!n}));if(r){const[t,e]=r;bt(e);try{if(this.playlistOrchestrator)return await this.playlistOrchestrator.startPlaylist(t),!0}catch(a){return!1}}return!1}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}destroy(){this.lastConfig=null}}function Mt(t){if(!t)return;if("auto"===t){return function(){try{const t=navigator.language||navigator.userLanguage;if(!t)return;return t.split("-")[0].toLowerCase()}catch(t){return}}()}return t.split("-")[0].toLowerCase()}class It{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=Mt(e.language);n={...e,language:t},e.language}this.lastUserIdentification={userId:t,userData:n};const i=vt.getState();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=Mt(t.language);e={...t,language:n},t.language}const n=this.playerInitializationService.getOrCreateAnonymousUserId();this.lastUserIdentification={userId:n,userData:e};vt.getState().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=vt.getState(),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(n){}}resolveUserDataLoaded(){this.userDataLoadedResolve&&(this.userDataLoadedResolve(),this.userDataLoadedResolve=null,this.userDataLoadedPromise=null)}destroy(){this.userDataLoadedPromise=null,this.userDataLoadedResolve=null,this.lastUserIdentification=null}}class Pt{async validatePlaylistStart(t){const{playlistId:e,options:n,eventManager:i}=t;try{const t=vt.getState();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}}const s=t.backendPlaylists;if(!s||0===s.length)return wt.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 wt.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"};const a=(null==r?void 0:r.hasTriggers)??(null==r?void 0:r.autoStart)??!1,o=!0===(null==n?void 0:n._triggeredByTriggerManager);if(a&&o){const t=await this.validateTriggerConditions(e,r,i);if(!t.isValid)return t}let l=n;if(null==n?void 0:n.once){const t=await this.validateOnceOptionConditions(e,n,i);if(!t.isValid)return t;l=t.updatedOptions||n}const c=await this.validateDeviceCompatibility(r,e);return c.isValid?{isValid:!0,manifestPath:r.path,updatedOptions:l}:c}catch(s){const t=s instanceof Error?s.message:"Unknown validation error";return wt.handlePlaylistError(`Playlist validation failed: ${t}`,{component:"PlaylistValidator",method:"validatePlaylistStart",playlistId:e,additionalData:{error:s}}),{isValid:!1,error:t}}}async validateTriggerConditions(t,e,n){var i,s;const r=vt.getState();if(!r.user)return wt.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=vt.getState().userData)?void 0:i.watchedPlaylists)||{},o=e.hasTriggers??e.autoStart??!1,l=a[t];return o&&(null==(s=e.triggers)?void 0:s.once)&&l&&("completed"===l.status||"dismissed"===l.status)?(q(`Playlist ${t} has hasTriggers enabled with once:true and has already been ${l.status}. Skipping playlist start.`,{watchedPlaylists:a,triggers:e.triggers}),{isValid:!1,error:`Playlist already ${l.status} with once=true policy`}):{isValid:!0}}async validateOnceOptionConditions(t,e,n){var i;const s=vt.getState();if(!s.user)return wt.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=vt.getState().userData)?void 0:i.watchedPlaylists)||{},a=r[t];if(a&&("completed"===a.status||"dismissed"===a.status))return q(`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`};if(a&&"in_progress"===a.status&&!(null==e?void 0:e.startNodeId)&&a.currentStepId){return{isValid:!0,updatedOptions:{...e,startNodeId:a.currentStepId}}}return{isValid:!0}}async validateDeviceCompatibility(t,e){try{const n=t.deviceType||"both",{isDeviceCompatible:i}=await Promise.resolve().then((()=>Ot));return i(n)?{isValid:!0}:(wt.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 wt.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),vt.getState(),e()};t.on("userDataLoaded",s)}))}}class xt{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 l=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.identifyUser(t.userId,t.userData),this.resetManagers(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()}catch(o){throw wt.handleInitializationError(`Failed to reinitialize player: ${o instanceof Error?o.message:"Unknown error"}`,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,additionalData:{reinitError:o}})}}l&&(this.resetManagers(),this.managers.transitionManager.setTriggerManager(this.managers.triggerManager),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions());const c=vt.getState();if(!c.config){if(!(null==(i=this.playerInitializationService)?void 0:i.getLastConfig()))throw wt.createError("Saltfish Player must be initialized at least once before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t});throw wt.createError("Saltfish Player must be initialized before starting a playlist",{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t})}c.manifest&&("playing"===c.currentState||"paused"===c.currentState||"loading"===c.currentState||"waitingForInteraction"===c.currentState||"autoplayBlocked"===c.currentState||"minimized"===c.currentState)&&(this.managerOrchestrator&&this.managerOrchestrator.cleanupCurrentPlaylist(),c.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions()),"completed"!==c.currentState&&"closing"!==c.currentState||(c.currentState,c.resetForNewPlaylist(),this.stateMachineActionHandler&&this.stateMachineActionHandler.registerStateMachineActions());this.managers.sessionManager.startNewRun();const d=null==(s=this.userManagementService)?void 0:s.getUserDataLoadedPromise();if(d&&await d,this.userManagementService&&await this.userManagementService.recordABTestAttempt(t),!this.managers.abTestManager.isPlaylistAvailable(t))return;const h=new Pt,u=await h.validatePlaylistStart({playlistId:t,options:e,eventManager:this.managers.eventManager});if(!u.isValid)return;e=u.updatedOptions||e;const p=u.manifestPath,g=e||{};g?(c.setPlaylistOptions(g),g.position||c.setPlaylistOptions({...g,position:"bottom-right"})):c.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(),c.sendStateMachineEvent({type:"LOAD_MANIFEST"});const m=null==e?void 0:e.persistence;if("undefined"!=typeof window){const e=null==(r=c.user)?void 0:r.id,n=this.managers.storageManager.getProgress(e);if(n&&n[t])c.loadPlaylistProgress(t,n[t]);else if(c.progress[t]){const e={...c.progress};delete e[t],vt.setState((t=>{t.progress=e}))}}this.managers.analyticsManager.trackPlaylistStart(t),this.managers.cursorManager.resetFirstAnimation(),await this.managers.playlistManager.load(p,{...g,persistence:m});const f=vt.getState();if(f.manifest){const t=g.persistence??f.manifest.isPersistent??!0,e=f.playlistOptions||{};f.setPlaylistOptions({...e,...g,persistence:t})}if(g.startNodeId&&f.manifest){f.manifest.steps.find((t=>t.id===g.startNodeId))?f.goToStep(g.startNodeId):console.warn(`[PlaylistOrchestrator] startNodeId '${g.startNodeId}' not found in manifest steps. Starting from default step.`)}if(f.manifest){f.manifest.cursorColor&&this.managers.cursorManager.setColor(f.manifest.cursorColor);const t=!0===g._triggeredByTriggerManager,e=f.currentStepId===(null==(a=f.manifest.steps[0])?void 0:a.id);if(f.manifest.compactFirstStep&&e&&t){const t=this.managers.uiManager.getPlayerElement();null==t||t.classList.add("sf-player--compact")}f.manifest.idleMode&&t?c.setIdleMode():c.play()}else c.play();q(`Playlist started: ${t}${f.manifest?` (${f.manifest.name})`:""}`)}catch(l){this.managers.uiManager.hideLoading();vt.getState().sendStateMachineEvent({type:"ERROR",error:l instanceof Error?l:new Error(String(l))}),wt.handlePlaylistError(l,{component:"PlaylistOrchestrator",method:"startPlaylist",playlistId:t,errorType:"playlist_load_failed"})}}resetPlaylist(){const t=vt.getState();t.manifest&&t.goToStep(t.manifest.startStep)}isInitialized(){return!!vt.getState().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 Ct{constructor(t){e(this,"managers"),e(this,"destroyCallback",null),this.managers=t}setDestroyCallback(t){this.destroyCallback=t}registerStateMachineActions(){vt.getState().registerStateMachineActions({startVideoPlayback:t=>{this.handleStartVideoPlayback(t)},pauseVideoPlayback:()=>{this.handlePauseVideoPlayback()},startMutedLoopedVideo:()=>{this.handleStartMutedLoopedVideo()},startIdleModeVideo:t=>{this.handleStartIdleModeVideo(t)},trackPlaylistComplete:()=>{this.handleTrackPlaylistComplete()},handleError:t=>{this.handleError(t)},showLoadingState:()=>{this.handleShowLoadingState()},hideLoadingState:()=>{this.handleHideLoadingState()},hideVideoControls:()=>{this.handleHideVideoControls()},showVideoControls:()=>{this.handleShowVideoControls()},showPlayButton:()=>{this.handleShowPlayButton()},hidePlayButton:()=>{this.handleHidePlayButton()},enablePlayButtonProminent:()=>{this.handleEnablePlayButtonProminent()},disablePlayButtonProminent:()=>{this.handleDisablePlayButtonProminent()},triggerPlaylistDismissed:()=>{this.handleTriggerPlaylistDismissed()},scheduleDestroy:()=>{this.handleScheduleDestroy()}})}getVideoUrl(t){var e;const n=null==(e=vt.getState().userData)?void 0:e.language;let i;if(n&&t.translations&&t.translations[n]){i=t.translations[n].videoUrl}else i=t.compressedUrl||t.videoUrl;return i&&""!==i.trim()||!t.audioUrl||""===t.audioUrl.trim()?i:(t.id,t.audioUrl)}isUsingAudioFallback(t){var e;const n=null==(e=vt.getState().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=vt.getState();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(){}async validateStepUrlRequirement(t){if(!t.urlRequirement)return!0;const{pattern:e,matchType:n}=t.urlRequirement;if(!e)return!0;const i=()=>{const t=window.location.href,i=window.location.pathname;let s=!1;if("regex"===n)try{const n=new RegExp(e);s=n.test(t)||n.test(i)}catch(r){}else s="contains"===n?t.includes(e)||i.includes(e):t===e||i===e;return s};for(let r=0;r<3;r++){if(i())return!0;if(r<2){await new Promise((t=>setTimeout(t,100)));if(!window._saltfishPlayer)return!1}}t.id;const s=window._saltfishPlayer;return s&&"function"==typeof s.destroy&&s.destroy(),!1}async handleStartVideoPlayback(t){if(!t.currentStep)return;const e=t.currentStep;if(e.urlRequirement){e.id;if(!(await this.validateStepUrlRequirement(e)))return}this.managers.uiManager.updatePosition();const n=this.managers.uiManager.getPlayerElement();null==n||n.classList.remove("sf-player--compact"),this.managers.uiManager.showPlayer();const i=this.getVideoUrl(e),s=this.isUsingAudioFallback(e);if(s){const t=vt.getState().manifest,n=e.gifUrl,i=null==t?void 0:t.avatarThumbnailUrl;this.managers.videoManager.showAudioFallbackOverlay(n,i)}else this.managers.videoManager.hideAudioFallbackOverlay();try{this.managers.interactionManager.clearButtons(),this.managers.interactionManager.clearDOMInteractions(),e.domInteractions&&this.managers.interactionManager.setupDOMInteractions(e.domInteractions),e.buttons&&this.managers.interactionManager.createButtons(e.buttons),e.id,e.cursorAnimations&&e.cursorAnimations.length,e.cursorAnimations&&e.cursorAnimations.length>0?(e.id,this.managers.cursorManager.setShouldShowCursor(!0),e.id,e.cursorAnimations[0].targetSelector,this.managers.cursorManager.animate(e.cursorAnimations[0])):(e.id,this.managers.cursorManager.setShouldShowCursor(!1));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)),n=t?"manual":"auto";t&&this.managers.transitionManager.setupTransitions(e,!1,!0),this.managers.videoManager.setCompletionPolicy(n,(()=>{var n;const i=vt.getState();if(t){const t=e.transitions.find((t=>"timeout"===t.type)),s=null==(n=e.buttons)?void 0:n.some((t=>"goto"===t.action.type||"next"===t.action.type));if(t&&!s){const n=t.timeout||0;t.nextStep,setTimeout((()=>{var n;const i=vt.getState();i.currentStepId!==e.id||"waitingForInteraction"!==i.currentState&&"playing"!==i.currentState?i.currentState:(t.nextStep,null==(n=i.goToStep)||n.call(i,t.nextStep))}),n),i.sendStateMachineEvent({type:"VIDEO_FINISHED_WAIT",step:e})}else i.sendStateMachineEvent({type:"VIDEO_FINISHED_WAIT",step:e})}else{this.managers.transitionManager.setupTransitions(e,!0);e.transitions.some((t=>i.manifest.steps.some((e=>e.id===t.nextStep))))||i.sendStateMachineEvent({type:"COMPLETE_PLAYLIST"})}}));const r=()=>{var t,n;const i=vt.getState(),s=(null==(t=i.manifest)?void 0:t.captions)??!0,r=null==(n=i.userData)?void 0:n.language;let a=e.transcript;if(r&&e.translations&&e.translations[r]){const t=e.translations[r].transcript;t&&(a=t,e.id)}a?(e.id,this.managers.videoManager.loadTranscript(a,s)):(e.id,this.managers.videoManager.loadTranscript(null,!0))};this.managers.videoManager.loadVideo(i).then((()=>{r(),s?this.managers.videoManager.startAudioVisualization():this.managers.videoManager.initializeAudioForVideo(),this.managers.videoManager.play();const t=this.findNextVideoUrl(e);t&&this.managers.videoManager.preloadNextVideo(t)})).catch((t=>{var n;this.managers.uiManager.showError(t instanceof Error?t:new Error(`Failed to load video: ${t}`),"video");const i=vt.getState(),s=t instanceof Error?t:new Error(`Failed to load video: ${t}`),r=t;this.managers.eventManager.trigger("error",{timestamp:Date.now(),playlistId:(null==(n=i.manifest)?void 0:n.id)||void 0,stepId:e.id,error:s,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})}))}catch(r){}}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);if(this.managers.uiManager.showPlayer(),i){const t=vt.getState().manifest,n=e.gifUrl,i=null==t?void 0:t.avatarThumbnailUrl;this.managers.videoManager.showAudioFallbackOverlay(n,i)}else this.managers.videoManager.hideAudioFallbackOverlay();this.managers.videoManager.loadVideo(n).then((()=>{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=vt.getState();if(n.manifest&&this.managers.eventManager){const i=n.manifest.id;this.managers.eventManager.trigger("playlistEnded",{timestamp:Date.now(),playlist:{id:i,title:n.manifest.name}});if(((null==(t=n.playlistOptions)?void 0:t.persistence)??!0)&&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=vt.getState();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"})}}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()}handleTriggerPlaylistDismissed(){const t=vt.getState();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)}}function Tt(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 vt.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){if(!n)return;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}}))}function kt(t){let e=null,n=null,i=null,s=null;const r=vt.subscribe((r=>{var a;if(e===r.currentState&&i===r.isMinimized&&s===r.currentStepId)return;const o=e,l=n,c=i,d=s;n=e,e=r.currentState,i=r.isMinimized,s=r.currentStepId;const h={prevPreviousState:l,previousState:o,currentState:r.currentState,currentStepId:r.currentStepId,isMinimized:r.isMinimized};null==(a=r.manifest)||a.id,function(t,e,n){const{prevPreviousState:i,previousState:s,currentState:r,currentStepId:a}=t,o="playing"===r&&"paused"===s&&"loading"===i,l="playing"===r&&("autoplayBlocked"===s||"idleMode"===s);if((o||l)&&e.manifest&&a){if(a===e.manifest.startStep)return e.manifest.id,void n.trigger("playlistStarted",{timestamp:Date.now(),playlist:{id:e.manifest.id,title:e.manifest.name}})}"paused"===s&&"playing"===r?n.trigger("playerResumed",{timestamp:Date.now(),previousState:s,currentState:r}):"playing"===s&&"paused"===r&&n.trigger("playerPaused",{timestamp:Date.now(),previousState:s,currentState:r})}(h,r,t),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})}(h,0,t,c),function(t,e,n,i){var s,r,a;const{prevPreviousState:o,previousState:l,currentStepId:c,currentState:d}=t,h=e.currentStepId?((null==(s=e.manifest)?void 0:s.steps)||[]).find((t=>t.id===e.currentStepId)):null;null==h||h.id,null==(r=e.manifest)||r.id,e.manifest;const u=i&&e.manifest&&(i!==c||"waitingForInteraction"===d||"completed"===d);if(e.manifest,u){const t=((null==(a=e.manifest)?void 0:a.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 p=c!==i&&"playing"===d,g=("autoplayBlocked"===l||"idleMode"===l)&&"playing"===d&&i===c,m="loading"===o&&"paused"===l&&"playing"===d&&c,f=h&&e.manifest&&(p||g||m);null==h||h.id,e.manifest,f&&(h.id,n.trigger("stepStarted",{timestamp:Date.now(),step:{id:h.id,title:h.title||h.id},playlist:{id:e.manifest.id,title:e.manifest.name}}))}(h,r,t,d),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"})}(h,r,t)}));return r}const _t=class t{constructor(t){e(this,"managers"),e(this,"uiUpdaterUnsubscribe",null),e(this,"eventUpdaterUnsubscribe",null),e(this,"isInitialized",!1),this.managers=t}setInitialized(t){this.isInitialized=t}setupUpdaters(){this.uiUpdaterUnsubscribe&&this.uiUpdaterUnsubscribe(),this.eventUpdaterUnsubscribe&&this.eventUpdaterUnsubscribe();const t=this.managers.uiManager.getPlayerElement();t&&(this.uiUpdaterUnsubscribe=Tt(t,this.managers.cursorManager)),this.eventUpdaterUnsubscribe=kt(this.managers.eventManager);const e=vt.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=vt.getState();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.managers.cursorManager.animate(n.cursorAnimations[0]))}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.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.interactionManager.clearDOMInteractions()),this.managers.uiManager.reset()}catch(t){wt.handleCleanupError(t,{component:"ManagerOrchestrator",method:"cleanupCurrentPlaylist"})}}cleanupPlaylist(){var t;if(this.isInitialized)try{const e=vt.getState();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,this.uiUpdaterUnsubscribe&&(this.uiUpdaterUnsubscribe(),this.uiUpdaterUnsubscribe=null),this.managers.transitionManager.destroy(),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(e){wt.handleCleanupError(e,{component:"ManagerOrchestrator",method:"cleanupPlaylist"})}else console.warn("Saltfish playlist Player is not initialized")}destroyAll(){var t;if(this.isInitialized)try{const e=vt.getState();e.currentState,e.currentStepId,e.isMinimized,null==(t=e.manifest)||t.id,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(e){wt.handleCleanupError(e,{component:"ManagerOrchestrator",method:"destroyAll"});try{this.isInitialized=!1;vt.getState().reset()}catch(n){wt.handleCleanupError(n,{component:"ManagerOrchestrator",method:"destroyAll",additionalData:{originalError:e}})}}else console.warn("Saltfish playlist Player is not initialized")}getManagers(){return this.managers}destroy(){this.destroyAll()}};e(_t,"prevState",{currentState:"idle",currentStepId:null,isMinimized:!1});let At=_t;class zt{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(e){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(){if(!this.shadowRoot)return null;return this.shadowRoot.getElementById("sf-player-root")}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(e){console.warn("ShadowDOMManager: Failed to append to adoptedStyleSheet:",e)}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-lg);\n box-shadow: 0 25px 50px rgba(0, 0, 0, 0.45), 0 10px 20px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(255, 255, 255, 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/* Dark gradient overlay at bottom of player */\n.sf-player::before {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 33.33%; /* One third of player 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: 8px;\n}\n\n/* Hide gradient overlay when minimized */\n.sf-player--minimized::before {\n display: none;\n}\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.35), 0 5px 15px rgba(0, 0, 0, 0.25), 0 0 0 2px rgba(255, 255, 255, 0.08);\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.35), 0 5px 15px rgba(0, 0, 0, 0.25), 0 0 0 2px rgba(255, 255, 255, 0.08);\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/* Adjust play button size in compact mode */\n.sf-player--compact .sf-player__center-play-button {\n width: var(--sf-play-button-compact-size);\n height: var(--sf-play-button-compact-size);\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 */\n.sf-player--compact::before {\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: 6px;\n width: var(--sf-minimize-button-size);\n height: var(--sf-minimize-button-size);\n background-color: transparent;\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: 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 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);\n backdrop-filter: blur(3px);\n -webkit-backdrop-filter: blur(3px);\n box-shadow: 0 15px 30px rgba(0, 0, 0, 0.5), 0 5px 15px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(255, 255, 255, 0.08);\n pointer-events: auto; /* Enable pointer events to capture clicks */\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 background-color: rgba(0, 0, 0, 0.7);\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 adjustment for 3+ buttons */\n.sf-player__center-play-button--with-many-buttons {\n transform: translate(-50%, -85%) !important; /* Move up by adjusting Y offset */\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: 20px;\n height: 20px;\n background-color: var(--sf-button-bg);\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 box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35);\n}\n\n/* Exit button hover state */\n.sf-player__exit-button:hover {\n transform: scale(1.1);\n background-color: var(--sf-button-hover-bg);\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}\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: 10%; /* Default minimum height */\n background-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 /* 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}\n\n/* Video blur effect (for end-of-video transitions) */\n.sf-video-container__video--blurred {\n filter: blur(3px);\n transition: filter 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 .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 .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}\n\n.sf-player--minimized .sf-video-container__video {\n border-radius: var(--sf-border-radius-circle);\n object-fit: cover;\n width: 100%;\n height: 100%;\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 width: 100%;\n height: 3px;\n background-color: rgba(255, 255, 255, 0.25);\n z-index: var(--sf-z-index-controls);\n border-radius: var(--sf-border-radius-md) var(--sf-border-radius-md) 0 0;\n cursor: pointer;\n}\n\n/* Show slightly thicker progress bar on hover for better UX */\n.sf-video-container__controls:hover {\n height: 5px;\n}\n\n/* Progress indicator */\n.sf-video-container__progress {\n height: 100%;\n background: rgba(255, 255, 255, 0.8);\n width: 0%;\n transition: width 0.1s linear;\n border-radius: var(--sf-border-radius-md) 0 0 0;\n cursor: pointer;\n transform-origin: left;\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: 6px;\n width: var(--sf-mute-button-size);\n height: var(--sf-mute-button-size);\n background-color: transparent;\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: 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 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: 6px;\n width: var(--sf-cc-button-size);\n height: var(--sf-cc-button-size);\n background-color: transparent;\n border-radius: 50%; /* Ensure perfect circle */\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.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/* 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 4+ buttons */\n.sf-choice-buttons-container--scrollable {\n max-height: 132px; /* Show ~3 buttons with gaps (3 * 36px button + 3 * 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;\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;\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-overlay);\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}\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 */\n.sf-transcript__word-container {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 0; /* Remove flex gap - spacing handled by margin on preview word */\n min-height: 60px;\n padding: 0;\n}\n\n/* Individual word styling */\n.sf-transcript__word {\n color: rgba(255, 255, 255, 0.9);\n font-size: var(--sf-font-size-lg);\n font-weight: 600;\n line-height: 1.2;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateY(0);\n filter: blur(0px);\n opacity: 1;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);\n}\n\n/* Active word (currently speaking) */\n.sf-transcript__word--active {\n opacity: 1;\n filter: blur(0px);\n transform: translateY(0) scale(1);\n color: rgba(255, 255, 255, 1);\n font-weight: 600;\n}\n\n/* Preview word (clean, unblurred when shown) */\n.sf-transcript__word--preview {\n opacity: 0.8;\n filter: blur(0px);\n transform: translateY(0) scale(0.98);\n color: rgba(255, 255, 255, 0.8);\n font-weight: 400;\n margin-left: 0.2em; /* Minimal spacing - just enough for a natural gap */\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: 50px; /* More space on mobile */\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: var(--sf-spacing-sm);\n gap: var(--sf-spacing-xs);\n }\n \n .sf-transcript__word {\n font-size: var(--sf-font-size-md);\n font-weight: 500;\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 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 /* \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 Lt{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(e){console.warn("DeviceDetector: Error in device change handler:",e)}};return window.addEventListener("orientationchange",e),window.addEventListener("resize",e),()=>{window.removeEventListener("orientationchange",e),window.removeEventListener("resize",e)}}}e(Lt,"cachedDeviceInfo",null);const Ot=Object.freeze(Object.defineProperty({__proto__:null,DeviceDetector:Lt,isDeviceCompatible:t=>{if(!t||"both"===t)return!0;const e=Lt.getDeviceInfo();return"mobile"===t?e.isMobile||e.isTablet:"desktop"===t&&e.isDesktop}},Symbol.toStringTag,{value:"Module"})),Vt=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)}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.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.hideTranscript(),this.updateCCButtonState(!!this.currentTranscript),this.isVisible)}handleCCButtonClick(t){t.preventDefault(),t.stopPropagation(),this.toggleVisibility()}handleTimeUpdate(t){if(!this.currentTranscript||!this.isVisible||!this.videoElement||0===this.chunks.length)return;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)}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){if(this.chunks[e+1].start-t<.1)return e+1;return t-this.chunks[e].end<.1?e:e+1}return-1}handleStateChange(t){this.currentTranscript,this.chunks.length,this.currentTranscript&&0!==this.chunks.length&&("waitingForInteraction"!==t&&"completedWaitingForInteraction"!==t?this.isVisible?(this.isVisible,this.showTranscript()):(this.isVisible,this.hideTranscript()):this.transcriptContent&&(this.transcriptContent.innerHTML=""))}shouldShowTwoWords(t){if(t<0||t>=this.chunks.length)return!1;const e=this.chunks[t];if(!this.chunks[t+1])return!1;const n=e.text.trim();return!(n.endsWith(".")||n.endsWith("!")||n.endsWith("?"))&&(!(t>=this.chunks.length-1)&&!(n.length>10))}updateIntelligentWordDisplay(t){if(!this.transcriptContent)return;const e=this.shouldShowTwoWords(t),n=t>=0&&t<this.chunks.length?this.chunks[t]:null,i=e&&t+1<this.chunks.length?this.chunks[t+1]:null;if(this.transcriptContent.innerHTML="",!n)return;const s=document.createElement("div");s.className="sf-transcript__word-container";const r=document.createElement("span");if(r.className="sf-transcript__word sf-transcript__word--active",r.textContent=n.text,s.appendChild(r),i){const t=document.createElement("span");t.className="sf-transcript__word sf-transcript__word--preview",t.textContent=i.text,s.appendChild(t)}this.transcriptContent.appendChild(s)}createTranscriptUI(){var t;if(this.transcriptContainer)return;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.transcriptContent&&(this.transcriptContent.innerHTML=""),this.currentTranscript=null,this.chunks=[],this.isNewVideo=!1,this.firstWordForceDisplayUntil=0,this.isVisible&&this.hideTranscript(),this.updateCCButtonState(!1),this.transcriptContainer=null,this.transcriptContent=null}static resetUserPreference(){t.userCaptionPreference=null}async destroy(){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(Vt,"userCaptionPreference",null);let Dt=Vt;class Bt{constructor(t){e(this,"deviceInfo"),this.deviceInfo=t}updateDeviceInfo(t){this.deviceInfo=t}}class Ft extends Bt{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(i){console.warn(`MobilePlaybackHandler: Failed to set attribute ${e}:`,i)}})),Object.entries(e.styles).forEach((([e,n])=>{try{t.style.setProperty(e,n)}catch(i){console.warn(`MobilePlaybackHandler: Failed to set style ${e}:`,i)}}))}configureControlElement(t){const e=this.getControlsConfig();t.style.setProperty("min-width",e.buttonMinSize.width),t.style.setProperty("min-height",e.buttonMinSize.height)}async handlePlayAttempt(t,e){const n=vt.getState().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(i){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(e){console.error("MobilePlaybackHandler: All autoplay attempts failed")}}destroy(){}getProgressUpdateFrequency(t){return t?500:16}}class Ut extends Bt{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,Object.entries(e.styles).forEach((([e,n])=>{t.style.setProperty(e,n)}))}configureControlElement(t){}async handlePlayAttempt(t,e){const n=vt.getState().isMuted;t.muted=n,t.loop=!1;try{return await t.play(),!0}catch(i){return t.muted,await this.handleAutoplayFallback(t),!1}}async handleAutoplayFallback(t){t.muted=!0,t.loop=!0;try{await t.play()}catch(e){throw console.error("DesktopPlaybackHandler: All autoplay attempts failed"),new Error("Desktop autoplay completely blocked")}}getProgressUpdateFrequency(t){return 16}destroy(){}}class Rt{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;if(this.lastTimeupdateEvent=Date.now(),this.progressBar&&!1===(null==(t=this.videoElement)?void 0:t.paused)&&this.progressBar.style.setProperty("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("transition","none"),this.updateProgress())})),e(this,"handleSeeked",(()=>{this.progressBar&&this.videoElement&&(this.videoElement.paused||(this.updateProgress(),this.progressBar.offsetWidth,this.progressBar.style.setProperty("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("transition","none"),this.progressBar.style.setProperty("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='\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="none"></polygon>\n <path d="M15 9c0.8 0.8 1.5 1.9 1.5 3s-0.7 2.2-1.5 3" stroke="currentColor"></path>\n <path d="M19 7c1.6 1.6 2.5 3.8 2.5 6s-0.9 4.4-2.5 6" stroke="currentColor"></path>\n </svg>\n ',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),t&&(t.addEventListener("seeking",this.handleSeeking),t.addEventListener("seeked",this.handleSeeked),t.addEventListener("timeupdate",this.handleDetailedTimeUpdate))}updateVideoElement(t){this.videoElement&&(this.videoElement.removeEventListener("seeking",this.handleSeeking),this.videoElement.removeEventListener("seeked",this.handleSeeked),this.videoElement.removeEventListener("timeupdate",this.handleDetailedTimeUpdate)),this.videoElement=t,t&&(t.addEventListener("seeking",this.handleSeeking),t.addEventListener("seeked",this.handleSeeked),t.addEventListener("timeupdate",this.handleDetailedTimeUpdate))}reset(){this.stopProgressTracking(),this.buttonsShownAt90Percent=!1,this.lastTimeupdateEvent=0,this.progressBar&&(this.progressBar.style.setProperty("transition","none"),this.progressBar.style.setProperty("width","0%"))}reset90PercentTrigger(){this.buttonsShownAt90Percent=!1}destroy(){if(this.stopProgressTracking(),this.videoElement&&(this.videoElement.removeEventListener("seeking",this.handleSeeking),this.videoElement.removeEventListener("seeked",this.handleSeeked),this.videoElement.removeEventListener("timeupdate",this.handleDetailedTimeUpdate)),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("transition","none"),this.progressBar.style.setProperty("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("transition"),s=Date.now()-this.lastTimeupdateEvent;this.progressBar.style.setProperty("transition","none"),this.progressBar.style.setProperty("width",`${n}%`),this.progressBar.offsetWidth,this.videoElement.ended?this.progressBar.style.setProperty("transition","width 0.2s ease-out"):!this.videoElement.paused&&!this.videoElement.seeking&&i&&s<500&&this.progressBar.style.setProperty("transition","width 0.1s linear")}}setMuted(t){vt.getState().setMuted(t),this.updateMuteButtonIcon()}toggleMute(){const t=!vt.getState().isMuted;this.setMuted(t),this.callbacks.onMuteToggle()}getMuted(){return vt.getState().isMuted}updateMuteButtonIcon(){if(!this.muteButton)return;const t=vt.getState().isMuted;this.muteButton.innerHTML=t?'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n </svg>\n ':'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n </svg>\n '}updateCCButtonIcon(t){this.ccButton&&(this.ccButton.innerHTML=t?'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n </svg>\n ':'\n <svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">\n <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"></path>\n <line x1="48" y1="48" x2="208" y2="208" stroke="currentColor" stroke-width="16" stroke-linecap="round"/>\n </svg>\n ')}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("transition","none"),this.progressBar.style.setProperty("width","0%"),this.progressBar.offsetWidth,this.progressBar.style.setProperty("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 Nt{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(e){console.warn("AudioVisualizationManager: Web Audio API failed, using fallback animation",e),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 a=0;a<e;a++){let t=0;const e=a*s,r=e+s;for(let n=e;n<r&&n<i;n++)t+=this.dataArray[n];const o=t/s/255;n.push(o)}const r=[...n].reverse();r.pop();return r.concat(n)}getFallbackBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let i=0;i<t;i++){let t=.3+(.3*Math.sin(.003*this.fallbackTime+.5*i)+.2*Math.sin(.005*this.fallbackTime+.3*i)+.15*Math.sin(.002*this.fallbackTime+.7*i));t=Math.max(0,Math.min(1,t)),e.push(t)}const n=[...e].reverse();n.pop();return n.concat(e)}getFlatBarHeights(){const t=Math.floor(this.barCount/2),e=[];for(let i=0;i<t;i++)e.push(.1);const n=[...e].reverse();n.pop();return n.concat(e)}getAverageAmplitude(){if(this.useFallbackMode||!this.analyser||!this.dataArray)return.5+.3*Math.sin(.002*this.fallbackTime);this.analyser.getByteFrequencyData(this.dataArray);let t=0;for(let n=0;n<this.dataArray.length;n++)t+=this.dataArray[n];const e=t/this.dataArray.length/255;return 0===e?.5+.3*Math.sin(.002*this.fallbackTime):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)}))}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 Ht{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=vt.getState();"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;console.error("VideoManager: Video error",e.error)})),e(this,"handleAutoVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()})),e(this,"handleManualVideoEnded",(()=>{this.videoEndedCallback&&this.videoEndedCallback()}));const t=Lt.getDeviceInfo();this.deviceHandler=function(t){return t.isMobile?new Ft(t):new Ut(t)}(t),this.transcriptManager=new Dt,this.audioVisualizationManager=new Nt,this.deviceChangeCleanup=Lt.onDeviceChange((t=>{this.deviceHandler.updateDeviceInfo(t)}))}getDeviceInfo(){return Lt.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);vt.getState().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)},on90PercentReached:()=>{if(this.container){const t=new CustomEvent("video90PercentReached",{bubbles:!0,detail:{timestamp:Date.now()}});this.container.dispatchEvent(t)}}};if(this.controls=new Rt(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}swapVideos(){const t=this.getActiveVideo(),e=this.getInactiveVideo();if(!t||!e)return;t.pause();const n=vt.getState();e.muted=n.isMuted,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)return;if(!t||""===t.trim())throw new Error("Cannot load video: No video URL provided for this step");this.controls&&this.controls.reset90PercentTrigger();const i=vt.getState();n.muted=i.isMuted;try{this.controls&&this.controls.reset();const i=(null==(e=vt.getState().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}i&&this.currentVideoUrl&&n.currentTime>0&&this.playbackPositions.set(this.currentVideoUrl,n.currentTime);if(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(s){if(console.error("VideoManager: Failed to load video:",s),s&&"object"==typeof s&&"videoUrl"in s)throw s;const e=new Error("Failed to load video");throw e.videoUrl=t,e.mediaErrorCode=null,e.mediaErrorMessage=null,e.failureReason="load_error",e}}preloadNextVideo(t){if(!t||this.preloadedVideos.has(t))return;if(this.currentVideoUrl===t)return;if(this.nextVideoUrl===t)return;const e=this.getInactiveVideo();if(e){this.nextVideoUrl=t,e.src=t,e.load(),e.preload="auto";const n=vt.getState();e.muted=n.isMuted}else 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=vt.getState();if(((null==(t=n.playlistOptions)?void 0:t.persistence)??!0)&&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");vt.getState().setAutoplayFallback()}))}pause(){const t=this.getActiveVideo();t&&(t.paused||(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,null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null),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(),null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null),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(){const t=this.currentVideo,e=this.nextVideo;t&&(t.addEventListener("ended",this.handleVideoEnded),t.addEventListener("error",this.handleVideoError)),e&&(e.addEventListener("ended",this.handleVideoEnded),e.addEventListener("error",this.handleVideoError))}removeEventListeners(){const t=this.currentVideo,e=this.nextVideo;t&&(t.removeEventListener("ended",this.handleVideoEnded),t.removeEventListener("error",this.handleVideoError)),e&&(e.removeEventListener("ended",this.handleVideoEnded),e.removeEventListener("error",this.handleVideoError))}setMuted(t){this.currentVideo&&(this.currentVideo.muted=t),this.nextVideo&&(this.nextVideo.muted=t),this.controls&&this.controls.setMuted(t)}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,null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null))}hasUserInteractedWith(){return this.hasUserInteracted}resetUserInteraction(){this.hasUserInteracted=!1,null!==this.autoplayFallbackTimeout&&(window.clearTimeout(this.autoplayFallbackTimeout),this.autoplayFallbackTimeout=null)}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)=>{if(!this.soundbarElement)return;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.height=`${r}%`;const a=180+Math.abs(n-5)/5*120;s.style.backgroundColor=`hsla(${a}, 70%, 60%, 1)`}))}))}catch(e){console.error("VideoManager: Failed to initialize audio visualization",e)}}initializeAudioForVideo(){const t=this.getActiveVideo();if(t)try{this.audioVisualizationManager.initialize(t)}catch(e){console.error("VideoManager: Failed to initialize audio for video",e)}}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 Yt=3e4,$t=500,Xt=100,jt=5e3,Wt=500,qt=10;class Zt{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,"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){this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null),this.targetMutationObserver=new MutationObserver((async(n,i)=>{if(this.isAutoplayBlocked())return i.disconnect(),void(this.targetMutationObserver=null);const s=await this.findElementAndScrollIntoView(t);s&&(i.disconnect(),this.targetMutationObserver=null,e(s))})),this.targetMutationObserver.observe(document.body,{childList:!0,subtree:!0});const n=setInterval((()=>{if(!this.targetMutationObserver||this.isAutoplayBlocked())return clearInterval(n),void(this.targetMutationObserver&&(this.targetMutationObserver.disconnect(),this.targetMutationObserver=null));const i=this.findElement(t);i&&(clearInterval(n),this.targetMutationObserver.disconnect(),this.targetMutationObserver=null,e(i))}),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){const e=document.querySelectorAll(t);if(0===e.length)return null;if(1===e.length)return e[0];for(const a of e)if(this.isElementInViewport(a))return a.getBoundingClientRect(),a;const n=window.innerWidth/2,i=window.innerHeight/2;let s=e[0],r=1/0;for(const a of e){const t=a.getBoundingClientRect(),e=t.left+t.width/2,o=t.top+t.height/2,l=Math.sqrt(Math.pow(e-n,2)+Math.pow(o-i,2));l<r&&(r=l,s=a)}return s.getBoundingClientRect(),s}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 r of s){const t=r.getBoundingClientRect();if(!(e.top>=t.top&&e.bottom<=t.bottom&&e.left>=t.left&&e.right<=t.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){const e=this.findElement(t);return e?(this.isElementInViewport(e)||await this.scrollElementIntoView(e),e):null}create(){this.injectCursorStyles(),this.cursor=document.createElement("div"),this.cursor.className="sf-cursor",this.cursor.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#ff7614" stroke-width="2">\n <path d="M3 3L10.5 21L13.5 13.5L21 10.5L3 3Z" fill="#ff7614" />\n </svg>\n ',this.selectionElement=document.createElement("div"),this.selectionElement.className="sf-selection",document.body.appendChild(this.cursor),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})}injectCursorStyles(){const t="\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 /* 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.1));\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 ";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"===yt.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.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.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,$t))),this.isAutoplayBlocked())return;const e=await this.findElementAndScrollIntoView(t.targetSelector);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)));this.setShouldShowCursor(!0),this.currentTargetElement=e,this.addScrollListenersToParents(e);const n=e.getBoundingClientRect();this.isFirstAnimation?(this.startX=50,this.startY=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};this.targetX=this.dragStartX+this.SELECTION_HORIZONTAL_OFFSET,this.targetY=this.dragStartY+this.SELECTION_VERTICAL_OFFSET;if(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=`\n polygon(\n 0% 0%, /* Top-left of screen */\n 100% 0%, /* Top-right of screen */\n 100% 100%, /* Bottom-right of screen */\n 0% 100%, /* Bottom-left of screen */\n 0% ${e}px, /* Begin cutout: bottom-left of cutout */\n ${t}px ${e}px, /* Bottom-left of cutout */\n ${t}px ${e+i}px, /* Top-left of cutout */\n ${t+n}px ${e+i}px, /* Top-right of cutout */\n ${t+n}px ${e}px, /* Bottom-right of cutout */\n 0% ${e}px /* Close cutout path */\n )\n `;this.flashlightOverlay.style.setProperty("--sf-flashlight-clip",s);const r=this.lastCursorX,a=this.lastCursorY;this.flashlightOverlay.style.setProperty("--sf-flashlight-bg",`radial-gradient(circle 150px at ${r}px ${a}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.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){e.setAttribute("stroke",t);const n=e.querySelector("path");n?n.setAttribute("fill",t):console.warn("[CursorManager.setColor] No path found in SVG")}else console.warn("[CursorManager.setColor] No SVG found in cursor")}else console.warn("[CursorManager.setColor] No cursor element");if(this.selectionElement){this.selectionElement.style.setProperty("--sf-selection-color",t);const e=this.colorToRgba(t,.1);this.selectionElement.style.setProperty("--sf-selection-bg-color",e)}}colorToRgba(t,e){const n=document.createElement("div");n.style.color=t,document.body.appendChild(n);const i=window.getComputedStyle(n).color;document.body.removeChild(n);const s=i.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);if(s){return`rgba(${s[1]}, ${s[2]}, ${s[3]}, ${e})`}return t}}class Kt{constructor(){e(this,"container",null),e(this,"buttons",[]),e(this,"buttonContainer",null),e(this,"scrollIndicator",null),e(this,"domEventListeners",new Map),e(this,"storeUnsubscribe",null),e(this,"storageManager",mt.getInstance()),e(this,"handleVideo90PercentReached",(t=>{this.showButtonsAt90Percent()}))}create(t){this.container=t,this.storeUnsubscribe=vt.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>=3,n=t.length>3;let i="sf-choice-buttons-container";n&&(i+=" sf-choice-buttons-container--scrollable"),this.buttonContainer.className=i,t.length,this.updateCenterPlayButtonPosition(e),this.container.appendChild(this.buttonContainer),n&&(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)})),n&&this.buttonContainer&&this.setupScrollIndicator(this.buttonContainer);vt.getState().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){if(!this.scrollIndicator)return;t.addEventListener("scroll",(()=>{if(!this.scrollIndicator)return;t.scrollHeight-t.scrollTop-t.clientHeight<qt?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");e&&(t?e.classList.add("sf-player__center-play-button--with-many-buttons"):e.classList.remove("sf-player__center-play-button--with-many-buttons"))}clearButtons(){this.updateCenterPlayButtonPosition(!1),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;if(vt.getState().isMinimized)return this.buttonContainer.classList.add("sf-hidden"),void(this.scrollIndicator&&this.scrollIndicator.classList.add("sf-hidden"));this.buttonContainer.classList.remove("sf-hidden"),this.scrollIndicator&&this.scrollIndicator.classList.remove("sf-hidden"),this.buttonContainer.className="sf-choice-buttons-container"}setupDOMInteractions(t){this.clearDOMInteractions(),t.forEach(((t,e)=>{try{const n=document.querySelectorAll(t.selector);if(0===n.length)return void t.selector;n.length,t.selector,n.forEach(((n,i)=>{const s=n,r=`dom-interaction-${e}-${i}-${Date.now()}`,a=e=>{this.handleDOMInteraction(e,t)};s.addEventListener(t.action,a),this.domEventListeners.set(r,{element:s,listener:a,type:t.action}),t.action,t.selector}))}catch(n){console.error(`InteractionManager: Error setting up DOM interaction for selector "${t.selector}":`,n)}}))}clearDOMInteractions(){this.domEventListeners.forEach((({element:t,listener:e,type:n})=>{try{t.removeEventListener(n,e)}catch(i){console.error("InteractionManager: Error removing event listener:",i)}})),this.domEventListeners.clear()}async handleButtonClick(t,e){var n,i,s,r,a,o;e.id,t.preventDefault(),t.stopPropagation();const l=vt.getState();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=vt.getState();if(t.manifest){vt.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(c){console.error("InteractionManager: Full error:",c)}if((null==(r=t.playlistOptions)?void 0:r.persistence)??!0){const n=null==(a=t.user)?void 0:a.id,i=vt.getState();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,lastProgressAt:Date.now()},this.storageManager.setAnonymousUserData(n),e.action.target)}}}e.action.url,window.location.href=e.action.url}else e.action.target,l.goToStep(e.action.target);break;case"url":if(e.action.target,await this.flushAnalytics(),"completedWaitingForInteraction"===l.currentState)l.completePlaylist(),await new Promise((t=>setTimeout(t,Xt)));else{this.isCurrentStepLast(l)&&(l.goToStep("completed"),await new Promise((t=>setTimeout(t,Xt))))}window.open(e.action.target,"_blank");const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ye)),d=t.getInstance();d&&d.destroy();break;case"playlist":e.action.target;try{await this.flushAnalytics(),l.completePlaylist(),await new Promise((t=>setTimeout(t,Xt)));const{SaltfishPlayer:t}=await Promise.resolve().then((()=>ye)),n=t.getInstance();n&&(e.action.target,await n.startPlaylist(e.action.target))}catch(c){console.error(`InteractionManager: Error starting playlist "${e.action.target}":`,c),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)}}handleDOMInteraction(t,e){if(e.action,e.selector,e.waitFor&&(t.preventDefault(),t.stopPropagation(),e.selector),"input"===e.action&&e.value){const n=t.target;n&&(n.value=e.value,e.value)}if(vt.getState().manifest){const t={selector:e.selector,action:e.action,value:e.value};JSON.stringify(t)}}isCurrentStepLast(t){if(!t.manifest||!t.currentStepId||!t.manifest.steps)return!1;const e=t.manifest.steps;return e.findIndex((e=>e.id===t.currentStepId))===e.length-1}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.clearDOMInteractions(),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.clearDOMInteractions(),this.container=null}}function Jt(){try{return vt.getState()}catch(t){return null}}class Gt{constructor(t){e(this,"config",null),e(this,"user",null),e(this,"eventQueue",[]),e(this,"isSending",!1),e(this,"flushInterval",null),e(this,"eventManager",null),e(this,"sessionId",null),e(this,"analyticsEnabled",!0),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}subscribeToEvents(){this.eventManager&&(this.eventManager.on("playerPaused",(t=>{const e=Jt(),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=Jt(),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=Jt(),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=Jt(),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()})})))}initialize(t,e){this.config=t,this.analyticsEnabled=!1!==t.enableAnalytics,e&&(this.sessionId=e),this.analyticsEnabled&&(this.flushInterval=window.setInterval((()=>{this.flushEvents()}),Yt))}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}}}destroy(){this.analyticsEnabled&&this.flushEvents(),null!==this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=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||mt.getInstance(),this.sessionId=this.getOrCreateSession(),this.sessionId}getOrCreateSession(){if("undefined"==typeof window)return this.generateUniqueId();const t=this.storageManager.getSession();if(t){if(Date.now()-t.lastActivity<it)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,"triggerManager",null),e(this,"handleURLChange",(()=>{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){if(!this.validateCurrentStepUrl())return}if(this.triggerManager&&this.triggerManager.evaluateAllTriggers(),e)for(const[n,i]of t){if(!i.data)continue;const{pattern:t,nextStepId:e}=i.data;if(this.isURLPathMatch(t)){this.triggerTransition(e);break}}})),window.addEventListener("popstate",this.handleURLChange),this.monitorHistoryChanges()}setTriggerManager(t){this.triggerManager=t}monitorHistoryChanges(){const t=history.pushState,e=history.replaceState;history.pushState=(...e)=>{t.apply(history,e),this.handleURLChange()},history.replaceState=(...t)=>{e.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;if(this.willCauseHardRefresh(e)){t.preventDefault(),t.stopImmediatePropagation();await this.triggerTransitionWithProgress(n)&&this.reDispatchClick(t)}else this.triggerTransition(n)};s.set(t,e),t.addEventListener("click",e,{capture:!0})})))},o=document.querySelectorAll(e);a(o),r=new MutationObserver((t=>{for(const n of t)"childList"===n.type&&n.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;n.matches(e)&&a([n]);const i=n.querySelectorAll(e);i.length>0&&(i.length,a(i))}}))})),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.isURLPathMatch(e)){this.triggerTransition(n);const t=5;let e=0;const i=()=>{if(e>=t)return;e++;const s=vt.getState();"waitingForInteraction"===s.currentState||"playing"===s.currentState?(s.currentState,this.triggerTransition(n)):e<t&&(s.currentState,setTimeout(i,Wt))};setTimeout(i,Wt)}const i=`url-path-${Date.now()}`,s=window.setInterval((()=>{this.isURLPathMatch(e)&&(clearInterval(s),this.triggerTransition(n))}),jt);this.activeTransitions.set(i,{handlers:new Map,cleanup:()=>{clearInterval(s)},data:{type:"url-path",pattern:e,nextStepId:n}})}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),r=s.test(e),a=s.test(n);return r||a}validateUrlRequirement(t){const{pattern:e,matchType:n}=t;if(!e)return!0;const i=window.location.href,s=window.location.pathname;if("regex"===n)try{const t=new RegExp(e),n=t.test(i),r=t.test(s),a=n||r;return a}catch(r){return!1}if("contains"===n){return i.includes(e)||s.includes(e)}return i===e||s===e}handleUrlRequirementFailure(t,e){e.pattern,e.matchType,this.cleanupTransitions();const n=window._saltfishPlayer;n&&"function"==typeof n.destroy&&n.destroy()}validateCurrentStepUrl(){const t=vt.getState(),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=this.validateUrlRequirement(i.urlRequirement);return s||this.handleUrlRequirementFailure(n,i.urlRequirement),s}triggerTransition(t){var e;const n=vt.getState(),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=vt.getState(),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,Xt))),!0}catch(s){return!1}}cleanupTransitions(){this.activeTransitions.forEach((t=>{t.cleanup()})),this.activeTransitions.clear(),this.waitingForInteraction=!1}setWaitingForInteraction(t){this.waitingForInteraction=t}isWaitingForInteraction(){return this.waitingForInteraction}reset(){this.cleanupTransitions()}destroy(){this.cleanupTransitions(),window.removeEventListener("popstate",this.handleURLChange)}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=document.querySelector(e);c?l(c):(r=new MutationObserver((t=>{for(const n of t)if("childList"===n.type&&n.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;if(n.matches(e))return void l(n);const i=n.querySelector(e);if(i)return void l(i)}})),!r)break})),r.observe(document.body,{childList:!0,subtree:!0}),o=window.setInterval((()=>{if(!r)return void(o&&clearInterval(o));const t=document.querySelector(e);t&&t.offsetWidth>0&&t.offsetHeight>0&&(o&&clearInterval(o),o=null,l(t))}),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(n){}}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(e){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.once})),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)this.evaluatePlaylistTrigger(t)}evaluatePlaylistTrigger(t){var e,n,i;if(!t.triggers)return;const{triggers:s}=t,r=t.id;if(this.triggeredPlaylistsSet.has(r))return;const a=vt.getState();if(!a.user)return;const o=[],l=this.evaluateOnceCondition(s.once,r,(null==(e=a.userData)?void 0:e.watchedPlaylists)||{});o.push(l);const c=this.evaluateURLCondition(s);o.push(c),s.url;const d=this.evaluatePlaylistSeenCondition(s.playlistSeen,(null==(n=a.userData)?void 0:n.watchedPlaylists)||{});o.push(d),JSON.stringify(s.playlistSeen);const h=this.evaluatePlaylistNotSeenCondition(s.playlistNotSeen,(null==(i=a.userData)?void 0:i.watchedPlaylists)||{});o.push(h),JSON.stringify(s.playlistNotSeen);const u=this.evaluateElementClickCondition(s.elementClicked);o.push(u),s.elementClicked;const p=this.evaluateElementVisibleCondition(s.elementVisible);o.push(p),s.elementVisible;const g=this.applyOperators(o,s.operators);s.operators.join(", "),g&&this.triggerPlaylist(r)}evaluateOnceCondition(t,e,n){if(!t)return!0;return!(n&&n[e])}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(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(c){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&&"in_progress"!==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){if(!t)return!0;return this.clickedElements.has(t)}evaluateElementVisibleCondition(t){if(!t)return!0;return this.visibleElements.has(t)}setupElementClickListeners(){this.clearElementClickListeners(),this.triggeredPlaylists.forEach((t=>{var e;(null==(e=t.triggers)?void 0:e.elementClicked)&&this.setupElementClickListener(t.id,t.triggers.elementClicked)}))}setupElementClickListener(t,e){try{const n=document.querySelector(e);if(!n)return;if(!this.triggeredPlaylists.find((e=>e.id===t)))return;const i=t=>{t.preventDefault(),t.stopPropagation(),this.clickedElements.add(e),this.evaluateAllTriggers()};n.addEventListener("click",i);const s=`${t}-${e}`;this.elementClickedListeners.set(s,{element:n,listener:i,selector:e})}catch(n){}}clearElementClickListeners(){this.elementClickedListeners.forEach((({element:t,listener:e})=>{try{t.removeEventListener("click",e)}catch(n){console.error("TriggerManager: Error removing element click listener:",n)}})),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)}))}setupElementVisibleObserver(t,e){try{const n=`${t}-${e}`;if(this.elementVisibleObservers.has(n))return;const i=t=>{const i=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});i.observe(t);const s=this.elementVisibleObservers.get(n);s?(s.mutationObserver&&s.mutationObserver.disconnect(),this.elementVisibleObservers.set(n,{observer:i,mutationObserver:null,selector:e})):this.elementVisibleObservers.set(n,{observer:i,mutationObserver:null,selector:e})},s=document.querySelector(e);if(s)i(s);else{const t=new MutationObserver((t=>{for(const n of t)"childList"===n.type&&n.addedNodes.forEach((t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;if(n.matches(e))i(n);else{const t=n.querySelector(e);t&&i(t)}}}))}));t.observe(document.body,{childList:!0,subtree:!0}),this.elementVisibleObservers.set(n,{observer:null,mutationObserver:t,selector:e})}}catch(n){}}clearElementVisibleObservers(){this.elementVisibleObservers.forEach((({observer:t,mutationObserver:e})=>{try{t&&t.disconnect(),e&&e.disconnect()}catch(n){console.error("TriggerManager: Error removing element visibility observer:",n)}})),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)}}resetTriggeredPlaylists(){this.triggeredPlaylistsSet.clear()}getTriggeredPlaylists(){return Array.from(this.triggeredPlaylistsSet)}destroy(){this.stopMonitoring(),this.clearElementClickListeners(),this.clearElementVisibleObservers(),this.triggeredPlaylists=[],this.triggeredPlaylistsSet.clear(),this.clickedElements.clear(),this.visibleElements.clear()}}class ne{constructor(t){e(this,"eventManager",null),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}subscribeToEvents(){this.eventManager&&this.eventManager.on("playlistStarted",(t=>{this.trackTestParticipation(t.playlist.id)}))}initializeTests(t){vt.getState().setABTests(t)}assignUserToTests(t,e,n){var i,s;const r=vt.getState(),a=r.abTests||[],o={...e};for(const l of a){const e=l.testType||"percentage";if("userList"!==e&&o[l.id])continue;let a=!1;if("userList"===e){a=!(!0===(null==(s=null==(i=r.user)?void 0:i.userData)?void 0:s.__isAnonymous))&&!0===(null==n?void 0:n[l.id])}else a=this.isUserInTest(t,l);o[l.id]={testId:l.id,assigned:a,assignedAt:Date.now()},l.name}return r.setABTestAssignments(o),o}isUserInTest(t,e){if(!e.percentage)return!1;const n=`${t}_${e.id}`;let i=0;for(let s=0;s<n.length;s++){i=(i<<5)-i+n.charCodeAt(s),i|=0}return Math.abs(i)%100<e.percentage}getFilteredPlaylists(t){const e=vt.getState(),n=e.abTests||[],i=e.abTestAssignments||{};if(0===n.length)return t;const s=new Set;for(const a of n){const t=i[a.id];t&&t.assigned||(s.add(a.playlistId),a.playlistId,a.name)}const r=t.filter((t=>!s.has(t.id)));return t.length,r.length,r}trackTestParticipation(t){var e;const n=vt.getState(),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 vt.getState().abTestAssignments||{}}isPlaylistAvailable(t){const e=vt.getState(),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=vt.getState(),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(i){console.error(`Error in ${t} event handler:`,i)}})))}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(s){const t=s instanceof Error?s.message:"Unknown error";throw K("[PlaylistLoader] Failed to load manifest:",s),new Error(`Unable to load playlist manifest: ${t}`)}}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 K("[PlaylistLoader] Fetch/parse failed:",e),K("[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 s of n)if(!(s in e))throw new Error(`Manifest missing required field: ${s}`);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 s of i){if("object"!=typeof s||null===s)throw new Error("Each step must be an object");const t=s;if(!t.id)throw new Error("Each step must have an id");if(!t.transitions||!Array.isArray(t.transitions))throw new Error(`Step '${t.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;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}=St(e);if(n){const n=e.currentStepId||e.lastStepId;if(n){t.steps.find((t=>t.id===n))&&(a=n)}}else a=t.startStep}}return a}}class re{constructor(t,n){e(this,"eventManager",null),e(this,"isUpdatingWatchedPlaylists",!1),e(this,"playlistLoader"),e(this,"storageManager"),this.playlistLoader=new se,this.storageManager=n||mt.getInstance(),t&&this.setEventManager(t)}setEventManager(t){this.eventManager=t,this.subscribeToEvents()}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,l;if(!this.isUpdatingWatchedPlaylists){this.isUpdatingWatchedPlaylists=!0;try{const d=Jt();if(!d)return;const h=d.userData||{},u=h.watchedPlaylists||{},p={status:e,currentStepId:"completed"===e?null:n||d.currentStepId||null,timestamp:Date.now(),lastProgressAt:Date.now()},g={...u,[t]:p};if(d.setUserData({...h,watchedPlaylists:g}),!(null==(i=null==d?void 0:d.config)?void 0:i.token)||!(null==(s=null==d?void 0:d.user)?void 0:s.id)||(null==(r=null==d?void 0:d.user)?void 0:r.__isAnonymous))return null==(a=null==d?void 0:d.config)||a.token,null==(o=null==d?void 0:d.user)||o.id,null==(l=null==d?void 0:d.user)||l.__isAnonymous,void this.updateAnonymousUserWatchedPlaylists(t,e,n||d.currentStepId||null);const m=`https://player.saltfish.ai/clients/${d.config.token}/users/${d.user.id}/playlists/${t}`;try{const t=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:e,currentStepId:n||d.currentStepId||null})});if(!t.ok)throw new Error(`Failed to update watched playlist status: ${t.statusText} (${t.status})`)}catch(c){console.error(`PlaylistManager: Error updating watched playlist status for ${t}:`,c)}}finally{this.isUpdatingWatchedPlaylists=!1}}}updateAnonymousUserWatchedPlaylists(t,e,n){if("undefined"==typeof window)return;let i=this.storageManager.getAnonymousUserData()||{userId:"anonymous",userData:{},watchedPlaylists:{},timestamp:Date.now()};i.watchedPlaylists||(i.watchedPlaylists={}),i.watchedPlaylists[t]={status:e,currentStepId:n||null,timestamp:Date.now(),lastProgressAt:Date.now()},i.timestamp=Date.now(),this.storageManager.setAnonymousUserData(i)}async load(t,e){var n;try{const i=Jt();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(i){const t=Jt(),e=i instanceof Error?i:new Error("Unknown error loading manifest");t?t.setError(e):console.error("[PlaylistManager] Cannot set error: Store not available",e)}}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='\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 ',this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(vt.getState().isMinimized)}handleClick(){const t=vt.getState(),e=!t.isMinimized;e?t.minimize():t.maximize(),e?this.minimize():this.maximize()}minimize(){this.button.innerHTML='\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 '}maximize(){this.button.innerHTML='\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 '}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='\n <svg 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 ',this.playButton.addEventListener("click",this.handlePlayClick.bind(this)),this.container.appendChild(this.playButton)}handlePlayClick(t){t&&t.stopPropagation();const e=vt.getState();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='\n <svg width="18" height="18" 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 ',this.button.addEventListener("click",this.handleClick.bind(this)),this.playerElement.appendChild(this.button),this.updateVisibility(vt.getState().isMinimized)}handleClick(t){t.stopPropagation();vt.getState().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=ct,this.errorOverlay.classList.add("sf-hidden");const t=document.createElement("div");t.className=ht;const e=document.createElement("p");e.className=ut,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(dt)}))}hide(){this.isVisible&&(this.errorOverlay.classList.remove(dt),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(`.${ut}`);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=`${pt}`,this.spinnerElement.innerHTML='\n <div class="sf-loading-spinner__content">\n <div class="sf-loading-spinner__icon">\n <svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">\n \x3c!-- Static Saltfish logo in center --\x3e\n <g transform="translate(10, 10) scale(0.656)">\n <g clip-path="url(#saltfish-clip)">\n <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"/>\n <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"/>\n </g>\n <defs>\n <clipPath id="saltfish-clip">\n <rect width="61" height="61" fill="white"/>\n </clipPath>\n </defs>\n </g>\n \n \x3c!-- Animated circular ring around logo --\x3e\n <circle cx="30" cy="30" r="28" \n stroke="black" stroke-width="2" \n fill="none" stroke-linecap="round"\n stroke-dasharray="8 6" stroke-opacity="0.3">\n <animateTransform attributeName="transform" \n type="rotate" \n values="0 30 30;360 30 30" \n dur="2s" \n repeatCount="indefinite"/>\n </circle>\n </svg>\n </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,"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=vt.getState();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=>{const e=vt.getState();if(e.isMinimized)return t.stopPropagation(),void this.handleMinimizeClick();const n=t.target;"BUTTON"===n.tagName||n.closest("button")||n.closest(".sf-controls-container")||"playing"===e.currentState&&e.pause()}))}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=vt.getState();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(at):this.playerElement.classList.remove(at)}handleMinimizeClick(){if(!this.playerElement)return;const t=vt.getState(),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=rt,t.appendChild(e),e}createControlsContainer(t){const e=document.createElement("div");return e.className=ot,t.appendChild(e),e}createSaltfishLogo(t){var e;if(!1===(null==(e=vt.getState().config)?void 0:e.showLogo))return;const n=document.createElement("div");n.className=lt,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=vt.getState();"playing"===n.currentState&&n.pause();const i=null==(e=n.config)?void 0:e.token;i?window.open(`https://www.saltfish.ai/demos?clientId=${i}`,"_blank"):(console.warn("UIManager: No token available, falling back to saltfish.ai homepage"),window.open("https://www.saltfish.ai/","_blank"))}))}initializeButtonManagement(){this.playerElement&&this.videoManager?(this.storeUnsubscribe=vt.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")))}createCenterPlayButton(){this.playerElement&&(this.centerPlayButton=document.createElement("button"),this.centerPlayButton.className="sf-player__center-play-button",this.centerPlayButton.innerHTML='\n <svg 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 ',this.playerElement.appendChild(this.centerPlayButton),this.centerPlayButton.addEventListener("click",(t=>{var e;t.stopPropagation(),t.preventDefault();const n=vt.getState();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();"paused"!==n.currentState&&"waitingForInteraction"!==n.currentState&&"completedWaitingForInteraction"!==n.currentState&&"autoplayBlocked"!==n.currentState&&"idleMode"!==n.currentState&&"error"!==n.currentState||n.play()})))}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.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;this.currentStepId;if(!("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",nt);let pe=ue;class ge{createManagers(){const t=mt.getInstance(),e=new Qt(t),n=new zt,i=new Ht,s=new ie,r=new Gt(s),a=new re(s,t),o=new ne(s),l=new Zt,c=new Kt,d=new te,h=new ee,u=new pe((()=>{}));d.setTriggerManager(h);return{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(e){console.error("ManagerFactory: Error resetting managers:",e)}}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(e){console.error("ManagerFactory: Error destroying managers:",e)}}}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),t.instance)throw new Error("SaltfishPlayer is a singleton. Use getInstance()");this.managerFactory=new ge;const n=this.managerFactory.createManagers();this.playerInitializationService=new Et(n),this.userManagementService=new It(n),this.playlistOrchestrator=new xt(n),this.stateMachineActionHandler=new Ct(n),this.managerOrchestrator=new At(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())),vt.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)console.warn("Saltfish playlist Player is already initialized");else 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(e){throw e}}identifyUser(t,e){this.userManagementService.identifyUser(t,e)}async identifyAnonymous(t){await this.userManagementService.identifyAnonymous(t)}async startPlaylist(t,e){await this.playlistOrchestrator.startPlaylist(t,e)}resetPlaylist(){this.playlistOrchestrator.resetPlaylist()}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="0.3.13";const be=function(){const t=fe.getInstance();let e=!1,n=!1,i=null;const s=[],r={init:r=>{if(n)return q("Saltfish already initialized"),Promise.resolve();if(e&&i)return i;const a={enableAnalytics:!0,..."string"==typeof r?{token:r}:r};return q(`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 e=s.shift();if(e)try{await e()}catch(t){K("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(i){n(i)}})),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()})):Z("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):Z("Cannot destroy - Saltfish not initialized")},getSessionId:()=>t.getSessionId(),getRunId:()=>t.getRunId(),version:()=>ve};return r.__dev__={getDeviceInfo:()=>Lt.getDeviceInfo()},r}();return"undefined"!=typeof window&&(window.saltfish=be),be}));
|
|
9
9
|
|