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.js CHANGED
@@ -282,6 +282,14 @@ function createImaController(video, options) {
282
282
  function makeAdsRequest(google, vastTagUrl) {
283
283
  const adsRequest = new google.ima.AdsRequest();
284
284
  adsRequest.adTagUrl = vastTagUrl;
285
+ const videoWidth = video.offsetWidth || video.clientWidth || 640;
286
+ const videoHeight = video.offsetHeight || video.clientHeight || 360;
287
+ adsRequest.linearAdSlotWidth = videoWidth;
288
+ adsRequest.linearAdSlotHeight = videoHeight;
289
+ adsRequest.nonLinearAdSlotWidth = videoWidth;
290
+ adsRequest.nonLinearAdSlotHeight = videoHeight;
291
+ adsRequest.vastLoadTimeout = 5e3;
292
+ console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
285
293
  adsLoader.requestAds(adsRequest);
286
294
  }
287
295
  function destroyAdsManager() {
@@ -328,6 +336,18 @@ function createImaController(video, options) {
328
336
  },
329
337
  async requestAds(vastTagUrl) {
330
338
  console.log("[IMA] Requesting ads:", vastTagUrl);
339
+ if (!vastTagUrl || vastTagUrl.trim() === "") {
340
+ const error = new Error("VAST tag URL is empty or undefined");
341
+ console.warn("[IMA]", error.message);
342
+ return Promise.reject(error);
343
+ }
344
+ try {
345
+ new URL(vastTagUrl);
346
+ } catch (e) {
347
+ const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
348
+ console.warn("[IMA]", error.message);
349
+ return Promise.reject(error);
350
+ }
331
351
  if (adPlaying) {
332
352
  console.warn(
333
353
  "[IMA] Cannot request new ads while an ad is playing. Call stop() first."
@@ -389,6 +409,18 @@ function createImaController(video, options) {
389
409
  );
390
410
  }
391
411
  }
412
+ const videoWidth = video.offsetWidth || video.clientWidth;
413
+ const videoHeight = video.offsetHeight || video.clientHeight;
414
+ if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
415
+ const error = new Error(
416
+ `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
417
+ );
418
+ console.warn("[IMA]", error.message);
419
+ currentReject == null ? void 0 : currentReject(error);
420
+ adsLoadedReject = void 0;
421
+ adsLoadedResolve = void 0;
422
+ return Promise.reject(error);
423
+ }
392
424
  if (!adsLoader) {
393
425
  console.log("[IMA] Creating ads loader");
394
426
  const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
@@ -437,7 +469,9 @@ function createImaController(video, options) {
437
469
  emit("ad_error");
438
470
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
439
471
  if (video.paused) {
440
- console.log("[IMA] Resuming paused video after ad error");
472
+ console.log(
473
+ "[IMA] Resuming paused video after ad error"
474
+ );
441
475
  (_a = video.play()) == null ? void 0 : _a.catch(() => {
442
476
  });
443
477
  }
@@ -539,7 +573,9 @@ function createImaController(video, options) {
539
573
  }
540
574
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
541
575
  if (video.paused) {
542
- console.log("[IMA] Resuming paused video after setup error");
576
+ console.log(
577
+ "[IMA] Resuming paused video after setup error"
578
+ );
543
579
  video.play().catch(() => {
544
580
  });
545
581
  }
@@ -1734,6 +1770,8 @@ var StormcloudVideoPlayer = class {
1734
1770
  this.totalAdsInBreak = 0;
1735
1771
  this.showAds = false;
1736
1772
  this.isLiveStream = false;
1773
+ this.nativeHlsMode = false;
1774
+ this.videoSrcProtection = null;
1737
1775
  initializePolyfills();
1738
1776
  const browserOverrides = getBrowserConfigOverrides();
1739
1777
  this.config = { ...config, ...browserOverrides };
@@ -1754,7 +1792,9 @@ var StormcloudVideoPlayer = class {
1754
1792
  }
1755
1793
  if (adPlayerType === "hls") {
1756
1794
  if (this.config.debugAdTiming) {
1757
- console.log("[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)");
1795
+ console.log(
1796
+ "[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)"
1797
+ );
1758
1798
  }
1759
1799
  return createHlsAdPlayer(this.video, {
1760
1800
  continueLiveStreamDuringAds,
@@ -1763,7 +1803,9 @@ var StormcloudVideoPlayer = class {
1763
1803
  });
1764
1804
  } else {
1765
1805
  if (this.config.debugAdTiming) {
1766
- console.log("[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)");
1806
+ console.log(
1807
+ "[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)"
1808
+ );
1767
1809
  }
1768
1810
  return createImaController(this.video, {
1769
1811
  continueLiveStreamDuringAds
@@ -1787,11 +1829,13 @@ var StormcloudVideoPlayer = class {
1787
1829
  }
1788
1830
  this.initializeTracking();
1789
1831
  if (this.shouldUseNativeHls()) {
1832
+ this.nativeHlsMode = true;
1833
+ this.videoSrcProtection = this.config.src;
1790
1834
  this.video.src = this.config.src;
1791
1835
  this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1792
1836
  if (this.config.debugAdTiming) {
1793
1837
  console.log(
1794
- "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
1838
+ "[StormcloudVideoPlayer] Using native HLS playback - VOD mode:",
1795
1839
  {
1796
1840
  isLive: this.isLiveStream,
1797
1841
  allowNativeHls: this.config.allowNativeHls,
@@ -1939,7 +1983,9 @@ var StormcloudVideoPlayer = class {
1939
1983
  this.ima.initialize();
1940
1984
  this.ima.on("all_ads_completed", () => {
1941
1985
  if (this.config.debugAdTiming) {
1942
- console.log("[StormcloudVideoPlayer] IMA all_ads_completed event received");
1986
+ console.log(
1987
+ "[StormcloudVideoPlayer] IMA all_ads_completed event received"
1988
+ );
1943
1989
  }
1944
1990
  });
1945
1991
  this.ima.on("ad_error", () => {
@@ -2004,13 +2050,31 @@ var StormcloudVideoPlayer = class {
2004
2050
  this.video.addEventListener("timeupdate", () => {
2005
2051
  this.onTimeUpdate(this.video.currentTime);
2006
2052
  });
2053
+ this.video.addEventListener("emptied", () => {
2054
+ if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
2055
+ if (this.config.debugAdTiming) {
2056
+ console.log(
2057
+ "[StormcloudVideoPlayer] Video src was cleared, restoring:",
2058
+ this.videoSrcProtection
2059
+ );
2060
+ }
2061
+ const currentTime = this.video.currentTime;
2062
+ const wasPaused = this.video.paused;
2063
+ this.video.src = this.videoSrcProtection;
2064
+ this.video.currentTime = currentTime;
2065
+ if (!wasPaused) {
2066
+ this.video.play().catch(() => {
2067
+ });
2068
+ }
2069
+ }
2070
+ });
2007
2071
  }
2008
2072
  shouldUseNativeHls() {
2009
2073
  const streamType = this.getStreamType();
2010
2074
  if (streamType === "other") {
2011
2075
  return true;
2012
2076
  }
2013
- const canNative = this.video.canPlayType("application/vnd.apple.mpegURL");
2077
+ const canNative = this.video.canPlayType("application/vnd.apple.mpegurl");
2014
2078
  return !!(this.config.allowNativeHls && canNative);
2015
2079
  }
2016
2080
  onId3Tag(tag) {
@@ -2437,10 +2501,7 @@ var StormcloudVideoPlayer = class {
2437
2501
  var _a, _b, _c;
2438
2502
  const vastMode = this.config.vastMode || "default";
2439
2503
  if (this.config.debugAdTiming) {
2440
- console.log(
2441
- "[StormcloudVideoPlayer] VAST mode:",
2442
- vastMode
2443
- );
2504
+ console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
2444
2505
  }
2445
2506
  if (vastMode === "adstorm") {
2446
2507
  if (!this.config.licenseKey) {
@@ -2558,10 +2619,7 @@ var StormcloudVideoPlayer = class {
2558
2619
  this.currentAdIndex = 0;
2559
2620
  this.totalAdsInBreak = 1;
2560
2621
  if (this.config.debugAdTiming) {
2561
- console.log(
2562
- "[StormcloudVideoPlayer] Using VAST endpoint:",
2563
- vastTagUrl
2564
- );
2622
+ console.log("[StormcloudVideoPlayer] Using VAST endpoint:", vastTagUrl);
2565
2623
  }
2566
2624
  } else if (tags && tags.length > 0) {
2567
2625
  vastTagUrl = tags[0];
@@ -2713,15 +2771,21 @@ var StormcloudVideoPlayer = class {
2713
2771
  await this.ima.requestAds(vastTagUrl);
2714
2772
  try {
2715
2773
  if (this.config.debugAdTiming) {
2716
- console.log("[StormcloudVideoPlayer] Ad request completed, attempting playback");
2774
+ console.log(
2775
+ "[StormcloudVideoPlayer] Ad request completed, attempting playback"
2776
+ );
2717
2777
  }
2718
2778
  await this.ima.play();
2719
2779
  if (this.config.debugAdTiming) {
2720
- console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2780
+ console.log(
2781
+ "[StormcloudVideoPlayer] Ad playback started successfully"
2782
+ );
2721
2783
  }
2722
2784
  } catch (playError) {
2723
2785
  if (this.config.debugAdTiming) {
2724
- console.log("[StormcloudVideoPlayer] No ads available, skipping playback");
2786
+ console.log(
2787
+ "[StormcloudVideoPlayer] No ads available, skipping playback"
2788
+ );
2725
2789
  }
2726
2790
  this.handleAdFailure();
2727
2791
  return;
@@ -2777,7 +2841,9 @@ var StormcloudVideoPlayer = class {
2777
2841
  });
2778
2842
  } else {
2779
2843
  if (this.config.debugAdTiming) {
2780
- console.log("[StormcloudVideoPlayer] Video is already playing, no resume needed");
2844
+ console.log(
2845
+ "[StormcloudVideoPlayer] Video is already playing, no resume needed"
2846
+ );
2781
2847
  }
2782
2848
  }
2783
2849
  }
@@ -2796,7 +2862,11 @@ var StormcloudVideoPlayer = class {
2796
2862
  if (this.config.debugAdTiming) {
2797
2863
  console.warn(
2798
2864
  "[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
2799
- { paused: this.video.paused, showAds: this.showAds, adPlaying: this.ima.isAdPlaying() }
2865
+ {
2866
+ paused: this.video.paused,
2867
+ showAds: this.showAds,
2868
+ adPlaying: this.ima.isAdPlaying()
2869
+ }
2800
2870
  );
2801
2871
  }
2802
2872
  this.handleAdFailure();
@@ -3001,6 +3071,19 @@ var StormcloudVideoPlayerComponent = React.memo(
3001
3071
  const [isBuffering, setIsBuffering] = React.useState(false);
3002
3072
  const [showCenterPlay, setShowCenterPlay] = React.useState(false);
3003
3073
  const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);
3074
+ const [viewportWidth, setViewportWidth] = React.useState(
3075
+ typeof window !== "undefined" ? window.innerWidth : 1920
3076
+ );
3077
+ const [isPortrait, setIsPortrait] = React.useState(
3078
+ typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false
3079
+ );
3080
+ const getResponsiveScale = () => {
3081
+ if (viewportWidth < 480) return 0.7;
3082
+ if (viewportWidth < 768) return 0.8;
3083
+ if (viewportWidth < 1024) return 0.9;
3084
+ return 1;
3085
+ };
3086
+ const responsiveScale = getResponsiveScale();
3004
3087
  const formatTime = (seconds) => {
3005
3088
  if (!isFinite(seconds)) return "0:00:00";
3006
3089
  const hours = Math.floor(seconds / 3600);
@@ -3009,10 +3092,20 @@ var StormcloudVideoPlayerComponent = React.memo(
3009
3092
  return `${hours}:${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
3010
3093
  };
3011
3094
  const handlePlayPause = () => {
3095
+ var _a;
3012
3096
  if (videoRef.current) {
3013
3097
  if (videoRef.current.paused) {
3014
- videoRef.current.play();
3015
- setShowCenterPlay(false);
3098
+ const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== "" || videoRef.current.readyState >= 1;
3099
+ if (hasValidSource) {
3100
+ (_a = videoRef.current.play()) == null ? void 0 : _a.catch((error) => {
3101
+ console.error("[StormcloudVideoPlayer] Failed to play:", error);
3102
+ });
3103
+ setShowCenterPlay(false);
3104
+ } else {
3105
+ console.warn(
3106
+ "[StormcloudVideoPlayer] Cannot play: video has no valid source"
3107
+ );
3108
+ }
3016
3109
  } else {
3017
3110
  videoRef.current.pause();
3018
3111
  setShowCenterPlay(true);
@@ -3020,9 +3113,19 @@ var StormcloudVideoPlayerComponent = React.memo(
3020
3113
  }
3021
3114
  };
3022
3115
  const handleCenterPlayClick = () => {
3116
+ var _a;
3023
3117
  if (videoRef.current && videoRef.current.paused) {
3024
- videoRef.current.play();
3025
- setShowCenterPlay(false);
3118
+ const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== "" || videoRef.current.readyState >= 1;
3119
+ if (hasValidSource) {
3120
+ (_a = videoRef.current.play()) == null ? void 0 : _a.catch((error) => {
3121
+ console.error("[StormcloudVideoPlayer] Failed to play:", error);
3122
+ });
3123
+ setShowCenterPlay(false);
3124
+ } else {
3125
+ console.warn(
3126
+ "[StormcloudVideoPlayer] Cannot play: video has no valid source"
3127
+ );
3128
+ }
3026
3129
  }
3027
3130
  };
3028
3131
  const handleTimelineSeek = (e) => {
@@ -3053,7 +3156,14 @@ var StormcloudVideoPlayerComponent = React.memo(
3053
3156
  const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);
3054
3157
  const criticalPropsKey = useMemo(() => {
3055
3158
  return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
3056
- }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs, vastMode]);
3159
+ }, [
3160
+ src,
3161
+ allowNativeHls,
3162
+ licenseKey,
3163
+ lowLatencyMode,
3164
+ driftToleranceMs,
3165
+ vastMode
3166
+ ]);
3057
3167
  useEffect(() => {
3058
3168
  if (typeof window === "undefined") return;
3059
3169
  const el = videoRef.current;
@@ -3157,6 +3267,8 @@ var StormcloudVideoPlayerComponent = React.memo(
3157
3267
  playerRef.current.resize();
3158
3268
  }
3159
3269
  }
3270
+ setViewportWidth(window.innerWidth);
3271
+ setIsPortrait(window.innerHeight > window.innerWidth);
3160
3272
  };
3161
3273
  window.addEventListener("resize", handleResize);
3162
3274
  return () => window.removeEventListener("resize", handleResize);
@@ -3473,14 +3585,14 @@ var StormcloudVideoPlayerComponent = React.memo(
3473
3585
  },
3474
3586
  onMouseEnter: (e) => {
3475
3587
  const target = e.currentTarget;
3476
- target.style.transform = "translate(-50%, -50%) scale(1.1)";
3588
+ target.style.transform = "translate(-50%, -50%)";
3477
3589
  target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)";
3478
3590
  target.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
3479
3591
  target.style.borderColor = "rgba(255, 255, 255, 0.9)";
3480
3592
  },
3481
3593
  onMouseLeave: (e) => {
3482
3594
  const target = e.currentTarget;
3483
- target.style.transform = "translate(-50%, -50%) scale(1)";
3595
+ target.style.transform = "translate(-50%, -50%)";
3484
3596
  target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)";
3485
3597
  target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
3486
3598
  target.style.borderColor = "rgba(255, 255, 255, 0.8)";
@@ -3570,7 +3682,9 @@ var StormcloudVideoPlayerComponent = React.memo(
3570
3682
  display: "flex",
3571
3683
  alignItems: "center",
3572
3684
  justifyContent: "space-between",
3573
- color: "white"
3685
+ color: "white",
3686
+ flexWrap: viewportWidth < 768 ? "wrap" : "nowrap",
3687
+ gap: `${8 * responsiveScale}px`
3574
3688
  },
3575
3689
  children: [
3576
3690
  /* @__PURE__ */ jsxs(
@@ -3579,7 +3693,8 @@ var StormcloudVideoPlayerComponent = React.memo(
3579
3693
  style: {
3580
3694
  display: "flex",
3581
3695
  alignItems: "center",
3582
- gap: "12px"
3696
+ gap: `${12 * responsiveScale}px`,
3697
+ flexWrap: viewportWidth < 480 ? "wrap" : "nowrap"
3583
3698
  },
3584
3699
  children: [
3585
3700
  /* @__PURE__ */ jsx(
@@ -3587,44 +3702,42 @@ var StormcloudVideoPlayerComponent = React.memo(
3587
3702
  {
3588
3703
  onClick: handlePlayPause,
3589
3704
  style: {
3590
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)",
3591
- backdropFilter: "blur(10px)",
3592
- border: "1px solid rgba(255, 255, 255, 0.2)",
3705
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
3706
+ backdropFilter: "blur(12px)",
3707
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3593
3708
  color: "#ffffff",
3594
3709
  cursor: "pointer",
3595
- padding: "12px",
3596
- borderRadius: "12px",
3710
+ padding: `${10 * responsiveScale}px`,
3711
+ borderRadius: `${16 * responsiveScale}px`,
3597
3712
  display: "flex",
3598
3713
  alignItems: "center",
3599
3714
  justifyContent: "center",
3600
3715
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3601
- boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2)",
3602
- minWidth: "48px",
3603
- minHeight: "48px"
3716
+ 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)",
3717
+ minWidth: `${48 * responsiveScale}px`,
3718
+ minHeight: `${48 * responsiveScale}px`
3604
3719
  },
3605
3720
  onMouseEnter: (e) => {
3606
3721
  const target = e.target;
3607
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.1) 100%)";
3608
- target.style.transform = "translateY(-2px) scale(1.05)";
3609
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
3722
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
3723
+ 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)";
3610
3724
  },
3611
3725
  onMouseLeave: (e) => {
3612
3726
  const target = e.target;
3613
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
3614
- target.style.transform = "translateY(0) scale(1)";
3615
- target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
3727
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
3728
+ 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)";
3616
3729
  },
3617
3730
  title: isPlaying ? "Pause" : "Play",
3618
3731
  children: isPlaying ? /* @__PURE__ */ jsx(
3619
3732
  FaPause,
3620
3733
  {
3621
- size: 20,
3734
+ size: Math.max(16, 20 * responsiveScale),
3622
3735
  style: { filter: "drop-shadow(0 0 0 transparent)" }
3623
3736
  }
3624
3737
  ) : /* @__PURE__ */ jsx(
3625
3738
  FaPlay,
3626
3739
  {
3627
- size: 20,
3740
+ size: Math.max(16, 20 * responsiveScale),
3628
3741
  style: { filter: "drop-shadow(0 0 0 transparent)" }
3629
3742
  }
3630
3743
  )
@@ -3647,45 +3760,44 @@ var StormcloudVideoPlayerComponent = React.memo(
3647
3760
  "button",
3648
3761
  {
3649
3762
  onClick: () => {
3763
+ if (playerRef.current) {
3764
+ playerRef.current.toggleMute();
3765
+ }
3650
3766
  if (onVolumeToggle) {
3651
3767
  onVolumeToggle();
3652
- } else if (playerRef.current) {
3653
- playerRef.current.toggleMute();
3654
3768
  }
3655
3769
  },
3656
3770
  style: {
3657
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)",
3658
- backdropFilter: "blur(8px)",
3659
- border: "1px solid rgba(255, 255, 255, 0.15)",
3660
- color: isMuted ? "#ff6b6b" : "#ffffff",
3771
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
3772
+ backdropFilter: "blur(10px)",
3773
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3774
+ color: "#ffffff",
3661
3775
  cursor: "pointer",
3662
- padding: "10px",
3663
- borderRadius: "10px",
3776
+ padding: `${8 * responsiveScale}px`,
3777
+ borderRadius: `${16 * responsiveScale}px`,
3664
3778
  display: "flex",
3665
3779
  alignItems: "center",
3666
3780
  justifyContent: "center",
3667
3781
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3668
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
3669
- minWidth: "40px",
3670
- minHeight: "40px"
3782
+ 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)",
3783
+ minWidth: `${44 * responsiveScale}px`,
3784
+ minHeight: `${44 * responsiveScale}px`
3671
3785
  },
3672
3786
  onMouseEnter: (e) => {
3673
3787
  const target = e.target;
3674
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.08) 100%)";
3675
- target.style.transform = "translateY(-1px) scale(1.03)";
3676
- target.style.boxShadow = "0 8px 28px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
3788
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
3789
+ 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)";
3677
3790
  },
3678
3791
  onMouseLeave: (e) => {
3679
3792
  const target = e.target;
3680
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)";
3681
- target.style.transform = "translateY(0) scale(1)";
3682
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
3793
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
3794
+ 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)";
3683
3795
  },
3684
3796
  title: isMuted ? "Unmute" : "Mute",
3685
3797
  children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(
3686
3798
  FaVolumeMute,
3687
3799
  {
3688
- size: 16,
3800
+ size: Math.max(14, 16 * responsiveScale),
3689
3801
  style: {
3690
3802
  filter: "drop-shadow(0 0 0 transparent)"
3691
3803
  }
@@ -3693,7 +3805,7 @@ var StormcloudVideoPlayerComponent = React.memo(
3693
3805
  ) : volume < 0.5 ? /* @__PURE__ */ jsx(
3694
3806
  FaVolumeDown,
3695
3807
  {
3696
- size: 16,
3808
+ size: Math.max(14, 16 * responsiveScale),
3697
3809
  style: {
3698
3810
  filter: "drop-shadow(0 0 0 transparent)"
3699
3811
  }
@@ -3701,7 +3813,7 @@ var StormcloudVideoPlayerComponent = React.memo(
3701
3813
  ) : /* @__PURE__ */ jsx(
3702
3814
  FaVolumeUp,
3703
3815
  {
3704
- size: 16,
3816
+ size: Math.max(14, 16 * responsiveScale),
3705
3817
  style: {
3706
3818
  filter: "drop-shadow(0 0 0 transparent)"
3707
3819
  }
@@ -3752,13 +3864,11 @@ var StormcloudVideoPlayerComponent = React.memo(
3752
3864
  },
3753
3865
  onMouseEnter: (e) => {
3754
3866
  setShowVolumeSlider(true);
3755
- e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
3756
3867
  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)";
3757
3868
  e.currentTarget.style.borderColor = "rgba(59, 130, 246, 0.4)";
3758
3869
  },
3759
3870
  onMouseLeave: (e) => {
3760
3871
  setShowVolumeSlider(false);
3761
- e.currentTarget.style.transform = "translateX(-50%)";
3762
3872
  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)";
3763
3873
  e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.15)";
3764
3874
  },
@@ -3773,10 +3883,8 @@ var StormcloudVideoPlayerComponent = React.memo(
3773
3883
  transition: "transform 0.2s ease-in-out"
3774
3884
  },
3775
3885
  onMouseEnter: (e) => {
3776
- e.currentTarget.style.transform = "scaleX(1.2)";
3777
3886
  },
3778
3887
  onMouseLeave: (e) => {
3779
- e.currentTarget.style.transform = "scaleX(1)";
3780
3888
  },
3781
3889
  onMouseDown: (e) => {
3782
3890
  e.preventDefault();
@@ -3789,11 +3897,23 @@ var StormcloudVideoPlayerComponent = React.memo(
3789
3897
  handleVolumeChange(percentage2);
3790
3898
  };
3791
3899
  const handleMouseUp = () => {
3792
- document.removeEventListener("mousemove", handleMouseMove);
3793
- document.removeEventListener("mouseup", handleMouseUp);
3900
+ document.removeEventListener(
3901
+ "mousemove",
3902
+ handleMouseMove
3903
+ );
3904
+ document.removeEventListener(
3905
+ "mouseup",
3906
+ handleMouseUp
3907
+ );
3794
3908
  };
3795
- document.addEventListener("mousemove", handleMouseMove);
3796
- document.addEventListener("mouseup", handleMouseUp);
3909
+ document.addEventListener(
3910
+ "mousemove",
3911
+ handleMouseMove
3912
+ );
3913
+ document.addEventListener(
3914
+ "mouseup",
3915
+ handleMouseUp
3916
+ );
3797
3917
  const rect = sliderElement.getBoundingClientRect();
3798
3918
  const y = e.clientY - rect.top;
3799
3919
  const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
@@ -3855,20 +3975,16 @@ var StormcloudVideoPlayerComponent = React.memo(
3855
3975
  cursor: "grab"
3856
3976
  },
3857
3977
  onMouseEnter: (e) => {
3858
- e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
3859
3978
  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)";
3860
3979
  e.currentTarget.style.cursor = "grab";
3861
3980
  },
3862
3981
  onMouseLeave: (e) => {
3863
- e.currentTarget.style.transform = "translateX(-50%) scale(1)";
3864
3982
  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)";
3865
3983
  },
3866
3984
  onMouseDown: (e) => {
3867
- e.currentTarget.style.transform = "translateX(-50%) scale(1.4)";
3868
3985
  e.currentTarget.style.cursor = "grabbing";
3869
3986
  },
3870
3987
  onMouseUp: (e) => {
3871
- e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
3872
3988
  e.currentTarget.style.cursor = "grab";
3873
3989
  }
3874
3990
  }
@@ -3886,9 +4002,10 @@ var StormcloudVideoPlayerComponent = React.memo(
3886
4002
  "div",
3887
4003
  {
3888
4004
  style: {
3889
- fontSize: "14px",
4005
+ fontSize: `${14 * responsiveScale}px`,
3890
4006
  fontFamily: "monospace",
3891
- color: "rgba(255, 255, 255, 0.9)"
4007
+ color: "rgba(255, 255, 255, 0.9)",
4008
+ display: viewportWidth < 480 ? "none" : "block"
3892
4009
  },
3893
4010
  children: [
3894
4011
  formatTime(currentTime),
@@ -3906,105 +4023,113 @@ var StormcloudVideoPlayerComponent = React.memo(
3906
4023
  style: {
3907
4024
  display: "flex",
3908
4025
  alignItems: "center",
3909
- gap: "12px"
4026
+ gap: `${12 * responsiveScale}px`
3910
4027
  },
3911
4028
  children: [
3912
- /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
3913
- /* @__PURE__ */ jsxs(
3914
- "button",
3915
- {
3916
- onClick: () => setShowSpeedMenu(!showSpeedMenu),
3917
- style: {
3918
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 100%)",
3919
- backdropFilter: "blur(8px)",
3920
- border: "1px solid rgba(255, 255, 255, 0.12)",
3921
- color: "#ffffff",
3922
- cursor: "pointer",
3923
- padding: "8px 14px",
3924
- borderRadius: "8px",
3925
- fontSize: "13px",
3926
- fontFamily: "monospace",
3927
- fontWeight: "600",
3928
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3929
- boxShadow: "0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08)",
3930
- minWidth: "50px"
3931
- },
3932
- onMouseEnter: (e) => {
3933
- const target = e.target;
3934
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0.06) 100%)";
3935
- target.style.transform = "translateY(-1px) scale(1.02)";
3936
- target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)";
3937
- },
3938
- onMouseLeave: (e) => {
3939
- const target = e.target;
3940
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 100%)";
3941
- target.style.transform = "translateY(0) scale(1)";
3942
- target.style.boxShadow = "0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08)";
3943
- },
3944
- title: "Playback Speed",
3945
- children: [
3946
- playbackRate,
3947
- "x"
3948
- ]
3949
- }
3950
- ),
3951
- showSpeedMenu && /* @__PURE__ */ jsx(
3952
- "div",
3953
- {
3954
- style: {
3955
- position: "absolute",
3956
- bottom: "100%",
3957
- right: 0,
3958
- marginBottom: "12px",
3959
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
3960
- backdropFilter: "blur(20px)",
3961
- borderRadius: "12px",
3962
- border: "1px solid rgba(255, 255, 255, 0.1)",
3963
- overflow: "hidden",
3964
- minWidth: "90px",
3965
- boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
3966
- },
3967
- children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
3968
- (speed) => /* @__PURE__ */ jsxs(
3969
- "button",
3970
- {
3971
- onClick: () => handlePlaybackRateChange(speed),
3972
- style: {
3973
- display: "block",
3974
- width: "100%",
3975
- padding: "10px 16px",
3976
- background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
3977
- border: "none",
3978
- color: "white",
3979
- cursor: "pointer",
3980
- fontSize: "13px",
3981
- fontFamily: "monospace",
3982
- fontWeight: "600",
3983
- textAlign: "center",
3984
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
3985
- borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
3986
- },
3987
- onMouseEnter: (e) => {
3988
- if (playbackRate !== speed) {
3989
- e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
3990
- }
3991
- },
3992
- onMouseLeave: (e) => {
3993
- if (playbackRate !== speed) {
3994
- e.target.style.background = "transparent";
3995
- }
3996
- },
3997
- children: [
3998
- speed,
3999
- "x"
4000
- ]
4029
+ /* @__PURE__ */ jsxs(
4030
+ "div",
4031
+ {
4032
+ style: {
4033
+ position: "relative",
4034
+ display: viewportWidth < 600 ? "none" : "block"
4035
+ },
4036
+ children: [
4037
+ /* @__PURE__ */ jsxs(
4038
+ "button",
4039
+ {
4040
+ onClick: () => setShowSpeedMenu(!showSpeedMenu),
4041
+ style: {
4042
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
4043
+ backdropFilter: "blur(10px)",
4044
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
4045
+ color: "#ffffff",
4046
+ cursor: "pointer",
4047
+ padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,
4048
+ borderRadius: `${14 * responsiveScale}px`,
4049
+ fontSize: `${14 * responsiveScale}px`,
4050
+ fontFamily: "monospace",
4051
+ fontWeight: "700",
4052
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
4053
+ 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)",
4054
+ minWidth: `${56 * responsiveScale}px`,
4055
+ minHeight: `${40 * responsiveScale}px`
4001
4056
  },
4002
- speed
4003
- )
4057
+ onMouseEnter: (e) => {
4058
+ const target = e.target;
4059
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
4060
+ 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)";
4061
+ },
4062
+ onMouseLeave: (e) => {
4063
+ const target = e.target;
4064
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
4065
+ 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)";
4066
+ },
4067
+ title: "Playback Speed",
4068
+ children: [
4069
+ playbackRate,
4070
+ "x"
4071
+ ]
4072
+ }
4073
+ ),
4074
+ showSpeedMenu && /* @__PURE__ */ jsx(
4075
+ "div",
4076
+ {
4077
+ style: {
4078
+ position: "absolute",
4079
+ bottom: "100%",
4080
+ right: 0,
4081
+ marginBottom: "12px",
4082
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
4083
+ backdropFilter: "blur(20px)",
4084
+ borderRadius: "12px",
4085
+ border: "1px solid rgba(255, 255, 255, 0.1)",
4086
+ overflow: "hidden",
4087
+ minWidth: "90px",
4088
+ boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
4089
+ },
4090
+ children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
4091
+ (speed) => /* @__PURE__ */ jsxs(
4092
+ "button",
4093
+ {
4094
+ onClick: () => handlePlaybackRateChange(speed),
4095
+ style: {
4096
+ display: "block",
4097
+ width: "100%",
4098
+ padding: "10px 16px",
4099
+ background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
4100
+ border: "none",
4101
+ color: "white",
4102
+ cursor: "pointer",
4103
+ fontSize: "13px",
4104
+ fontFamily: "monospace",
4105
+ fontWeight: "600",
4106
+ textAlign: "center",
4107
+ transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
4108
+ borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
4109
+ },
4110
+ onMouseEnter: (e) => {
4111
+ if (playbackRate !== speed) {
4112
+ e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
4113
+ }
4114
+ },
4115
+ onMouseLeave: (e) => {
4116
+ if (playbackRate !== speed) {
4117
+ e.target.style.background = "transparent";
4118
+ }
4119
+ },
4120
+ children: [
4121
+ speed,
4122
+ "x"
4123
+ ]
4124
+ },
4125
+ speed
4126
+ )
4127
+ )
4128
+ }
4004
4129
  )
4005
- }
4006
- )
4007
- ] }),
4130
+ ]
4131
+ }
4132
+ ),
4008
4133
  /* @__PURE__ */ jsx(
4009
4134
  "button",
4010
4135
  {
@@ -4018,44 +4143,42 @@ var StormcloudVideoPlayerComponent = React.memo(
4018
4143
  }
4019
4144
  },
4020
4145
  style: {
4021
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)",
4022
- backdropFilter: "blur(8px)",
4023
- border: "1px solid rgba(255, 255, 255, 0.15)",
4146
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
4147
+ backdropFilter: "blur(10px)",
4148
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
4024
4149
  color: "#ffffff",
4025
4150
  cursor: "pointer",
4026
- padding: "10px",
4027
- borderRadius: "10px",
4151
+ padding: `${8 * responsiveScale}px`,
4152
+ borderRadius: `${16 * responsiveScale}px`,
4028
4153
  display: "flex",
4029
4154
  alignItems: "center",
4030
4155
  justifyContent: "center",
4031
4156
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
4032
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
4033
- minWidth: "40px",
4034
- minHeight: "40px"
4157
+ 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)",
4158
+ minWidth: `${44 * responsiveScale}px`,
4159
+ minHeight: `${44 * responsiveScale}px`
4035
4160
  },
4036
4161
  onMouseEnter: (e) => {
4037
4162
  const target = e.target;
4038
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.08) 100%)";
4039
- target.style.transform = "translateY(-1px) scale(1.03)";
4040
- target.style.boxShadow = "0 8px 28px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
4163
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
4164
+ 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)";
4041
4165
  },
4042
4166
  onMouseLeave: (e) => {
4043
4167
  const target = e.target;
4044
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)";
4045
- target.style.transform = "translateY(0) scale(1)";
4046
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
4168
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
4169
+ 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)";
4047
4170
  },
4048
4171
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
4049
4172
  children: isFullscreen ? /* @__PURE__ */ jsx(
4050
4173
  FaCompress,
4051
4174
  {
4052
- size: 16,
4175
+ size: Math.max(14, 16 * responsiveScale),
4053
4176
  style: { filter: "drop-shadow(0 0 0 transparent)" }
4054
4177
  }
4055
4178
  ) : /* @__PURE__ */ jsx(
4056
4179
  FaExpand,
4057
4180
  {
4058
- size: 16,
4181
+ size: Math.max(14, 16 * responsiveScale),
4059
4182
  style: { filter: "drop-shadow(0 0 0 transparent)" }
4060
4183
  }
4061
4184
  )
@@ -4074,10 +4197,12 @@ var StormcloudVideoPlayerComponent = React.memo(
4074
4197
  {
4075
4198
  style: {
4076
4199
  position: "absolute",
4077
- bottom: "10px",
4078
- right: "10px",
4200
+ bottom: `${10 * responsiveScale}px`,
4201
+ right: `${10 * responsiveScale}px`,
4202
+ transform: "none",
4079
4203
  display: "flex",
4080
- gap: "8px",
4204
+ flexDirection: isPortrait ? "column" : "row",
4205
+ gap: `${10 * responsiveScale}px`,
4081
4206
  zIndex: 10
4082
4207
  },
4083
4208
  children: [
@@ -4098,45 +4223,44 @@ var StormcloudVideoPlayerComponent = React.memo(
4098
4223
  "button",
4099
4224
  {
4100
4225
  onClick: () => {
4226
+ if (playerRef.current) {
4227
+ playerRef.current.toggleMute();
4228
+ }
4101
4229
  if (onVolumeToggle) {
4102
4230
  onVolumeToggle();
4103
- } else if (playerRef.current) {
4104
- playerRef.current.toggleMute();
4105
4231
  }
4106
4232
  },
4107
4233
  onMouseEnter: (e) => {
4108
4234
  const target = e.currentTarget;
4109
- target.style.transform = "translateY(-3px) scale(1.08)";
4110
- 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)";
4111
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(40, 40, 40, 0.85) 100%)";
4235
+ 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)";
4236
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
4112
4237
  },
4113
4238
  onMouseLeave: (e) => {
4114
4239
  const target = e.currentTarget;
4115
- target.style.transform = "translateY(0) scale(1)";
4116
- 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)";
4117
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)";
4240
+ 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)";
4241
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
4118
4242
  },
4119
4243
  style: {
4120
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)",
4121
- color: isMuted ? "#ff6b6b" : "#ffffff",
4244
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
4245
+ color: "#ffffff",
4122
4246
  border: "none",
4123
- borderRadius: "16px",
4124
- padding: "10px",
4247
+ borderRadius: `${18 * responsiveScale}px`,
4248
+ padding: `${8 * responsiveScale}px`,
4125
4249
  cursor: "pointer",
4126
4250
  display: "flex",
4127
4251
  alignItems: "center",
4128
4252
  justifyContent: "center",
4129
4253
  backdropFilter: "blur(20px)",
4130
- 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)",
4254
+ 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)",
4131
4255
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
4132
- minWidth: "44px",
4133
- minHeight: "44px"
4256
+ minWidth: `${46 * responsiveScale}px`,
4257
+ minHeight: `${46 * responsiveScale}px`
4134
4258
  },
4135
4259
  title: isMuted ? "Unmute" : "Mute",
4136
4260
  children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(
4137
4261
  FaVolumeMute,
4138
4262
  {
4139
- size: 16,
4263
+ size: Math.max(14, 16 * responsiveScale),
4140
4264
  style: {
4141
4265
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4142
4266
  color: "#ffffff"
@@ -4145,7 +4269,7 @@ var StormcloudVideoPlayerComponent = React.memo(
4145
4269
  ) : volume < 0.5 ? /* @__PURE__ */ jsx(
4146
4270
  FaVolumeDown,
4147
4271
  {
4148
- size: 16,
4272
+ size: Math.max(14, 16 * responsiveScale),
4149
4273
  style: {
4150
4274
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4151
4275
  color: "#ffffff"
@@ -4154,7 +4278,7 @@ var StormcloudVideoPlayerComponent = React.memo(
4154
4278
  ) : /* @__PURE__ */ jsx(
4155
4279
  FaVolumeUp,
4156
4280
  {
4157
- size: 16,
4281
+ size: Math.max(14, 16 * responsiveScale),
4158
4282
  style: {
4159
4283
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4160
4284
  color: "#ffffff"
@@ -4206,13 +4330,11 @@ var StormcloudVideoPlayerComponent = React.memo(
4206
4330
  },
4207
4331
  onMouseEnter: (e) => {
4208
4332
  setShowVolumeSlider(true);
4209
- e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
4210
4333
  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)";
4211
4334
  e.currentTarget.style.borderColor = "rgba(96, 165, 250, 0.8)";
4212
4335
  },
4213
4336
  onMouseLeave: (e) => {
4214
4337
  setShowVolumeSlider(false);
4215
- e.currentTarget.style.transform = "translateX(-50%)";
4216
4338
  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)";
4217
4339
  e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.7)";
4218
4340
  },
@@ -4226,12 +4348,6 @@ var StormcloudVideoPlayerComponent = React.memo(
4226
4348
  cursor: "pointer",
4227
4349
  transition: "transform 0.2s ease-in-out"
4228
4350
  },
4229
- onMouseEnter: (e) => {
4230
- e.currentTarget.style.transform = "scaleX(1.2)";
4231
- },
4232
- onMouseLeave: (e) => {
4233
- e.currentTarget.style.transform = "scaleX(1)";
4234
- },
4235
4351
  onMouseDown: (e) => {
4236
4352
  e.preventDefault();
4237
4353
  const sliderElement = e.currentTarget;
@@ -4243,11 +4359,23 @@ var StormcloudVideoPlayerComponent = React.memo(
4243
4359
  handleVolumeChange(percentage2);
4244
4360
  };
4245
4361
  const handleMouseUp = () => {
4246
- document.removeEventListener("mousemove", handleMouseMove);
4247
- document.removeEventListener("mouseup", handleMouseUp);
4362
+ document.removeEventListener(
4363
+ "mousemove",
4364
+ handleMouseMove
4365
+ );
4366
+ document.removeEventListener(
4367
+ "mouseup",
4368
+ handleMouseUp
4369
+ );
4248
4370
  };
4249
- document.addEventListener("mousemove", handleMouseMove);
4250
- document.addEventListener("mouseup", handleMouseUp);
4371
+ document.addEventListener(
4372
+ "mousemove",
4373
+ handleMouseMove
4374
+ );
4375
+ document.addEventListener(
4376
+ "mouseup",
4377
+ handleMouseUp
4378
+ );
4251
4379
  const rect = sliderElement.getBoundingClientRect();
4252
4380
  const y = e.clientY - rect.top;
4253
4381
  const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
@@ -4311,20 +4439,16 @@ var StormcloudVideoPlayerComponent = React.memo(
4311
4439
  cursor: "grab"
4312
4440
  },
4313
4441
  onMouseEnter: (e) => {
4314
- e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
4315
4442
  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)";
4316
4443
  e.currentTarget.style.cursor = "grab";
4317
4444
  },
4318
4445
  onMouseLeave: (e) => {
4319
- e.currentTarget.style.transform = "translateX(-50%) scale(1)";
4320
4446
  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)";
4321
4447
  },
4322
4448
  onMouseDown: (e) => {
4323
- e.currentTarget.style.transform = "translateX(-50%) scale(1.45)";
4324
4449
  e.currentTarget.style.cursor = "grabbing";
4325
4450
  },
4326
4451
  onMouseUp: (e) => {
4327
- e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
4328
4452
  e.currentTarget.style.cursor = "grab";
4329
4453
  }
4330
4454
  }
@@ -4352,37 +4476,35 @@ var StormcloudVideoPlayerComponent = React.memo(
4352
4476
  },
4353
4477
  onMouseEnter: (e) => {
4354
4478
  const target = e.currentTarget;
4355
- target.style.transform = "translateY(-3px) scale(1.08)";
4356
- 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)";
4357
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(40, 40, 40, 0.85) 100%)";
4479
+ 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)";
4480
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
4358
4481
  },
4359
4482
  onMouseLeave: (e) => {
4360
4483
  const target = e.currentTarget;
4361
- target.style.transform = "translateY(0) scale(1)";
4362
- 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)";
4363
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)";
4484
+ 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)";
4485
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
4364
4486
  },
4365
4487
  style: {
4366
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)",
4488
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
4367
4489
  color: "#ffffff",
4368
4490
  border: "none",
4369
- borderRadius: "16px",
4370
- padding: "10px",
4491
+ borderRadius: `${18 * responsiveScale}px`,
4492
+ padding: `${8 * responsiveScale}px`,
4371
4493
  cursor: "pointer",
4372
4494
  display: "flex",
4373
4495
  alignItems: "center",
4374
4496
  justifyContent: "center",
4375
4497
  backdropFilter: "blur(20px)",
4376
- 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)",
4498
+ 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)",
4377
4499
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
4378
- minWidth: "44px",
4379
- minHeight: "44px"
4500
+ minWidth: `${46 * responsiveScale}px`,
4501
+ minHeight: `${46 * responsiveScale}px`
4380
4502
  },
4381
4503
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
4382
4504
  children: isFullscreen ? /* @__PURE__ */ jsx(
4383
4505
  FaCompress,
4384
4506
  {
4385
- size: 16,
4507
+ size: Math.max(14, 16 * responsiveScale),
4386
4508
  style: {
4387
4509
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4388
4510
  color: "#ffffff"
@@ -4391,7 +4513,7 @@ var StormcloudVideoPlayerComponent = React.memo(
4391
4513
  ) : /* @__PURE__ */ jsx(
4392
4514
  FaExpand,
4393
4515
  {
4394
- size: 16,
4516
+ size: Math.max(14, 16 * responsiveScale),
4395
4517
  style: {
4396
4518
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4397
4519
  color: "#ffffff"
@@ -4681,10 +4803,20 @@ var HlsPlayer = class extends Component {
4681
4803
  }
4682
4804
  };
4683
4805
  this.play = () => {
4684
- var _a, _b;
4806
+ var _a, _b, _c;
4685
4807
  if (this.props.videoElement) {
4686
- this.props.videoElement.play();
4687
- (_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
4808
+ const video = this.props.videoElement;
4809
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
4810
+ if (hasValidSource) {
4811
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
4812
+ var _a2, _b2;
4813
+ console.error("[HlsPlayer] Failed to play:", error);
4814
+ (_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
4815
+ });
4816
+ (_c = (_b = this.props).onPlay) == null ? void 0 : _c.call(_b);
4817
+ } else {
4818
+ console.warn("[HlsPlayer] Cannot play: video has no valid source");
4819
+ }
4688
4820
  }
4689
4821
  };
4690
4822
  this.pause = () => {
@@ -4853,8 +4985,19 @@ var FilePlayer = class extends Component2 {
4853
4985
  };
4854
4986
  };
4855
4987
  this.play = () => {
4988
+ var _a;
4856
4989
  if (this.props.videoElement) {
4857
- this.props.videoElement.play();
4990
+ const video = this.props.videoElement;
4991
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
4992
+ if (hasValidSource) {
4993
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
4994
+ var _a2, _b;
4995
+ console.error("[FilePlayer] Failed to play:", error);
4996
+ (_b = (_a2 = this.props).onError) == null ? void 0 : _b.call(_a2, error);
4997
+ });
4998
+ } else {
4999
+ console.warn("[FilePlayer] Cannot play: video has no valid source");
5000
+ }
4858
5001
  }
4859
5002
  };
4860
5003
  this.pause = () => {