stormcloud-video-player 0.2.14 → 0.2.16

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
@@ -848,7 +848,7 @@ function createHlsAdPlayer(contentVideo, options) {
848
848
  const xmlDoc = parser.parseFromString(xmlString, "text/xml");
849
849
  const parserError = xmlDoc.querySelector("parsererror");
850
850
  if (parserError) {
851
- console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
851
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
852
852
  return null;
853
853
  }
854
854
  const adElement = xmlDoc.querySelector("Ad");
@@ -858,28 +858,45 @@ function createHlsAdPlayer(contentVideo, options) {
858
858
  }
859
859
  const adId = adElement.getAttribute("id") || "unknown";
860
860
  const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
861
+ const isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
861
862
  const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
862
863
  const durationParts = durationText.split(":");
863
864
  const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
864
865
  const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
865
866
  const mediaFiles = [];
866
- mediaFileElements.forEach((mf) => {
867
+ console.log(`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`);
868
+ mediaFileElements.forEach((mf, index) => {
867
869
  var _a2;
868
870
  const type = mf.getAttribute("type") || "";
871
+ const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
872
+ const width = mf.getAttribute("width") || "";
873
+ const height = mf.getAttribute("height") || "";
874
+ console.log(`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`);
869
875
  if (type === "application/x-mpegURL" || type.includes("m3u8")) {
876
+ if (!url) {
877
+ console.warn(`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`);
878
+ return;
879
+ }
870
880
  const bitrateAttr = mf.getAttribute("bitrate");
871
881
  const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
872
882
  mediaFiles.push({
873
- url: ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "",
883
+ url,
874
884
  type,
875
- width: parseInt(mf.getAttribute("width") || "1920", 10),
876
- height: parseInt(mf.getAttribute("height") || "1080", 10),
885
+ width: parseInt(width || "1920", 10),
886
+ height: parseInt(height || "1080", 10),
877
887
  bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
878
888
  });
889
+ console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
890
+ } else {
891
+ console.log(`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`);
879
892
  }
880
893
  });
881
894
  if (mediaFiles.length === 0) {
882
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
895
+ if (isNoAdAvailable) {
896
+ console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
897
+ } else {
898
+ console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
899
+ }
883
900
  return null;
884
901
  }
885
902
  const trackingUrls = {
@@ -1067,9 +1084,11 @@ function createHlsAdPlayer(contentVideo, options) {
1067
1084
  }
1068
1085
  const vastXml = await response.text();
1069
1086
  console.log("[HlsAdPlayer] VAST XML received");
1087
+ console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1070
1088
  const ad = parseVastXml(vastXml);
1071
1089
  if (!ad) {
1072
- throw new Error("Failed to parse VAST XML or no ads available");
1090
+ console.warn("[HlsAdPlayer] No ads available from VAST response");
1091
+ return Promise.resolve();
1073
1092
  }
1074
1093
  currentAd = ad;
1075
1094
  console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
@@ -1084,7 +1103,7 @@ function createHlsAdPlayer(contentVideo, options) {
1084
1103
  },
1085
1104
  async play() {
1086
1105
  if (!currentAd) {
1087
- console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
1106
+ console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
1088
1107
  return Promise.reject(new Error("No ad loaded"));
1089
1108
  }
1090
1109
  console.log("[HlsAdPlayer] Starting ad playback");
@@ -1715,6 +1734,8 @@ var StormcloudVideoPlayer = class {
1715
1734
  this.totalAdsInBreak = 0;
1716
1735
  this.showAds = false;
1717
1736
  this.isLiveStream = false;
1737
+ this.nativeHlsMode = false;
1738
+ this.videoSrcProtection = null;
1718
1739
  initializePolyfills();
1719
1740
  const browserOverrides = getBrowserConfigOverrides();
1720
1741
  this.config = { ...config, ...browserOverrides };
@@ -1735,7 +1756,9 @@ var StormcloudVideoPlayer = class {
1735
1756
  }
1736
1757
  if (adPlayerType === "hls") {
1737
1758
  if (this.config.debugAdTiming) {
1738
- console.log("[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)");
1759
+ console.log(
1760
+ "[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)"
1761
+ );
1739
1762
  }
1740
1763
  return createHlsAdPlayer(this.video, {
1741
1764
  continueLiveStreamDuringAds,
@@ -1744,7 +1767,9 @@ var StormcloudVideoPlayer = class {
1744
1767
  });
1745
1768
  } else {
1746
1769
  if (this.config.debugAdTiming) {
1747
- console.log("[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)");
1770
+ console.log(
1771
+ "[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)"
1772
+ );
1748
1773
  }
1749
1774
  return createImaController(this.video, {
1750
1775
  continueLiveStreamDuringAds
@@ -1768,11 +1793,13 @@ var StormcloudVideoPlayer = class {
1768
1793
  }
1769
1794
  this.initializeTracking();
1770
1795
  if (this.shouldUseNativeHls()) {
1796
+ this.nativeHlsMode = true;
1797
+ this.videoSrcProtection = this.config.src;
1771
1798
  this.video.src = this.config.src;
1772
1799
  this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1773
1800
  if (this.config.debugAdTiming) {
1774
1801
  console.log(
1775
- "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
1802
+ "[StormcloudVideoPlayer] Using native HLS playback - VOD mode:",
1776
1803
  {
1777
1804
  isLive: this.isLiveStream,
1778
1805
  allowNativeHls: this.config.allowNativeHls,
@@ -1920,7 +1947,9 @@ var StormcloudVideoPlayer = class {
1920
1947
  this.ima.initialize();
1921
1948
  this.ima.on("all_ads_completed", () => {
1922
1949
  if (this.config.debugAdTiming) {
1923
- console.log("[StormcloudVideoPlayer] IMA all_ads_completed event received");
1950
+ console.log(
1951
+ "[StormcloudVideoPlayer] IMA all_ads_completed event received"
1952
+ );
1924
1953
  }
1925
1954
  });
1926
1955
  this.ima.on("ad_error", () => {
@@ -1985,13 +2014,31 @@ var StormcloudVideoPlayer = class {
1985
2014
  this.video.addEventListener("timeupdate", () => {
1986
2015
  this.onTimeUpdate(this.video.currentTime);
1987
2016
  });
2017
+ this.video.addEventListener("emptied", () => {
2018
+ if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
2019
+ if (this.config.debugAdTiming) {
2020
+ console.log(
2021
+ "[StormcloudVideoPlayer] Video src was cleared, restoring:",
2022
+ this.videoSrcProtection
2023
+ );
2024
+ }
2025
+ const currentTime = this.video.currentTime;
2026
+ const wasPaused = this.video.paused;
2027
+ this.video.src = this.videoSrcProtection;
2028
+ this.video.currentTime = currentTime;
2029
+ if (!wasPaused) {
2030
+ this.video.play().catch(() => {
2031
+ });
2032
+ }
2033
+ }
2034
+ });
1988
2035
  }
1989
2036
  shouldUseNativeHls() {
1990
2037
  const streamType = this.getStreamType();
1991
2038
  if (streamType === "other") {
1992
2039
  return true;
1993
2040
  }
1994
- const canNative = this.video.canPlayType("application/vnd.apple.mpegURL");
2041
+ const canNative = this.video.canPlayType("application/vnd.apple.mpegurl");
1995
2042
  return !!(this.config.allowNativeHls && canNative);
1996
2043
  }
1997
2044
  onId3Tag(tag) {
@@ -2418,10 +2465,7 @@ var StormcloudVideoPlayer = class {
2418
2465
  var _a, _b, _c;
2419
2466
  const vastMode = this.config.vastMode || "default";
2420
2467
  if (this.config.debugAdTiming) {
2421
- console.log(
2422
- "[StormcloudVideoPlayer] VAST mode:",
2423
- vastMode
2424
- );
2468
+ console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
2425
2469
  }
2426
2470
  if (vastMode === "adstorm") {
2427
2471
  if (!this.config.licenseKey) {
@@ -2436,7 +2480,7 @@ var StormcloudVideoPlayer = class {
2436
2480
  this.apiVastTagUrl = vastEndpoint;
2437
2481
  if (this.config.debugAdTiming) {
2438
2482
  console.log(
2439
- "[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
2483
+ "[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):",
2440
2484
  vastEndpoint
2441
2485
  );
2442
2486
  }
@@ -2539,10 +2583,7 @@ var StormcloudVideoPlayer = class {
2539
2583
  this.currentAdIndex = 0;
2540
2584
  this.totalAdsInBreak = 1;
2541
2585
  if (this.config.debugAdTiming) {
2542
- console.log(
2543
- "[StormcloudVideoPlayer] Using VAST endpoint:",
2544
- vastTagUrl
2545
- );
2586
+ console.log("[StormcloudVideoPlayer] Using VAST endpoint:", vastTagUrl);
2546
2587
  }
2547
2588
  } else if (tags && tags.length > 0) {
2548
2589
  vastTagUrl = tags[0];
@@ -2692,12 +2733,26 @@ var StormcloudVideoPlayer = class {
2692
2733
  this.startAdFailsafeTimer();
2693
2734
  try {
2694
2735
  await this.ima.requestAds(vastTagUrl);
2695
- if (this.config.debugAdTiming) {
2696
- console.log("[StormcloudVideoPlayer] Ad request successful, starting playback");
2697
- }
2698
- await this.ima.play();
2699
- if (this.config.debugAdTiming) {
2700
- console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2736
+ try {
2737
+ if (this.config.debugAdTiming) {
2738
+ console.log(
2739
+ "[StormcloudVideoPlayer] Ad request completed, attempting playback"
2740
+ );
2741
+ }
2742
+ await this.ima.play();
2743
+ if (this.config.debugAdTiming) {
2744
+ console.log(
2745
+ "[StormcloudVideoPlayer] Ad playback started successfully"
2746
+ );
2747
+ }
2748
+ } catch (playError) {
2749
+ if (this.config.debugAdTiming) {
2750
+ console.log(
2751
+ "[StormcloudVideoPlayer] No ads available, skipping playback"
2752
+ );
2753
+ }
2754
+ this.handleAdFailure();
2755
+ return;
2701
2756
  }
2702
2757
  } catch (error) {
2703
2758
  if (this.config.debugAdTiming) {
@@ -2750,7 +2805,9 @@ var StormcloudVideoPlayer = class {
2750
2805
  });
2751
2806
  } else {
2752
2807
  if (this.config.debugAdTiming) {
2753
- console.log("[StormcloudVideoPlayer] Video is already playing, no resume needed");
2808
+ console.log(
2809
+ "[StormcloudVideoPlayer] Video is already playing, no resume needed"
2810
+ );
2754
2811
  }
2755
2812
  }
2756
2813
  }
@@ -2769,7 +2826,11 @@ var StormcloudVideoPlayer = class {
2769
2826
  if (this.config.debugAdTiming) {
2770
2827
  console.warn(
2771
2828
  "[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
2772
- { paused: this.video.paused, showAds: this.showAds, adPlaying: this.ima.isAdPlaying() }
2829
+ {
2830
+ paused: this.video.paused,
2831
+ showAds: this.showAds,
2832
+ adPlaying: this.ima.isAdPlaying()
2833
+ }
2773
2834
  );
2774
2835
  }
2775
2836
  this.handleAdFailure();
@@ -2923,7 +2984,8 @@ var CRITICAL_PROPS = [
2923
2984
  "allowNativeHls",
2924
2985
  "licenseKey",
2925
2986
  "lowLatencyMode",
2926
- "driftToleranceMs"
2987
+ "driftToleranceMs",
2988
+ "vastMode"
2927
2989
  ];
2928
2990
  var StormcloudVideoPlayerComponent = React.memo(
2929
2991
  (props) => {
@@ -2951,6 +3013,9 @@ var StormcloudVideoPlayerComponent = React.memo(
2951
3013
  poster,
2952
3014
  children,
2953
3015
  licenseKey,
3016
+ vastMode,
3017
+ vastTagUrl,
3018
+ adPlayerType,
2954
3019
  ...restVideoAttrs
2955
3020
  } = props;
2956
3021
  const videoRef = useRef(null);
@@ -2970,6 +3035,19 @@ var StormcloudVideoPlayerComponent = React.memo(
2970
3035
  const [isBuffering, setIsBuffering] = React.useState(false);
2971
3036
  const [showCenterPlay, setShowCenterPlay] = React.useState(false);
2972
3037
  const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);
3038
+ const [viewportWidth, setViewportWidth] = React.useState(
3039
+ typeof window !== "undefined" ? window.innerWidth : 1920
3040
+ );
3041
+ const [isPortrait, setIsPortrait] = React.useState(
3042
+ typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false
3043
+ );
3044
+ const getResponsiveScale = () => {
3045
+ if (viewportWidth < 480) return 0.7;
3046
+ if (viewportWidth < 768) return 0.8;
3047
+ if (viewportWidth < 1024) return 0.9;
3048
+ return 1;
3049
+ };
3050
+ const responsiveScale = getResponsiveScale();
2973
3051
  const formatTime = (seconds) => {
2974
3052
  if (!isFinite(seconds)) return "0:00:00";
2975
3053
  const hours = Math.floor(seconds / 3600);
@@ -2978,10 +3056,20 @@ var StormcloudVideoPlayerComponent = React.memo(
2978
3056
  return `${hours}:${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
2979
3057
  };
2980
3058
  const handlePlayPause = () => {
3059
+ var _a;
2981
3060
  if (videoRef.current) {
2982
3061
  if (videoRef.current.paused) {
2983
- videoRef.current.play();
2984
- setShowCenterPlay(false);
3062
+ const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== "" || videoRef.current.readyState >= 1;
3063
+ if (hasValidSource) {
3064
+ (_a = videoRef.current.play()) == null ? void 0 : _a.catch((error) => {
3065
+ console.error("[StormcloudVideoPlayer] Failed to play:", error);
3066
+ });
3067
+ setShowCenterPlay(false);
3068
+ } else {
3069
+ console.warn(
3070
+ "[StormcloudVideoPlayer] Cannot play: video has no valid source"
3071
+ );
3072
+ }
2985
3073
  } else {
2986
3074
  videoRef.current.pause();
2987
3075
  setShowCenterPlay(true);
@@ -2989,9 +3077,19 @@ var StormcloudVideoPlayerComponent = React.memo(
2989
3077
  }
2990
3078
  };
2991
3079
  const handleCenterPlayClick = () => {
3080
+ var _a;
2992
3081
  if (videoRef.current && videoRef.current.paused) {
2993
- videoRef.current.play();
2994
- setShowCenterPlay(false);
3082
+ const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== "" || videoRef.current.readyState >= 1;
3083
+ if (hasValidSource) {
3084
+ (_a = videoRef.current.play()) == null ? void 0 : _a.catch((error) => {
3085
+ console.error("[StormcloudVideoPlayer] Failed to play:", error);
3086
+ });
3087
+ setShowCenterPlay(false);
3088
+ } else {
3089
+ console.warn(
3090
+ "[StormcloudVideoPlayer] Cannot play: video has no valid source"
3091
+ );
3092
+ }
2995
3093
  }
2996
3094
  };
2997
3095
  const handleTimelineSeek = (e) => {
@@ -3022,7 +3120,14 @@ var StormcloudVideoPlayerComponent = React.memo(
3022
3120
  const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);
3023
3121
  const criticalPropsKey = useMemo(() => {
3024
3122
  return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
3025
- }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
3123
+ }, [
3124
+ src,
3125
+ allowNativeHls,
3126
+ licenseKey,
3127
+ lowLatencyMode,
3128
+ driftToleranceMs,
3129
+ vastMode
3130
+ ]);
3026
3131
  useEffect(() => {
3027
3132
  if (typeof window === "undefined") return;
3028
3133
  const el = videoRef.current;
@@ -3063,6 +3168,9 @@ var StormcloudVideoPlayerComponent = React.memo(
3063
3168
  cfg.onFullscreenToggle = onFullscreenToggle;
3064
3169
  if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
3065
3170
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
3171
+ if (vastMode !== void 0) cfg.vastMode = vastMode;
3172
+ if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
3173
+ if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
3066
3174
  const player = new StormcloudVideoPlayer(cfg);
3067
3175
  playerRef.current = player;
3068
3176
  player.load().then(() => {
@@ -3123,6 +3231,8 @@ var StormcloudVideoPlayerComponent = React.memo(
3123
3231
  playerRef.current.resize();
3124
3232
  }
3125
3233
  }
3234
+ setViewportWidth(window.innerWidth);
3235
+ setIsPortrait(window.innerHeight > window.innerWidth);
3126
3236
  };
3127
3237
  window.addEventListener("resize", handleResize);
3128
3238
  return () => window.removeEventListener("resize", handleResize);
@@ -3439,14 +3549,14 @@ var StormcloudVideoPlayerComponent = React.memo(
3439
3549
  },
3440
3550
  onMouseEnter: (e) => {
3441
3551
  const target = e.currentTarget;
3442
- target.style.transform = "translate(-50%, -50%) scale(1.1)";
3552
+ target.style.transform = "translate(-50%, -50%)";
3443
3553
  target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)";
3444
3554
  target.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
3445
3555
  target.style.borderColor = "rgba(255, 255, 255, 0.9)";
3446
3556
  },
3447
3557
  onMouseLeave: (e) => {
3448
3558
  const target = e.currentTarget;
3449
- target.style.transform = "translate(-50%, -50%) scale(1)";
3559
+ target.style.transform = "translate(-50%, -50%)";
3450
3560
  target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)";
3451
3561
  target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
3452
3562
  target.style.borderColor = "rgba(255, 255, 255, 0.8)";
@@ -3536,7 +3646,9 @@ var StormcloudVideoPlayerComponent = React.memo(
3536
3646
  display: "flex",
3537
3647
  alignItems: "center",
3538
3648
  justifyContent: "space-between",
3539
- color: "white"
3649
+ color: "white",
3650
+ flexWrap: viewportWidth < 768 ? "wrap" : "nowrap",
3651
+ gap: `${8 * responsiveScale}px`
3540
3652
  },
3541
3653
  children: [
3542
3654
  /* @__PURE__ */ jsxs(
@@ -3545,7 +3657,8 @@ var StormcloudVideoPlayerComponent = React.memo(
3545
3657
  style: {
3546
3658
  display: "flex",
3547
3659
  alignItems: "center",
3548
- gap: "12px"
3660
+ gap: `${12 * responsiveScale}px`,
3661
+ flexWrap: viewportWidth < 480 ? "wrap" : "nowrap"
3549
3662
  },
3550
3663
  children: [
3551
3664
  /* @__PURE__ */ jsx(
@@ -3553,44 +3666,42 @@ var StormcloudVideoPlayerComponent = React.memo(
3553
3666
  {
3554
3667
  onClick: handlePlayPause,
3555
3668
  style: {
3556
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)",
3557
- backdropFilter: "blur(10px)",
3558
- border: "1px solid rgba(255, 255, 255, 0.2)",
3669
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
3670
+ backdropFilter: "blur(12px)",
3671
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3559
3672
  color: "#ffffff",
3560
3673
  cursor: "pointer",
3561
- padding: "12px",
3562
- borderRadius: "12px",
3674
+ padding: `${10 * responsiveScale}px`,
3675
+ borderRadius: `${16 * responsiveScale}px`,
3563
3676
  display: "flex",
3564
3677
  alignItems: "center",
3565
3678
  justifyContent: "center",
3566
3679
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3567
- boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2)",
3568
- minWidth: "48px",
3569
- minHeight: "48px"
3680
+ 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)",
3681
+ minWidth: `${48 * responsiveScale}px`,
3682
+ minHeight: `${48 * responsiveScale}px`
3570
3683
  },
3571
3684
  onMouseEnter: (e) => {
3572
3685
  const target = e.target;
3573
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.1) 100%)";
3574
- target.style.transform = "translateY(-2px) scale(1.05)";
3575
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
3686
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
3687
+ 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)";
3576
3688
  },
3577
3689
  onMouseLeave: (e) => {
3578
3690
  const target = e.target;
3579
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
3580
- target.style.transform = "translateY(0) scale(1)";
3581
- target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
3691
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
3692
+ 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)";
3582
3693
  },
3583
3694
  title: isPlaying ? "Pause" : "Play",
3584
3695
  children: isPlaying ? /* @__PURE__ */ jsx(
3585
3696
  FaPause,
3586
3697
  {
3587
- size: 20,
3698
+ size: Math.max(16, 20 * responsiveScale),
3588
3699
  style: { filter: "drop-shadow(0 0 0 transparent)" }
3589
3700
  }
3590
3701
  ) : /* @__PURE__ */ jsx(
3591
3702
  FaPlay,
3592
3703
  {
3593
- size: 20,
3704
+ size: Math.max(16, 20 * responsiveScale),
3594
3705
  style: { filter: "drop-shadow(0 0 0 transparent)" }
3595
3706
  }
3596
3707
  )
@@ -3613,45 +3724,44 @@ var StormcloudVideoPlayerComponent = React.memo(
3613
3724
  "button",
3614
3725
  {
3615
3726
  onClick: () => {
3727
+ if (playerRef.current) {
3728
+ playerRef.current.toggleMute();
3729
+ }
3616
3730
  if (onVolumeToggle) {
3617
3731
  onVolumeToggle();
3618
- } else if (playerRef.current) {
3619
- playerRef.current.toggleMute();
3620
3732
  }
3621
3733
  },
3622
3734
  style: {
3623
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)",
3624
- backdropFilter: "blur(8px)",
3625
- border: "1px solid rgba(255, 255, 255, 0.15)",
3626
- color: isMuted ? "#ff6b6b" : "#ffffff",
3735
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
3736
+ backdropFilter: "blur(10px)",
3737
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3738
+ color: "#ffffff",
3627
3739
  cursor: "pointer",
3628
- padding: "10px",
3629
- borderRadius: "10px",
3740
+ padding: `${8 * responsiveScale}px`,
3741
+ borderRadius: `${16 * responsiveScale}px`,
3630
3742
  display: "flex",
3631
3743
  alignItems: "center",
3632
3744
  justifyContent: "center",
3633
3745
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3634
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
3635
- minWidth: "40px",
3636
- minHeight: "40px"
3746
+ 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)",
3747
+ minWidth: `${44 * responsiveScale}px`,
3748
+ minHeight: `${44 * responsiveScale}px`
3637
3749
  },
3638
3750
  onMouseEnter: (e) => {
3639
3751
  const target = e.target;
3640
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.08) 100%)";
3641
- target.style.transform = "translateY(-1px) scale(1.03)";
3642
- target.style.boxShadow = "0 8px 28px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
3752
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
3753
+ 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)";
3643
3754
  },
3644
3755
  onMouseLeave: (e) => {
3645
3756
  const target = e.target;
3646
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)";
3647
- target.style.transform = "translateY(0) scale(1)";
3648
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
3757
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
3758
+ 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)";
3649
3759
  },
3650
3760
  title: isMuted ? "Unmute" : "Mute",
3651
3761
  children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(
3652
3762
  FaVolumeMute,
3653
3763
  {
3654
- size: 16,
3764
+ size: Math.max(14, 16 * responsiveScale),
3655
3765
  style: {
3656
3766
  filter: "drop-shadow(0 0 0 transparent)"
3657
3767
  }
@@ -3659,7 +3769,7 @@ var StormcloudVideoPlayerComponent = React.memo(
3659
3769
  ) : volume < 0.5 ? /* @__PURE__ */ jsx(
3660
3770
  FaVolumeDown,
3661
3771
  {
3662
- size: 16,
3772
+ size: Math.max(14, 16 * responsiveScale),
3663
3773
  style: {
3664
3774
  filter: "drop-shadow(0 0 0 transparent)"
3665
3775
  }
@@ -3667,7 +3777,7 @@ var StormcloudVideoPlayerComponent = React.memo(
3667
3777
  ) : /* @__PURE__ */ jsx(
3668
3778
  FaVolumeUp,
3669
3779
  {
3670
- size: 16,
3780
+ size: Math.max(14, 16 * responsiveScale),
3671
3781
  style: {
3672
3782
  filter: "drop-shadow(0 0 0 transparent)"
3673
3783
  }
@@ -3718,13 +3828,11 @@ var StormcloudVideoPlayerComponent = React.memo(
3718
3828
  },
3719
3829
  onMouseEnter: (e) => {
3720
3830
  setShowVolumeSlider(true);
3721
- e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
3722
3831
  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)";
3723
3832
  e.currentTarget.style.borderColor = "rgba(59, 130, 246, 0.4)";
3724
3833
  },
3725
3834
  onMouseLeave: (e) => {
3726
3835
  setShowVolumeSlider(false);
3727
- e.currentTarget.style.transform = "translateX(-50%)";
3728
3836
  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)";
3729
3837
  e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.15)";
3730
3838
  },
@@ -3739,10 +3847,8 @@ var StormcloudVideoPlayerComponent = React.memo(
3739
3847
  transition: "transform 0.2s ease-in-out"
3740
3848
  },
3741
3849
  onMouseEnter: (e) => {
3742
- e.currentTarget.style.transform = "scaleX(1.2)";
3743
3850
  },
3744
3851
  onMouseLeave: (e) => {
3745
- e.currentTarget.style.transform = "scaleX(1)";
3746
3852
  },
3747
3853
  onMouseDown: (e) => {
3748
3854
  e.preventDefault();
@@ -3755,11 +3861,23 @@ var StormcloudVideoPlayerComponent = React.memo(
3755
3861
  handleVolumeChange(percentage2);
3756
3862
  };
3757
3863
  const handleMouseUp = () => {
3758
- document.removeEventListener("mousemove", handleMouseMove);
3759
- document.removeEventListener("mouseup", handleMouseUp);
3864
+ document.removeEventListener(
3865
+ "mousemove",
3866
+ handleMouseMove
3867
+ );
3868
+ document.removeEventListener(
3869
+ "mouseup",
3870
+ handleMouseUp
3871
+ );
3760
3872
  };
3761
- document.addEventListener("mousemove", handleMouseMove);
3762
- document.addEventListener("mouseup", handleMouseUp);
3873
+ document.addEventListener(
3874
+ "mousemove",
3875
+ handleMouseMove
3876
+ );
3877
+ document.addEventListener(
3878
+ "mouseup",
3879
+ handleMouseUp
3880
+ );
3763
3881
  const rect = sliderElement.getBoundingClientRect();
3764
3882
  const y = e.clientY - rect.top;
3765
3883
  const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
@@ -3821,20 +3939,16 @@ var StormcloudVideoPlayerComponent = React.memo(
3821
3939
  cursor: "grab"
3822
3940
  },
3823
3941
  onMouseEnter: (e) => {
3824
- e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
3825
3942
  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)";
3826
3943
  e.currentTarget.style.cursor = "grab";
3827
3944
  },
3828
3945
  onMouseLeave: (e) => {
3829
- e.currentTarget.style.transform = "translateX(-50%) scale(1)";
3830
3946
  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)";
3831
3947
  },
3832
3948
  onMouseDown: (e) => {
3833
- e.currentTarget.style.transform = "translateX(-50%) scale(1.4)";
3834
3949
  e.currentTarget.style.cursor = "grabbing";
3835
3950
  },
3836
3951
  onMouseUp: (e) => {
3837
- e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
3838
3952
  e.currentTarget.style.cursor = "grab";
3839
3953
  }
3840
3954
  }
@@ -3852,9 +3966,10 @@ var StormcloudVideoPlayerComponent = React.memo(
3852
3966
  "div",
3853
3967
  {
3854
3968
  style: {
3855
- fontSize: "14px",
3969
+ fontSize: `${14 * responsiveScale}px`,
3856
3970
  fontFamily: "monospace",
3857
- color: "rgba(255, 255, 255, 0.9)"
3971
+ color: "rgba(255, 255, 255, 0.9)",
3972
+ display: viewportWidth < 480 ? "none" : "block"
3858
3973
  },
3859
3974
  children: [
3860
3975
  formatTime(currentTime),
@@ -3872,105 +3987,113 @@ var StormcloudVideoPlayerComponent = React.memo(
3872
3987
  style: {
3873
3988
  display: "flex",
3874
3989
  alignItems: "center",
3875
- gap: "12px"
3990
+ gap: `${12 * responsiveScale}px`
3876
3991
  },
3877
3992
  children: [
3878
- /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
3879
- /* @__PURE__ */ jsxs(
3880
- "button",
3881
- {
3882
- onClick: () => setShowSpeedMenu(!showSpeedMenu),
3883
- style: {
3884
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 100%)",
3885
- backdropFilter: "blur(8px)",
3886
- border: "1px solid rgba(255, 255, 255, 0.12)",
3887
- color: "#ffffff",
3888
- cursor: "pointer",
3889
- padding: "8px 14px",
3890
- borderRadius: "8px",
3891
- fontSize: "13px",
3892
- fontFamily: "monospace",
3893
- fontWeight: "600",
3894
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3895
- boxShadow: "0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08)",
3896
- minWidth: "50px"
3897
- },
3898
- onMouseEnter: (e) => {
3899
- const target = e.target;
3900
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0.06) 100%)";
3901
- target.style.transform = "translateY(-1px) scale(1.02)";
3902
- target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)";
3903
- },
3904
- onMouseLeave: (e) => {
3905
- const target = e.target;
3906
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 100%)";
3907
- target.style.transform = "translateY(0) scale(1)";
3908
- target.style.boxShadow = "0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08)";
3909
- },
3910
- title: "Playback Speed",
3911
- children: [
3912
- playbackRate,
3913
- "x"
3914
- ]
3915
- }
3916
- ),
3917
- showSpeedMenu && /* @__PURE__ */ jsx(
3918
- "div",
3919
- {
3920
- style: {
3921
- position: "absolute",
3922
- bottom: "100%",
3923
- right: 0,
3924
- marginBottom: "12px",
3925
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
3926
- backdropFilter: "blur(20px)",
3927
- borderRadius: "12px",
3928
- border: "1px solid rgba(255, 255, 255, 0.1)",
3929
- overflow: "hidden",
3930
- minWidth: "90px",
3931
- boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
3932
- },
3933
- children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
3934
- (speed) => /* @__PURE__ */ jsxs(
3935
- "button",
3936
- {
3937
- onClick: () => handlePlaybackRateChange(speed),
3938
- style: {
3939
- display: "block",
3940
- width: "100%",
3941
- padding: "10px 16px",
3942
- background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
3943
- border: "none",
3944
- color: "white",
3945
- cursor: "pointer",
3946
- fontSize: "13px",
3947
- fontFamily: "monospace",
3948
- fontWeight: "600",
3949
- textAlign: "center",
3950
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
3951
- borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
3952
- },
3953
- onMouseEnter: (e) => {
3954
- if (playbackRate !== speed) {
3955
- e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
3956
- }
3957
- },
3958
- onMouseLeave: (e) => {
3959
- if (playbackRate !== speed) {
3960
- e.target.style.background = "transparent";
3961
- }
3962
- },
3963
- children: [
3964
- speed,
3965
- "x"
3966
- ]
3993
+ /* @__PURE__ */ jsxs(
3994
+ "div",
3995
+ {
3996
+ style: {
3997
+ position: "relative",
3998
+ display: viewportWidth < 600 ? "none" : "block"
3999
+ },
4000
+ children: [
4001
+ /* @__PURE__ */ jsxs(
4002
+ "button",
4003
+ {
4004
+ onClick: () => setShowSpeedMenu(!showSpeedMenu),
4005
+ style: {
4006
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
4007
+ backdropFilter: "blur(10px)",
4008
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
4009
+ color: "#ffffff",
4010
+ cursor: "pointer",
4011
+ padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,
4012
+ borderRadius: `${14 * responsiveScale}px`,
4013
+ fontSize: `${14 * responsiveScale}px`,
4014
+ fontFamily: "monospace",
4015
+ fontWeight: "700",
4016
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
4017
+ 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)",
4018
+ minWidth: `${56 * responsiveScale}px`,
4019
+ minHeight: `${40 * responsiveScale}px`
3967
4020
  },
3968
- speed
3969
- )
4021
+ onMouseEnter: (e) => {
4022
+ const target = e.target;
4023
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
4024
+ 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)";
4025
+ },
4026
+ onMouseLeave: (e) => {
4027
+ const target = e.target;
4028
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
4029
+ 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)";
4030
+ },
4031
+ title: "Playback Speed",
4032
+ children: [
4033
+ playbackRate,
4034
+ "x"
4035
+ ]
4036
+ }
4037
+ ),
4038
+ showSpeedMenu && /* @__PURE__ */ jsx(
4039
+ "div",
4040
+ {
4041
+ style: {
4042
+ position: "absolute",
4043
+ bottom: "100%",
4044
+ right: 0,
4045
+ marginBottom: "12px",
4046
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
4047
+ backdropFilter: "blur(20px)",
4048
+ borderRadius: "12px",
4049
+ border: "1px solid rgba(255, 255, 255, 0.1)",
4050
+ overflow: "hidden",
4051
+ minWidth: "90px",
4052
+ boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
4053
+ },
4054
+ children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
4055
+ (speed) => /* @__PURE__ */ jsxs(
4056
+ "button",
4057
+ {
4058
+ onClick: () => handlePlaybackRateChange(speed),
4059
+ style: {
4060
+ display: "block",
4061
+ width: "100%",
4062
+ padding: "10px 16px",
4063
+ background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
4064
+ border: "none",
4065
+ color: "white",
4066
+ cursor: "pointer",
4067
+ fontSize: "13px",
4068
+ fontFamily: "monospace",
4069
+ fontWeight: "600",
4070
+ textAlign: "center",
4071
+ transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
4072
+ borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
4073
+ },
4074
+ onMouseEnter: (e) => {
4075
+ if (playbackRate !== speed) {
4076
+ e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
4077
+ }
4078
+ },
4079
+ onMouseLeave: (e) => {
4080
+ if (playbackRate !== speed) {
4081
+ e.target.style.background = "transparent";
4082
+ }
4083
+ },
4084
+ children: [
4085
+ speed,
4086
+ "x"
4087
+ ]
4088
+ },
4089
+ speed
4090
+ )
4091
+ )
4092
+ }
3970
4093
  )
3971
- }
3972
- )
3973
- ] }),
4094
+ ]
4095
+ }
4096
+ ),
3974
4097
  /* @__PURE__ */ jsx(
3975
4098
  "button",
3976
4099
  {
@@ -3984,44 +4107,42 @@ var StormcloudVideoPlayerComponent = React.memo(
3984
4107
  }
3985
4108
  },
3986
4109
  style: {
3987
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)",
3988
- backdropFilter: "blur(8px)",
3989
- border: "1px solid rgba(255, 255, 255, 0.15)",
4110
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
4111
+ backdropFilter: "blur(10px)",
4112
+ border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,
3990
4113
  color: "#ffffff",
3991
4114
  cursor: "pointer",
3992
- padding: "10px",
3993
- borderRadius: "10px",
4115
+ padding: `${8 * responsiveScale}px`,
4116
+ borderRadius: `${16 * responsiveScale}px`,
3994
4117
  display: "flex",
3995
4118
  alignItems: "center",
3996
4119
  justifyContent: "center",
3997
4120
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3998
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
3999
- minWidth: "40px",
4000
- minHeight: "40px"
4121
+ 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)",
4122
+ minWidth: `${44 * responsiveScale}px`,
4123
+ minHeight: `${44 * responsiveScale}px`
4001
4124
  },
4002
4125
  onMouseEnter: (e) => {
4003
4126
  const target = e.target;
4004
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.08) 100%)";
4005
- target.style.transform = "translateY(-1px) scale(1.03)";
4006
- target.style.boxShadow = "0 8px 28px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
4127
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
4128
+ 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)";
4007
4129
  },
4008
4130
  onMouseLeave: (e) => {
4009
4131
  const target = e.target;
4010
- target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 100%)";
4011
- target.style.transform = "translateY(0) scale(1)";
4012
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
4132
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
4133
+ 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)";
4013
4134
  },
4014
4135
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
4015
4136
  children: isFullscreen ? /* @__PURE__ */ jsx(
4016
4137
  FaCompress,
4017
4138
  {
4018
- size: 16,
4139
+ size: Math.max(14, 16 * responsiveScale),
4019
4140
  style: { filter: "drop-shadow(0 0 0 transparent)" }
4020
4141
  }
4021
4142
  ) : /* @__PURE__ */ jsx(
4022
4143
  FaExpand,
4023
4144
  {
4024
- size: 16,
4145
+ size: Math.max(14, 16 * responsiveScale),
4025
4146
  style: { filter: "drop-shadow(0 0 0 transparent)" }
4026
4147
  }
4027
4148
  )
@@ -4040,10 +4161,12 @@ var StormcloudVideoPlayerComponent = React.memo(
4040
4161
  {
4041
4162
  style: {
4042
4163
  position: "absolute",
4043
- bottom: "10px",
4044
- right: "10px",
4164
+ bottom: `${10 * responsiveScale}px`,
4165
+ right: `${10 * responsiveScale}px`,
4166
+ transform: "none",
4045
4167
  display: "flex",
4046
- gap: "8px",
4168
+ flexDirection: isPortrait ? "column" : "row",
4169
+ gap: `${10 * responsiveScale}px`,
4047
4170
  zIndex: 10
4048
4171
  },
4049
4172
  children: [
@@ -4064,45 +4187,44 @@ var StormcloudVideoPlayerComponent = React.memo(
4064
4187
  "button",
4065
4188
  {
4066
4189
  onClick: () => {
4190
+ if (playerRef.current) {
4191
+ playerRef.current.toggleMute();
4192
+ }
4067
4193
  if (onVolumeToggle) {
4068
4194
  onVolumeToggle();
4069
- } else if (playerRef.current) {
4070
- playerRef.current.toggleMute();
4071
4195
  }
4072
4196
  },
4073
4197
  onMouseEnter: (e) => {
4074
4198
  const target = e.currentTarget;
4075
- target.style.transform = "translateY(-3px) scale(1.08)";
4076
- 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)";
4077
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(40, 40, 40, 0.85) 100%)";
4199
+ 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)";
4200
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
4078
4201
  },
4079
4202
  onMouseLeave: (e) => {
4080
4203
  const target = e.currentTarget;
4081
- target.style.transform = "translateY(0) scale(1)";
4082
- 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)";
4083
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)";
4204
+ 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)";
4205
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
4084
4206
  },
4085
4207
  style: {
4086
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)",
4087
- color: isMuted ? "#ff6b6b" : "#ffffff",
4208
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
4209
+ color: "#ffffff",
4088
4210
  border: "none",
4089
- borderRadius: "16px",
4090
- padding: "10px",
4211
+ borderRadius: `${18 * responsiveScale}px`,
4212
+ padding: `${8 * responsiveScale}px`,
4091
4213
  cursor: "pointer",
4092
4214
  display: "flex",
4093
4215
  alignItems: "center",
4094
4216
  justifyContent: "center",
4095
4217
  backdropFilter: "blur(20px)",
4096
- 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)",
4218
+ 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)",
4097
4219
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
4098
- minWidth: "44px",
4099
- minHeight: "44px"
4220
+ minWidth: `${46 * responsiveScale}px`,
4221
+ minHeight: `${46 * responsiveScale}px`
4100
4222
  },
4101
4223
  title: isMuted ? "Unmute" : "Mute",
4102
4224
  children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(
4103
4225
  FaVolumeMute,
4104
4226
  {
4105
- size: 16,
4227
+ size: Math.max(14, 16 * responsiveScale),
4106
4228
  style: {
4107
4229
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4108
4230
  color: "#ffffff"
@@ -4111,7 +4233,7 @@ var StormcloudVideoPlayerComponent = React.memo(
4111
4233
  ) : volume < 0.5 ? /* @__PURE__ */ jsx(
4112
4234
  FaVolumeDown,
4113
4235
  {
4114
- size: 16,
4236
+ size: Math.max(14, 16 * responsiveScale),
4115
4237
  style: {
4116
4238
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4117
4239
  color: "#ffffff"
@@ -4120,7 +4242,7 @@ var StormcloudVideoPlayerComponent = React.memo(
4120
4242
  ) : /* @__PURE__ */ jsx(
4121
4243
  FaVolumeUp,
4122
4244
  {
4123
- size: 16,
4245
+ size: Math.max(14, 16 * responsiveScale),
4124
4246
  style: {
4125
4247
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4126
4248
  color: "#ffffff"
@@ -4172,13 +4294,11 @@ var StormcloudVideoPlayerComponent = React.memo(
4172
4294
  },
4173
4295
  onMouseEnter: (e) => {
4174
4296
  setShowVolumeSlider(true);
4175
- e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
4176
4297
  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)";
4177
4298
  e.currentTarget.style.borderColor = "rgba(96, 165, 250, 0.8)";
4178
4299
  },
4179
4300
  onMouseLeave: (e) => {
4180
4301
  setShowVolumeSlider(false);
4181
- e.currentTarget.style.transform = "translateX(-50%)";
4182
4302
  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)";
4183
4303
  e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.7)";
4184
4304
  },
@@ -4192,12 +4312,6 @@ var StormcloudVideoPlayerComponent = React.memo(
4192
4312
  cursor: "pointer",
4193
4313
  transition: "transform 0.2s ease-in-out"
4194
4314
  },
4195
- onMouseEnter: (e) => {
4196
- e.currentTarget.style.transform = "scaleX(1.2)";
4197
- },
4198
- onMouseLeave: (e) => {
4199
- e.currentTarget.style.transform = "scaleX(1)";
4200
- },
4201
4315
  onMouseDown: (e) => {
4202
4316
  e.preventDefault();
4203
4317
  const sliderElement = e.currentTarget;
@@ -4209,11 +4323,23 @@ var StormcloudVideoPlayerComponent = React.memo(
4209
4323
  handleVolumeChange(percentage2);
4210
4324
  };
4211
4325
  const handleMouseUp = () => {
4212
- document.removeEventListener("mousemove", handleMouseMove);
4213
- document.removeEventListener("mouseup", handleMouseUp);
4326
+ document.removeEventListener(
4327
+ "mousemove",
4328
+ handleMouseMove
4329
+ );
4330
+ document.removeEventListener(
4331
+ "mouseup",
4332
+ handleMouseUp
4333
+ );
4214
4334
  };
4215
- document.addEventListener("mousemove", handleMouseMove);
4216
- document.addEventListener("mouseup", handleMouseUp);
4335
+ document.addEventListener(
4336
+ "mousemove",
4337
+ handleMouseMove
4338
+ );
4339
+ document.addEventListener(
4340
+ "mouseup",
4341
+ handleMouseUp
4342
+ );
4217
4343
  const rect = sliderElement.getBoundingClientRect();
4218
4344
  const y = e.clientY - rect.top;
4219
4345
  const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
@@ -4277,20 +4403,16 @@ var StormcloudVideoPlayerComponent = React.memo(
4277
4403
  cursor: "grab"
4278
4404
  },
4279
4405
  onMouseEnter: (e) => {
4280
- e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
4281
4406
  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)";
4282
4407
  e.currentTarget.style.cursor = "grab";
4283
4408
  },
4284
4409
  onMouseLeave: (e) => {
4285
- e.currentTarget.style.transform = "translateX(-50%) scale(1)";
4286
4410
  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)";
4287
4411
  },
4288
4412
  onMouseDown: (e) => {
4289
- e.currentTarget.style.transform = "translateX(-50%) scale(1.45)";
4290
4413
  e.currentTarget.style.cursor = "grabbing";
4291
4414
  },
4292
4415
  onMouseUp: (e) => {
4293
- e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
4294
4416
  e.currentTarget.style.cursor = "grab";
4295
4417
  }
4296
4418
  }
@@ -4318,37 +4440,35 @@ var StormcloudVideoPlayerComponent = React.memo(
4318
4440
  },
4319
4441
  onMouseEnter: (e) => {
4320
4442
  const target = e.currentTarget;
4321
- target.style.transform = "translateY(-3px) scale(1.08)";
4322
- 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)";
4323
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(40, 40, 40, 0.85) 100%)";
4443
+ 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)";
4444
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
4324
4445
  },
4325
4446
  onMouseLeave: (e) => {
4326
4447
  const target = e.currentTarget;
4327
- target.style.transform = "translateY(0) scale(1)";
4328
- 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)";
4329
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)";
4448
+ 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)";
4449
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
4330
4450
  },
4331
4451
  style: {
4332
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(30, 30, 30, 0.8) 100%)",
4452
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
4333
4453
  color: "#ffffff",
4334
4454
  border: "none",
4335
- borderRadius: "16px",
4336
- padding: "10px",
4455
+ borderRadius: `${18 * responsiveScale}px`,
4456
+ padding: `${8 * responsiveScale}px`,
4337
4457
  cursor: "pointer",
4338
4458
  display: "flex",
4339
4459
  alignItems: "center",
4340
4460
  justifyContent: "center",
4341
4461
  backdropFilter: "blur(20px)",
4342
- 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)",
4462
+ 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)",
4343
4463
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
4344
- minWidth: "44px",
4345
- minHeight: "44px"
4464
+ minWidth: `${46 * responsiveScale}px`,
4465
+ minHeight: `${46 * responsiveScale}px`
4346
4466
  },
4347
4467
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
4348
4468
  children: isFullscreen ? /* @__PURE__ */ jsx(
4349
4469
  FaCompress,
4350
4470
  {
4351
- size: 16,
4471
+ size: Math.max(14, 16 * responsiveScale),
4352
4472
  style: {
4353
4473
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4354
4474
  color: "#ffffff"
@@ -4357,7 +4477,7 @@ var StormcloudVideoPlayerComponent = React.memo(
4357
4477
  ) : /* @__PURE__ */ jsx(
4358
4478
  FaExpand,
4359
4479
  {
4360
- size: 16,
4480
+ size: Math.max(14, 16 * responsiveScale),
4361
4481
  style: {
4362
4482
  filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
4363
4483
  color: "#ffffff"
@@ -4647,10 +4767,20 @@ var HlsPlayer = class extends Component {
4647
4767
  }
4648
4768
  };
4649
4769
  this.play = () => {
4650
- var _a, _b;
4770
+ var _a, _b, _c;
4651
4771
  if (this.props.videoElement) {
4652
- this.props.videoElement.play();
4653
- (_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
4772
+ const video = this.props.videoElement;
4773
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
4774
+ if (hasValidSource) {
4775
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
4776
+ var _a2, _b2;
4777
+ console.error("[HlsPlayer] Failed to play:", error);
4778
+ (_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
4779
+ });
4780
+ (_c = (_b = this.props).onPlay) == null ? void 0 : _c.call(_b);
4781
+ } else {
4782
+ console.warn("[HlsPlayer] Cannot play: video has no valid source");
4783
+ }
4654
4784
  }
4655
4785
  };
4656
4786
  this.pause = () => {
@@ -4819,8 +4949,19 @@ var FilePlayer = class extends Component2 {
4819
4949
  };
4820
4950
  };
4821
4951
  this.play = () => {
4952
+ var _a;
4822
4953
  if (this.props.videoElement) {
4823
- this.props.videoElement.play();
4954
+ const video = this.props.videoElement;
4955
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
4956
+ if (hasValidSource) {
4957
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
4958
+ var _a2, _b;
4959
+ console.error("[FilePlayer] Failed to play:", error);
4960
+ (_b = (_a2 = this.props).onError) == null ? void 0 : _b.call(_a2, error);
4961
+ });
4962
+ } else {
4963
+ console.warn("[FilePlayer] Cannot play: video has no valid source");
4964
+ }
4824
4965
  }
4825
4966
  };
4826
4967
  this.pause = () => {