stormcloud-video-player 0.2.15 → 0.2.17

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/lib/index.cjs CHANGED
@@ -351,6 +351,14 @@ function createImaController(video, options) {
351
351
  function makeAdsRequest(google, vastTagUrl) {
352
352
  const adsRequest = new google.ima.AdsRequest();
353
353
  adsRequest.adTagUrl = vastTagUrl;
354
+ const videoWidth = video.offsetWidth || video.clientWidth || 640;
355
+ const videoHeight = video.offsetHeight || video.clientHeight || 360;
356
+ adsRequest.linearAdSlotWidth = videoWidth;
357
+ adsRequest.linearAdSlotHeight = videoHeight;
358
+ adsRequest.nonLinearAdSlotWidth = videoWidth;
359
+ adsRequest.nonLinearAdSlotHeight = videoHeight;
360
+ adsRequest.vastLoadTimeout = 5e3;
361
+ console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
354
362
  adsLoader.requestAds(adsRequest);
355
363
  }
356
364
  function destroyAdsManager() {
@@ -397,6 +405,18 @@ function createImaController(video, options) {
397
405
  },
398
406
  async requestAds(vastTagUrl) {
399
407
  console.log("[IMA] Requesting ads:", vastTagUrl);
408
+ if (!vastTagUrl || vastTagUrl.trim() === "") {
409
+ const error = new Error("VAST tag URL is empty or undefined");
410
+ console.warn("[IMA]", error.message);
411
+ return Promise.reject(error);
412
+ }
413
+ try {
414
+ new URL(vastTagUrl);
415
+ } catch (e) {
416
+ const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
417
+ console.warn("[IMA]", error.message);
418
+ return Promise.reject(error);
419
+ }
400
420
  if (adPlaying) {
401
421
  console.warn(
402
422
  "[IMA] Cannot request new ads while an ad is playing. Call stop() first."
@@ -458,6 +478,18 @@ function createImaController(video, options) {
458
478
  );
459
479
  }
460
480
  }
481
+ const videoWidth = video.offsetWidth || video.clientWidth;
482
+ const videoHeight = video.offsetHeight || video.clientHeight;
483
+ if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
484
+ const error = new Error(
485
+ `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
486
+ );
487
+ console.warn("[IMA]", error.message);
488
+ currentReject == null ? void 0 : currentReject(error);
489
+ adsLoadedReject = void 0;
490
+ adsLoadedResolve = void 0;
491
+ return Promise.reject(error);
492
+ }
461
493
  if (!adsLoader) {
462
494
  console.log("[IMA] Creating ads loader");
463
495
  const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
@@ -506,7 +538,9 @@ function createImaController(video, options) {
506
538
  emit("ad_error");
507
539
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
508
540
  if (video.paused) {
509
- console.log("[IMA] Resuming paused video after ad error");
541
+ console.log(
542
+ "[IMA] Resuming paused video after ad error"
543
+ );
510
544
  (_a = video.play()) == null ? void 0 : _a.catch(() => {
511
545
  });
512
546
  }
@@ -608,7 +642,9 @@ function createImaController(video, options) {
608
642
  }
609
643
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
610
644
  if (video.paused) {
611
- console.log("[IMA] Resuming paused video after setup error");
645
+ console.log(
646
+ "[IMA] Resuming paused video after setup error"
647
+ );
612
648
  video.play().catch(() => {
613
649
  });
614
650
  }
@@ -1803,6 +1839,8 @@ var StormcloudVideoPlayer = class {
1803
1839
  this.totalAdsInBreak = 0;
1804
1840
  this.showAds = false;
1805
1841
  this.isLiveStream = false;
1842
+ this.nativeHlsMode = false;
1843
+ this.videoSrcProtection = null;
1806
1844
  initializePolyfills();
1807
1845
  const browserOverrides = getBrowserConfigOverrides();
1808
1846
  this.config = { ...config, ...browserOverrides };
@@ -1823,7 +1861,9 @@ var StormcloudVideoPlayer = class {
1823
1861
  }
1824
1862
  if (adPlayerType === "hls") {
1825
1863
  if (this.config.debugAdTiming) {
1826
- console.log("[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)");
1864
+ console.log(
1865
+ "[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)"
1866
+ );
1827
1867
  }
1828
1868
  return createHlsAdPlayer(this.video, {
1829
1869
  continueLiveStreamDuringAds,
@@ -1832,7 +1872,9 @@ var StormcloudVideoPlayer = class {
1832
1872
  });
1833
1873
  } else {
1834
1874
  if (this.config.debugAdTiming) {
1835
- console.log("[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)");
1875
+ console.log(
1876
+ "[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)"
1877
+ );
1836
1878
  }
1837
1879
  return createImaController(this.video, {
1838
1880
  continueLiveStreamDuringAds
@@ -1856,11 +1898,13 @@ var StormcloudVideoPlayer = class {
1856
1898
  }
1857
1899
  this.initializeTracking();
1858
1900
  if (this.shouldUseNativeHls()) {
1901
+ this.nativeHlsMode = true;
1902
+ this.videoSrcProtection = this.config.src;
1859
1903
  this.video.src = this.config.src;
1860
1904
  this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1861
1905
  if (this.config.debugAdTiming) {
1862
1906
  console.log(
1863
- "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
1907
+ "[StormcloudVideoPlayer] Using native HLS playback - VOD mode:",
1864
1908
  {
1865
1909
  isLive: this.isLiveStream,
1866
1910
  allowNativeHls: this.config.allowNativeHls,
@@ -2008,7 +2052,9 @@ var StormcloudVideoPlayer = class {
2008
2052
  this.ima.initialize();
2009
2053
  this.ima.on("all_ads_completed", () => {
2010
2054
  if (this.config.debugAdTiming) {
2011
- console.log("[StormcloudVideoPlayer] IMA all_ads_completed event received");
2055
+ console.log(
2056
+ "[StormcloudVideoPlayer] IMA all_ads_completed event received"
2057
+ );
2012
2058
  }
2013
2059
  });
2014
2060
  this.ima.on("ad_error", () => {
@@ -2073,13 +2119,31 @@ var StormcloudVideoPlayer = class {
2073
2119
  this.video.addEventListener("timeupdate", () => {
2074
2120
  this.onTimeUpdate(this.video.currentTime);
2075
2121
  });
2122
+ this.video.addEventListener("emptied", () => {
2123
+ if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
2124
+ if (this.config.debugAdTiming) {
2125
+ console.log(
2126
+ "[StormcloudVideoPlayer] Video src was cleared, restoring:",
2127
+ this.videoSrcProtection
2128
+ );
2129
+ }
2130
+ const currentTime = this.video.currentTime;
2131
+ const wasPaused = this.video.paused;
2132
+ this.video.src = this.videoSrcProtection;
2133
+ this.video.currentTime = currentTime;
2134
+ if (!wasPaused) {
2135
+ this.video.play().catch(() => {
2136
+ });
2137
+ }
2138
+ }
2139
+ });
2076
2140
  }
2077
2141
  shouldUseNativeHls() {
2078
2142
  const streamType = this.getStreamType();
2079
2143
  if (streamType === "other") {
2080
2144
  return true;
2081
2145
  }
2082
- const canNative = this.video.canPlayType("application/vnd.apple.mpegURL");
2146
+ const canNative = this.video.canPlayType("application/vnd.apple.mpegurl");
2083
2147
  return !!(this.config.allowNativeHls && canNative);
2084
2148
  }
2085
2149
  onId3Tag(tag) {
@@ -2506,10 +2570,7 @@ var StormcloudVideoPlayer = class {
2506
2570
  var _a, _b, _c;
2507
2571
  const vastMode = this.config.vastMode || "default";
2508
2572
  if (this.config.debugAdTiming) {
2509
- console.log(
2510
- "[StormcloudVideoPlayer] VAST mode:",
2511
- vastMode
2512
- );
2573
+ console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
2513
2574
  }
2514
2575
  if (vastMode === "adstorm") {
2515
2576
  if (!this.config.licenseKey) {
@@ -2627,10 +2688,7 @@ var StormcloudVideoPlayer = class {
2627
2688
  this.currentAdIndex = 0;
2628
2689
  this.totalAdsInBreak = 1;
2629
2690
  if (this.config.debugAdTiming) {
2630
- console.log(
2631
- "[StormcloudVideoPlayer] Using VAST endpoint:",
2632
- vastTagUrl
2633
- );
2691
+ console.log("[StormcloudVideoPlayer] Using VAST endpoint:", vastTagUrl);
2634
2692
  }
2635
2693
  } else if (tags && tags.length > 0) {
2636
2694
  vastTagUrl = tags[0];
@@ -2782,15 +2840,21 @@ var StormcloudVideoPlayer = class {
2782
2840
  await this.ima.requestAds(vastTagUrl);
2783
2841
  try {
2784
2842
  if (this.config.debugAdTiming) {
2785
- console.log("[StormcloudVideoPlayer] Ad request completed, attempting playback");
2843
+ console.log(
2844
+ "[StormcloudVideoPlayer] Ad request completed, attempting playback"
2845
+ );
2786
2846
  }
2787
2847
  await this.ima.play();
2788
2848
  if (this.config.debugAdTiming) {
2789
- console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2849
+ console.log(
2850
+ "[StormcloudVideoPlayer] Ad playback started successfully"
2851
+ );
2790
2852
  }
2791
2853
  } catch (playError) {
2792
2854
  if (this.config.debugAdTiming) {
2793
- console.log("[StormcloudVideoPlayer] No ads available, skipping playback");
2855
+ console.log(
2856
+ "[StormcloudVideoPlayer] No ads available, skipping playback"
2857
+ );
2794
2858
  }
2795
2859
  this.handleAdFailure();
2796
2860
  return;
@@ -2846,7 +2910,9 @@ var StormcloudVideoPlayer = class {
2846
2910
  });
2847
2911
  } else {
2848
2912
  if (this.config.debugAdTiming) {
2849
- console.log("[StormcloudVideoPlayer] Video is already playing, no resume needed");
2913
+ console.log(
2914
+ "[StormcloudVideoPlayer] Video is already playing, no resume needed"
2915
+ );
2850
2916
  }
2851
2917
  }
2852
2918
  }
@@ -2865,7 +2931,11 @@ var StormcloudVideoPlayer = class {
2865
2931
  if (this.config.debugAdTiming) {
2866
2932
  console.warn(
2867
2933
  "[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
2868
- { paused: this.video.paused, showAds: this.showAds, adPlaying: this.ima.isAdPlaying() }
2934
+ {
2935
+ paused: this.video.paused,
2936
+ showAds: this.showAds,
2937
+ adPlaying: this.ima.isAdPlaying()
2938
+ }
2869
2939
  );
2870
2940
  }
2871
2941
  this.handleAdFailure();
@@ -3061,6 +3131,19 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3061
3131
  const [isBuffering, setIsBuffering] = import_react.default.useState(false);
3062
3132
  const [showCenterPlay, setShowCenterPlay] = import_react.default.useState(false);
3063
3133
  const [showLicenseWarning, setShowLicenseWarning] = import_react.default.useState(false);
3134
+ const [viewportWidth, setViewportWidth] = import_react.default.useState(
3135
+ typeof window !== "undefined" ? window.innerWidth : 1920
3136
+ );
3137
+ const [isPortrait, setIsPortrait] = import_react.default.useState(
3138
+ typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false
3139
+ );
3140
+ const getResponsiveScale = () => {
3141
+ if (viewportWidth < 480) return 0.7;
3142
+ if (viewportWidth < 768) return 0.8;
3143
+ if (viewportWidth < 1024) return 0.9;
3144
+ return 1;
3145
+ };
3146
+ const responsiveScale = getResponsiveScale();
3064
3147
  const formatTime = (seconds) => {
3065
3148
  if (!isFinite(seconds)) return "0:00:00";
3066
3149
  const hours = Math.floor(seconds / 3600);
@@ -3069,10 +3152,20 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3069
3152
  return `${hours}:${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
3070
3153
  };
3071
3154
  const handlePlayPause = () => {
3155
+ var _a;
3072
3156
  if (videoRef.current) {
3073
3157
  if (videoRef.current.paused) {
3074
- videoRef.current.play();
3075
- setShowCenterPlay(false);
3158
+ const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== "" || videoRef.current.readyState >= 1;
3159
+ if (hasValidSource) {
3160
+ (_a = videoRef.current.play()) == null ? void 0 : _a.catch((error) => {
3161
+ console.error("[StormcloudVideoPlayer] Failed to play:", error);
3162
+ });
3163
+ setShowCenterPlay(false);
3164
+ } else {
3165
+ console.warn(
3166
+ "[StormcloudVideoPlayer] Cannot play: video has no valid source"
3167
+ );
3168
+ }
3076
3169
  } else {
3077
3170
  videoRef.current.pause();
3078
3171
  setShowCenterPlay(true);
@@ -3080,9 +3173,19 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3080
3173
  }
3081
3174
  };
3082
3175
  const handleCenterPlayClick = () => {
3176
+ var _a;
3083
3177
  if (videoRef.current && videoRef.current.paused) {
3084
- videoRef.current.play();
3085
- setShowCenterPlay(false);
3178
+ const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== "" || videoRef.current.readyState >= 1;
3179
+ if (hasValidSource) {
3180
+ (_a = videoRef.current.play()) == null ? void 0 : _a.catch((error) => {
3181
+ console.error("[StormcloudVideoPlayer] Failed to play:", error);
3182
+ });
3183
+ setShowCenterPlay(false);
3184
+ } else {
3185
+ console.warn(
3186
+ "[StormcloudVideoPlayer] Cannot play: video has no valid source"
3187
+ );
3188
+ }
3086
3189
  }
3087
3190
  };
3088
3191
  const handleTimelineSeek = (e) => {
@@ -3113,7 +3216,14 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3113
3216
  const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);
3114
3217
  const criticalPropsKey = (0, import_react.useMemo)(() => {
3115
3218
  return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
3116
- }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs, vastMode]);
3219
+ }, [
3220
+ src,
3221
+ allowNativeHls,
3222
+ licenseKey,
3223
+ lowLatencyMode,
3224
+ driftToleranceMs,
3225
+ vastMode
3226
+ ]);
3117
3227
  (0, import_react.useEffect)(() => {
3118
3228
  if (typeof window === "undefined") return;
3119
3229
  const el = videoRef.current;
@@ -3217,6 +3327,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3217
3327
  playerRef.current.resize();
3218
3328
  }
3219
3329
  }
3330
+ setViewportWidth(window.innerWidth);
3331
+ setIsPortrait(window.innerHeight > window.innerWidth);
3220
3332
  };
3221
3333
  window.addEventListener("resize", handleResize);
3222
3334
  return () => window.removeEventListener("resize", handleResize);
@@ -3533,14 +3645,14 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3533
3645
  },
3534
3646
  onMouseEnter: (e) => {
3535
3647
  const target = e.currentTarget;
3536
- target.style.transform = "translate(-50%, -50%) scale(1.1)";
3648
+ target.style.transform = "translate(-50%, -50%)";
3537
3649
  target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)";
3538
3650
  target.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
3539
3651
  target.style.borderColor = "rgba(255, 255, 255, 0.9)";
3540
3652
  },
3541
3653
  onMouseLeave: (e) => {
3542
3654
  const target = e.currentTarget;
3543
- target.style.transform = "translate(-50%, -50%) scale(1)";
3655
+ target.style.transform = "translate(-50%, -50%)";
3544
3656
  target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)";
3545
3657
  target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
3546
3658
  target.style.borderColor = "rgba(255, 255, 255, 0.8)";
@@ -3630,7 +3742,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3630
3742
  display: "flex",
3631
3743
  alignItems: "center",
3632
3744
  justifyContent: "space-between",
3633
- color: "white"
3745
+ color: "white",
3746
+ flexWrap: viewportWidth < 768 ? "wrap" : "nowrap",
3747
+ gap: `${8 * responsiveScale}px`
3634
3748
  },
3635
3749
  children: [
3636
3750
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
@@ -3639,7 +3753,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3639
3753
  style: {
3640
3754
  display: "flex",
3641
3755
  alignItems: "center",
3642
- gap: "12px"
3756
+ gap: `${12 * responsiveScale}px`,
3757
+ flexWrap: viewportWidth < 480 ? "wrap" : "nowrap"
3643
3758
  },
3644
3759
  children: [
3645
3760
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -3647,44 +3762,42 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3647
3762
  {
3648
3763
  onClick: handlePlayPause,
3649
3764
  style: {
3650
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)",
3651
- backdropFilter: "blur(10px)",
3652
- border: "1px solid rgba(255, 255, 255, 0.2)",
3765
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
3766
+ backdropFilter: "blur(12px)",
3767
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3653
3768
  color: "#ffffff",
3654
3769
  cursor: "pointer",
3655
- padding: "12px",
3656
- borderRadius: "12px",
3770
+ padding: `${10 * responsiveScale}px`,
3771
+ borderRadius: `${16 * responsiveScale}px`,
3657
3772
  display: "flex",
3658
3773
  alignItems: "center",
3659
3774
  justifyContent: "center",
3660
3775
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3661
- boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2)",
3662
- minWidth: "48px",
3663
- minHeight: "48px"
3776
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
3777
+ minWidth: `${48 * responsiveScale}px`,
3778
+ minHeight: `${48 * responsiveScale}px`
3664
3779
  },
3665
3780
  onMouseEnter: (e) => {
3666
3781
  const target = e.target;
3667
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.1) 100%)";
3668
- target.style.transform = "translateY(-2px) scale(1.05)";
3669
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
3782
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
3783
+ target.style.boxShadow = "0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
3670
3784
  },
3671
3785
  onMouseLeave: (e) => {
3672
3786
  const target = e.target;
3673
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
3674
- target.style.transform = "translateY(0) scale(1)";
3675
- target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
3787
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
3788
+ target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
3676
3789
  },
3677
3790
  title: isPlaying ? "Pause" : "Play",
3678
3791
  children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3679
3792
  import_fa.FaPause,
3680
3793
  {
3681
- size: 20,
3794
+ size: Math.max(16, 20 * responsiveScale),
3682
3795
  style: { filter: "drop-shadow(0 0 0 transparent)" }
3683
3796
  }
3684
3797
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3685
3798
  import_fa.FaPlay,
3686
3799
  {
3687
- size: 20,
3800
+ size: Math.max(16, 20 * responsiveScale),
3688
3801
  style: { filter: "drop-shadow(0 0 0 transparent)" }
3689
3802
  }
3690
3803
  )
@@ -3707,45 +3820,44 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3707
3820
  "button",
3708
3821
  {
3709
3822
  onClick: () => {
3823
+ if (playerRef.current) {
3824
+ playerRef.current.toggleMute();
3825
+ }
3710
3826
  if (onVolumeToggle) {
3711
3827
  onVolumeToggle();
3712
- } else if (playerRef.current) {
3713
- playerRef.current.toggleMute();
3714
3828
  }
3715
3829
  },
3716
3830
  style: {
3717
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)",
3718
- backdropFilter: "blur(8px)",
3719
- border: "1px solid rgba(255, 255, 255, 0.15)",
3720
- color: isMuted ? "#ff6b6b" : "#ffffff",
3831
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
3832
+ backdropFilter: "blur(10px)",
3833
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3834
+ color: "#ffffff",
3721
3835
  cursor: "pointer",
3722
- padding: "10px",
3723
- borderRadius: "10px",
3836
+ padding: `${8 * responsiveScale}px`,
3837
+ borderRadius: `${16 * responsiveScale}px`,
3724
3838
  display: "flex",
3725
3839
  alignItems: "center",
3726
3840
  justifyContent: "center",
3727
3841
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3728
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
3729
- minWidth: "40px",
3730
- minHeight: "40px"
3842
+ boxShadow: "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)",
3843
+ minWidth: `${44 * responsiveScale}px`,
3844
+ minHeight: `${44 * responsiveScale}px`
3731
3845
  },
3732
3846
  onMouseEnter: (e) => {
3733
3847
  const target = e.target;
3734
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.08) 100%)";
3735
- target.style.transform = "translateY(-1px) scale(1.03)";
3736
- target.style.boxShadow = "0 8px 28px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
3848
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
3849
+ target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)";
3737
3850
  },
3738
3851
  onMouseLeave: (e) => {
3739
3852
  const target = e.target;
3740
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)";
3741
- target.style.transform = "translateY(0) scale(1)";
3742
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
3853
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
3854
+ target.style.boxShadow = "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)";
3743
3855
  },
3744
3856
  title: isMuted ? "Unmute" : "Mute",
3745
3857
  children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3746
3858
  import_fa.FaVolumeMute,
3747
3859
  {
3748
- size: 16,
3860
+ size: Math.max(14, 16 * responsiveScale),
3749
3861
  style: {
3750
3862
  filter: "drop-shadow(0 0 0 transparent)"
3751
3863
  }
@@ -3753,7 +3865,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3753
3865
  ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3754
3866
  import_fa.FaVolumeDown,
3755
3867
  {
3756
- size: 16,
3868
+ size: Math.max(14, 16 * responsiveScale),
3757
3869
  style: {
3758
3870
  filter: "drop-shadow(0 0 0 transparent)"
3759
3871
  }
@@ -3761,7 +3873,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3761
3873
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3762
3874
  import_fa.FaVolumeUp,
3763
3875
  {
3764
- size: 16,
3876
+ size: Math.max(14, 16 * responsiveScale),
3765
3877
  style: {
3766
3878
  filter: "drop-shadow(0 0 0 transparent)"
3767
3879
  }
@@ -3812,13 +3924,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3812
3924
  },
3813
3925
  onMouseEnter: (e) => {
3814
3926
  setShowVolumeSlider(true);
3815
- e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
3816
3927
  e.currentTarget.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)";
3817
3928
  e.currentTarget.style.borderColor = "rgba(59, 130, 246, 0.4)";
3818
3929
  },
3819
3930
  onMouseLeave: (e) => {
3820
3931
  setShowVolumeSlider(false);
3821
- e.currentTarget.style.transform = "translateX(-50%)";
3822
3932
  e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)";
3823
3933
  e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.15)";
3824
3934
  },
@@ -3833,10 +3943,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3833
3943
  transition: "transform 0.2s ease-in-out"
3834
3944
  },
3835
3945
  onMouseEnter: (e) => {
3836
- e.currentTarget.style.transform = "scaleX(1.2)";
3837
3946
  },
3838
3947
  onMouseLeave: (e) => {
3839
- e.currentTarget.style.transform = "scaleX(1)";
3840
3948
  },
3841
3949
  onMouseDown: (e) => {
3842
3950
  e.preventDefault();
@@ -3849,11 +3957,23 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3849
3957
  handleVolumeChange(percentage2);
3850
3958
  };
3851
3959
  const handleMouseUp = () => {
3852
- document.removeEventListener("mousemove", handleMouseMove);
3853
- document.removeEventListener("mouseup", handleMouseUp);
3960
+ document.removeEventListener(
3961
+ "mousemove",
3962
+ handleMouseMove
3963
+ );
3964
+ document.removeEventListener(
3965
+ "mouseup",
3966
+ handleMouseUp
3967
+ );
3854
3968
  };
3855
- document.addEventListener("mousemove", handleMouseMove);
3856
- document.addEventListener("mouseup", handleMouseUp);
3969
+ document.addEventListener(
3970
+ "mousemove",
3971
+ handleMouseMove
3972
+ );
3973
+ document.addEventListener(
3974
+ "mouseup",
3975
+ handleMouseUp
3976
+ );
3857
3977
  const rect = sliderElement.getBoundingClientRect();
3858
3978
  const y = e.clientY - rect.top;
3859
3979
  const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
@@ -3915,20 +4035,16 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3915
4035
  cursor: "grab"
3916
4036
  },
3917
4037
  onMouseEnter: (e) => {
3918
- e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
3919
4038
  e.currentTarget.style.boxShadow = "0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)";
3920
4039
  e.currentTarget.style.cursor = "grab";
3921
4040
  },
3922
4041
  onMouseLeave: (e) => {
3923
- e.currentTarget.style.transform = "translateX(-50%) scale(1)";
3924
4042
  e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)";
3925
4043
  },
3926
4044
  onMouseDown: (e) => {
3927
- e.currentTarget.style.transform = "translateX(-50%) scale(1.4)";
3928
4045
  e.currentTarget.style.cursor = "grabbing";
3929
4046
  },
3930
4047
  onMouseUp: (e) => {
3931
- e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
3932
4048
  e.currentTarget.style.cursor = "grab";
3933
4049
  }
3934
4050
  }
@@ -3946,9 +4062,10 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3946
4062
  "div",
3947
4063
  {
3948
4064
  style: {
3949
- fontSize: "14px",
4065
+ fontSize: `${14 * responsiveScale}px`,
3950
4066
  fontFamily: "monospace",
3951
- color: "rgba(255, 255, 255, 0.9)"
4067
+ color: "rgba(255, 255, 255, 0.9)",
4068
+ display: viewportWidth < 480 ? "none" : "block"
3952
4069
  },
3953
4070
  children: [
3954
4071
  formatTime(currentTime),
@@ -3966,105 +4083,113 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3966
4083
  style: {
3967
4084
  display: "flex",
3968
4085
  alignItems: "center",
3969
- gap: "12px"
4086
+ gap: `${12 * responsiveScale}px`
3970
4087
  },
3971
4088
  children: [
3972
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
3973
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3974
- "button",
3975
- {
3976
- onClick: () => setShowSpeedMenu(!showSpeedMenu),
3977
- style: {
3978
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 100%)",
3979
- backdropFilter: "blur(8px)",
3980
- border: "1px solid rgba(255, 255, 255, 0.12)",
3981
- color: "#ffffff",
3982
- cursor: "pointer",
3983
- padding: "8px 14px",
3984
- borderRadius: "8px",
3985
- fontSize: "13px",
3986
- fontFamily: "monospace",
3987
- fontWeight: "600",
3988
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3989
- boxShadow: "0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08)",
3990
- minWidth: "50px"
3991
- },
3992
- onMouseEnter: (e) => {
3993
- const target = e.target;
3994
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0.06) 100%)";
3995
- target.style.transform = "translateY(-1px) scale(1.02)";
3996
- target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)";
3997
- },
3998
- onMouseLeave: (e) => {
3999
- const target = e.target;
4000
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 100%)";
4001
- target.style.transform = "translateY(0) scale(1)";
4002
- target.style.boxShadow = "0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08)";
4003
- },
4004
- title: "Playback Speed",
4005
- children: [
4006
- playbackRate,
4007
- "x"
4008
- ]
4009
- }
4010
- ),
4011
- showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4012
- "div",
4013
- {
4014
- style: {
4015
- position: "absolute",
4016
- bottom: "100%",
4017
- right: 0,
4018
- marginBottom: "12px",
4019
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
4020
- backdropFilter: "blur(20px)",
4021
- borderRadius: "12px",
4022
- border: "1px solid rgba(255, 255, 255, 0.1)",
4023
- overflow: "hidden",
4024
- minWidth: "90px",
4025
- boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
4026
- },
4027
- children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
4028
- (speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
4029
- "button",
4030
- {
4031
- onClick: () => handlePlaybackRateChange(speed),
4032
- style: {
4033
- display: "block",
4034
- width: "100%",
4035
- padding: "10px 16px",
4036
- background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
4037
- border: "none",
4038
- color: "white",
4039
- cursor: "pointer",
4040
- fontSize: "13px",
4041
- fontFamily: "monospace",
4042
- fontWeight: "600",
4043
- textAlign: "center",
4044
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
4045
- borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
4046
- },
4047
- onMouseEnter: (e) => {
4048
- if (playbackRate !== speed) {
4049
- e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
4050
- }
4051
- },
4052
- onMouseLeave: (e) => {
4053
- if (playbackRate !== speed) {
4054
- e.target.style.background = "transparent";
4055
- }
4056
- },
4057
- children: [
4058
- speed,
4059
- "x"
4060
- ]
4089
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
4090
+ "div",
4091
+ {
4092
+ style: {
4093
+ position: "relative",
4094
+ display: viewportWidth < 600 ? "none" : "block"
4095
+ },
4096
+ children: [
4097
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
4098
+ "button",
4099
+ {
4100
+ onClick: () => setShowSpeedMenu(!showSpeedMenu),
4101
+ style: {
4102
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
4103
+ backdropFilter: "blur(10px)",
4104
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
4105
+ color: "#ffffff",
4106
+ cursor: "pointer",
4107
+ padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,
4108
+ borderRadius: `${14 * responsiveScale}px`,
4109
+ fontSize: `${14 * responsiveScale}px`,
4110
+ fontFamily: "monospace",
4111
+ fontWeight: "700",
4112
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
4113
+ boxShadow: "0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)",
4114
+ minWidth: `${56 * responsiveScale}px`,
4115
+ minHeight: `${40 * responsiveScale}px`
4061
4116
  },
4062
- speed
4063
- )
4117
+ onMouseEnter: (e) => {
4118
+ const target = e.target;
4119
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
4120
+ target.style.boxShadow = "0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)";
4121
+ },
4122
+ onMouseLeave: (e) => {
4123
+ const target = e.target;
4124
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
4125
+ target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)";
4126
+ },
4127
+ title: "Playback Speed",
4128
+ children: [
4129
+ playbackRate,
4130
+ "x"
4131
+ ]
4132
+ }
4133
+ ),
4134
+ showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4135
+ "div",
4136
+ {
4137
+ style: {
4138
+ position: "absolute",
4139
+ bottom: "100%",
4140
+ right: 0,
4141
+ marginBottom: "12px",
4142
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
4143
+ backdropFilter: "blur(20px)",
4144
+ borderRadius: "12px",
4145
+ border: "1px solid rgba(255, 255, 255, 0.1)",
4146
+ overflow: "hidden",
4147
+ minWidth: "90px",
4148
+ boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
4149
+ },
4150
+ children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
4151
+ (speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
4152
+ "button",
4153
+ {
4154
+ onClick: () => handlePlaybackRateChange(speed),
4155
+ style: {
4156
+ display: "block",
4157
+ width: "100%",
4158
+ padding: "10px 16px",
4159
+ background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
4160
+ border: "none",
4161
+ color: "white",
4162
+ cursor: "pointer",
4163
+ fontSize: "13px",
4164
+ fontFamily: "monospace",
4165
+ fontWeight: "600",
4166
+ textAlign: "center",
4167
+ transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
4168
+ borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
4169
+ },
4170
+ onMouseEnter: (e) => {
4171
+ if (playbackRate !== speed) {
4172
+ e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
4173
+ }
4174
+ },
4175
+ onMouseLeave: (e) => {
4176
+ if (playbackRate !== speed) {
4177
+ e.target.style.background = "transparent";
4178
+ }
4179
+ },
4180
+ children: [
4181
+ speed,
4182
+ "x"
4183
+ ]
4184
+ },
4185
+ speed
4186
+ )
4187
+ )
4188
+ }
4064
4189
  )
4065
- }
4066
- )
4067
- ] }),
4190
+ ]
4191
+ }
4192
+ ),
4068
4193
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4069
4194
  "button",
4070
4195
  {
@@ -4078,44 +4203,42 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4078
4203
  }
4079
4204
  },
4080
4205
  style: {
4081
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)",
4082
- backdropFilter: "blur(8px)",
4083
- border: "1px solid rgba(255, 255, 255, 0.15)",
4206
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
4207
+ backdropFilter: "blur(10px)",
4208
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
4084
4209
  color: "#ffffff",
4085
4210
  cursor: "pointer",
4086
- padding: "10px",
4087
- borderRadius: "10px",
4211
+ padding: `${8 * responsiveScale}px`,
4212
+ borderRadius: `${16 * responsiveScale}px`,
4088
4213
  display: "flex",
4089
4214
  alignItems: "center",
4090
4215
  justifyContent: "center",
4091
4216
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
4092
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
4093
- minWidth: "40px",
4094
- minHeight: "40px"
4217
+ boxShadow: "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)",
4218
+ minWidth: `${44 * responsiveScale}px`,
4219
+ minHeight: `${44 * responsiveScale}px`
4095
4220
  },
4096
4221
  onMouseEnter: (e) => {
4097
4222
  const target = e.target;
4098
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.08) 100%)";
4099
- target.style.transform = "translateY(-1px) scale(1.03)";
4100
- target.style.boxShadow = "0 8px 28px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
4223
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
4224
+ target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)";
4101
4225
  },
4102
4226
  onMouseLeave: (e) => {
4103
4227
  const target = e.target;
4104
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)";
4105
- target.style.transform = "translateY(0) scale(1)";
4106
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
4228
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
4229
+ target.style.boxShadow = "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)";
4107
4230
  },
4108
4231
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
4109
4232
  children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4110
4233
  import_fa.FaCompress,
4111
4234
  {
4112
- size: 16,
4235
+ size: Math.max(14, 16 * responsiveScale),
4113
4236
  style: { filter: "drop-shadow(0 0 0 transparent)" }
4114
4237
  }
4115
4238
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4116
4239
  import_fa.FaExpand,
4117
4240
  {
4118
- size: 16,
4241
+ size: Math.max(14, 16 * responsiveScale),
4119
4242
  style: { filter: "drop-shadow(0 0 0 transparent)" }
4120
4243
  }
4121
4244
  )
@@ -4134,10 +4257,12 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4134
4257
  {
4135
4258
  style: {
4136
4259
  position: "absolute",
4137
- bottom: "10px",
4138
- right: "10px",
4260
+ bottom: `${10 * responsiveScale}px`,
4261
+ right: `${10 * responsiveScale}px`,
4262
+ transform: "none",
4139
4263
  display: "flex",
4140
- gap: "8px",
4264
+ flexDirection: isPortrait ? "column" : "row",
4265
+ gap: `${10 * responsiveScale}px`,
4141
4266
  zIndex: 10
4142
4267
  },
4143
4268
  children: [
@@ -4158,45 +4283,44 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4158
4283
  "button",
4159
4284
  {
4160
4285
  onClick: () => {
4286
+ if (playerRef.current) {
4287
+ playerRef.current.toggleMute();
4288
+ }
4161
4289
  if (onVolumeToggle) {
4162
4290
  onVolumeToggle();
4163
- } else if (playerRef.current) {
4164
- playerRef.current.toggleMute();
4165
4291
  }
4166
4292
  },
4167
4293
  onMouseEnter: (e) => {
4168
4294
  const target = e.currentTarget;
4169
- target.style.transform = "translateY(-3px) scale(1.08)";
4170
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), 0 0 0 2px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
4171
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(40, 40, 40, 0.85) 100%)";
4295
+ target.style.boxShadow = "0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
4296
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
4172
4297
  },
4173
4298
  onMouseLeave: (e) => {
4174
4299
  const target = e.currentTarget;
4175
- target.style.transform = "translateY(0) scale(1)";
4176
- target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.7), 0 0 0 2px rgba(255, 255, 255, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
4177
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)";
4300
+ target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
4301
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
4178
4302
  },
4179
4303
  style: {
4180
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)",
4181
- color: isMuted ? "#ff6b6b" : "#ffffff",
4304
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
4305
+ color: "#ffffff",
4182
4306
  border: "none",
4183
- borderRadius: "16px",
4184
- padding: "10px",
4307
+ borderRadius: `${18 * responsiveScale}px`,
4308
+ padding: `${8 * responsiveScale}px`,
4185
4309
  cursor: "pointer",
4186
4310
  display: "flex",
4187
4311
  alignItems: "center",
4188
4312
  justifyContent: "center",
4189
4313
  backdropFilter: "blur(20px)",
4190
- boxShadow: "0 8px 32px rgba(0, 0, 0, 0.7), 0 0 0 2px rgba(255, 255, 255, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2)",
4314
+ boxShadow: "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
4191
4315
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
4192
- minWidth: "44px",
4193
- minHeight: "44px"
4316
+ minWidth: `${46 * responsiveScale}px`,
4317
+ minHeight: `${46 * responsiveScale}px`
4194
4318
  },
4195
4319
  title: isMuted ? "Unmute" : "Mute",
4196
4320
  children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4197
4321
  import_fa.FaVolumeMute,
4198
4322
  {
4199
- size: 16,
4323
+ size: Math.max(14, 16 * responsiveScale),
4200
4324
  style: {
4201
4325
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4202
4326
  color: "#ffffff"
@@ -4205,7 +4329,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4205
4329
  ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4206
4330
  import_fa.FaVolumeDown,
4207
4331
  {
4208
- size: 16,
4332
+ size: Math.max(14, 16 * responsiveScale),
4209
4333
  style: {
4210
4334
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4211
4335
  color: "#ffffff"
@@ -4214,7 +4338,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4214
4338
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4215
4339
  import_fa.FaVolumeUp,
4216
4340
  {
4217
- size: 16,
4341
+ size: Math.max(14, 16 * responsiveScale),
4218
4342
  style: {
4219
4343
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4220
4344
  color: "#ffffff"
@@ -4266,13 +4390,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4266
4390
  },
4267
4391
  onMouseEnter: (e) => {
4268
4392
  setShowVolumeSlider(true);
4269
- e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
4270
4393
  e.currentTarget.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)";
4271
4394
  e.currentTarget.style.borderColor = "rgba(96, 165, 250, 0.8)";
4272
4395
  },
4273
4396
  onMouseLeave: (e) => {
4274
4397
  setShowVolumeSlider(false);
4275
- e.currentTarget.style.transform = "translateX(-50%)";
4276
4398
  e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)";
4277
4399
  e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.7)";
4278
4400
  },
@@ -4286,12 +4408,6 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4286
4408
  cursor: "pointer",
4287
4409
  transition: "transform 0.2s ease-in-out"
4288
4410
  },
4289
- onMouseEnter: (e) => {
4290
- e.currentTarget.style.transform = "scaleX(1.2)";
4291
- },
4292
- onMouseLeave: (e) => {
4293
- e.currentTarget.style.transform = "scaleX(1)";
4294
- },
4295
4411
  onMouseDown: (e) => {
4296
4412
  e.preventDefault();
4297
4413
  const sliderElement = e.currentTarget;
@@ -4303,11 +4419,23 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4303
4419
  handleVolumeChange(percentage2);
4304
4420
  };
4305
4421
  const handleMouseUp = () => {
4306
- document.removeEventListener("mousemove", handleMouseMove);
4307
- document.removeEventListener("mouseup", handleMouseUp);
4422
+ document.removeEventListener(
4423
+ "mousemove",
4424
+ handleMouseMove
4425
+ );
4426
+ document.removeEventListener(
4427
+ "mouseup",
4428
+ handleMouseUp
4429
+ );
4308
4430
  };
4309
- document.addEventListener("mousemove", handleMouseMove);
4310
- document.addEventListener("mouseup", handleMouseUp);
4431
+ document.addEventListener(
4432
+ "mousemove",
4433
+ handleMouseMove
4434
+ );
4435
+ document.addEventListener(
4436
+ "mouseup",
4437
+ handleMouseUp
4438
+ );
4311
4439
  const rect = sliderElement.getBoundingClientRect();
4312
4440
  const y = e.clientY - rect.top;
4313
4441
  const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
@@ -4371,20 +4499,16 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4371
4499
  cursor: "grab"
4372
4500
  },
4373
4501
  onMouseEnter: (e) => {
4374
- e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
4375
4502
  e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)";
4376
4503
  e.currentTarget.style.cursor = "grab";
4377
4504
  },
4378
4505
  onMouseLeave: (e) => {
4379
- e.currentTarget.style.transform = "translateX(-50%) scale(1)";
4380
4506
  e.currentTarget.style.boxShadow = "0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)";
4381
4507
  },
4382
4508
  onMouseDown: (e) => {
4383
- e.currentTarget.style.transform = "translateX(-50%) scale(1.45)";
4384
4509
  e.currentTarget.style.cursor = "grabbing";
4385
4510
  },
4386
4511
  onMouseUp: (e) => {
4387
- e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
4388
4512
  e.currentTarget.style.cursor = "grab";
4389
4513
  }
4390
4514
  }
@@ -4412,37 +4536,35 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4412
4536
  },
4413
4537
  onMouseEnter: (e) => {
4414
4538
  const target = e.currentTarget;
4415
- target.style.transform = "translateY(-3px) scale(1.08)";
4416
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), 0 0 0 2px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
4417
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(40, 40, 40, 0.85) 100%)";
4539
+ target.style.boxShadow = "0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
4540
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
4418
4541
  },
4419
4542
  onMouseLeave: (e) => {
4420
4543
  const target = e.currentTarget;
4421
- target.style.transform = "translateY(0) scale(1)";
4422
- target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.7), 0 0 0 2px rgba(255, 255, 255, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
4423
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)";
4544
+ target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
4545
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
4424
4546
  },
4425
4547
  style: {
4426
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)",
4548
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
4427
4549
  color: "#ffffff",
4428
4550
  border: "none",
4429
- borderRadius: "16px",
4430
- padding: "10px",
4551
+ borderRadius: `${18 * responsiveScale}px`,
4552
+ padding: `${8 * responsiveScale}px`,
4431
4553
  cursor: "pointer",
4432
4554
  display: "flex",
4433
4555
  alignItems: "center",
4434
4556
  justifyContent: "center",
4435
4557
  backdropFilter: "blur(20px)",
4436
- boxShadow: "0 8px 32px rgba(0, 0, 0, 0.7), 0 0 0 2px rgba(255, 255, 255, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2)",
4558
+ boxShadow: "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
4437
4559
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
4438
- minWidth: "44px",
4439
- minHeight: "44px"
4560
+ minWidth: `${46 * responsiveScale}px`,
4561
+ minHeight: `${46 * responsiveScale}px`
4440
4562
  },
4441
4563
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
4442
4564
  children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4443
4565
  import_fa.FaCompress,
4444
4566
  {
4445
- size: 16,
4567
+ size: Math.max(14, 16 * responsiveScale),
4446
4568
  style: {
4447
4569
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4448
4570
  color: "#ffffff"
@@ -4451,7 +4573,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
4451
4573
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4452
4574
  import_fa.FaExpand,
4453
4575
  {
4454
- size: 16,
4576
+ size: Math.max(14, 16 * responsiveScale),
4455
4577
  style: {
4456
4578
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4457
4579
  color: "#ffffff"
@@ -4741,10 +4863,20 @@ var HlsPlayer = class extends import_react3.Component {
4741
4863
  }
4742
4864
  };
4743
4865
  this.play = () => {
4744
- var _a, _b;
4866
+ var _a, _b, _c;
4745
4867
  if (this.props.videoElement) {
4746
- this.props.videoElement.play();
4747
- (_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
4868
+ const video = this.props.videoElement;
4869
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
4870
+ if (hasValidSource) {
4871
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
4872
+ var _a2, _b2;
4873
+ console.error("[HlsPlayer] Failed to play:", error);
4874
+ (_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
4875
+ });
4876
+ (_c = (_b = this.props).onPlay) == null ? void 0 : _c.call(_b);
4877
+ } else {
4878
+ console.warn("[HlsPlayer] Cannot play: video has no valid source");
4879
+ }
4748
4880
  }
4749
4881
  };
4750
4882
  this.pause = () => {
@@ -4913,8 +5045,19 @@ var FilePlayer = class extends import_react4.Component {
4913
5045
  };
4914
5046
  };
4915
5047
  this.play = () => {
5048
+ var _a;
4916
5049
  if (this.props.videoElement) {
4917
- this.props.videoElement.play();
5050
+ const video = this.props.videoElement;
5051
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
5052
+ if (hasValidSource) {
5053
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
5054
+ var _a2, _b;
5055
+ console.error("[FilePlayer] Failed to play:", error);
5056
+ (_b = (_a2 = this.props).onError) == null ? void 0 : _b.call(_a2, error);
5057
+ });
5058
+ } else {
5059
+ console.warn("[FilePlayer] Cannot play: video has no valid source");
5060
+ }
4918
5061
  }
4919
5062
  };
4920
5063
  this.pause = () => {