unified-video-framework 1.4.162 → 1.4.164

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.
@@ -3861,217 +3861,6 @@ export class WebPlayer extends BasePlayer {
3861
3861
  @media screen and (max-width: 767px) {
3862
3862
  html, body {
3863
3863
  overflow-x: hidden;
3864
- background: #000;
3865
- }
3866
-
3867
- /* Mobile Portrait Layout - Centered Player with Top/Bottom Black Areas */
3868
- @media screen and (orientation: portrait) {
3869
- .uvf-responsive-container {
3870
- display: flex;
3871
- flex-direction: column;
3872
- height: 100vh;
3873
- height: 100dvh;
3874
- background: #000;
3875
- overflow: hidden;
3876
- position: fixed;
3877
- top: 0;
3878
- left: 0;
3879
- width: 100vw;
3880
- }
3881
-
3882
- /* Top black area - 25% of viewport */
3883
- .uvf-responsive-container::before {
3884
- content: '';
3885
- flex: 0 0 25vh;
3886
- background: #000;
3887
- pointer-events: none;
3888
- }
3889
-
3890
- /* Bottom black area - 25% of viewport */
3891
- .uvf-responsive-container::after {
3892
- content: '';
3893
- flex: 0 0 25vh;
3894
- background: #000;
3895
- pointer-events: none;
3896
- }
3897
-
3898
- /* Centered video player wrapper - 50% of viewport */
3899
- .uvf-responsive-container .uvf-player-wrapper {
3900
- flex: 1;
3901
- width: 100vw;
3902
- display: flex;
3903
- align-items: center;
3904
- justify-content: center;
3905
- background: #000;
3906
- position: relative;
3907
- }
3908
-
3909
- /* Video container fills player wrapper */
3910
- .uvf-responsive-container .uvf-video-container {
3911
- width: 100%;
3912
- height: 100%;
3913
- position: relative;
3914
- background: #000;
3915
- border-radius: 0;
3916
- overflow: hidden;
3917
- }
3918
-
3919
- /* Video element fills container */
3920
- .uvf-responsive-container .uvf-video {
3921
- width: 100%;
3922
- height: 100%;
3923
- object-fit: contain;
3924
- background: #000;
3925
- }
3926
-
3927
- /* All controls positioned inside video container */
3928
- .uvf-controls-bar {
3929
- position: absolute !important;
3930
- bottom: 0 !important;
3931
- left: 0 !important;
3932
- right: 0 !important;
3933
- background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
3934
- padding: 12px 16px;
3935
- padding-bottom: calc(12px + var(--uvf-safe-area-bottom));
3936
- z-index: 1000;
3937
- /* Ensure controls are always visible */
3938
- opacity: 1 !important;
3939
- visibility: visible !important;
3940
- display: flex !important;
3941
- flex-direction: column !important;
3942
- /* Ensure hardware acceleration */
3943
- -webkit-transform: translate3d(0,0,0);
3944
- transform: translate3d(0,0,0);
3945
- }
3946
-
3947
- /* Force controls visibility on mobile portrait */
3948
- .uvf-responsive-container .uvf-controls-bar {
3949
- opacity: 1 !important;
3950
- visibility: visible !important;
3951
- transform: translateY(0) !important;
3952
- pointer-events: auto !important;
3953
- }
3954
-
3955
- /* Progress section - ensure visibility */
3956
- .uvf-progress-section {
3957
- width: 100%;
3958
- margin-bottom: 8px;
3959
- opacity: 1 !important;
3960
- visibility: visible !important;
3961
- display: block !important;
3962
- }
3963
-
3964
- /* Progress bar styling */
3965
- .uvf-progress-bar-wrapper {
3966
- opacity: 1 !important;
3967
- visibility: visible !important;
3968
- }
3969
-
3970
- .uvf-progress-bar {
3971
- height: 4px;
3972
- background: rgba(255, 255, 255, 0.3);
3973
- border-radius: 2px;
3974
- }
3975
-
3976
- .uvf-progress-filled {
3977
- background: var(--uvf-accent-1, #8B5CF6);
3978
- height: 100%;
3979
- border-radius: 2px;
3980
- }
3981
-
3982
- /* Controls row alignment - ensure visibility */
3983
- .uvf-controls-row {
3984
- width: 100%;
3985
- display: flex !important;
3986
- align-items: center;
3987
- justify-content: flex-start;
3988
- gap: 12px;
3989
- opacity: 1 !important;
3990
- visibility: visible !important;
3991
- margin-top: 8px;
3992
- }
3993
-
3994
- /* Time display visibility */
3995
- .uvf-time-display {
3996
- color: #fff;
3997
- font-size: 12px;
3998
- font-weight: 500;
3999
- opacity: 1 !important;
4000
- visibility: visible !important;
4001
- display: block !important;
4002
- }
4003
-
4004
- /* Control buttons visibility */
4005
- .uvf-control-btn {
4006
- opacity: 1 !important;
4007
- visibility: visible !important;
4008
- display: flex !important;
4009
- color: #fff;
4010
- }
4011
-
4012
- .uvf-control-btn svg {
4013
- fill: #fff;
4014
- opacity: 1;
4015
- }
4016
-
4017
- /* Right controls - ensure visibility */
4018
- .uvf-right-controls {
4019
- margin-left: auto;
4020
- display: flex !important;
4021
- align-items: center;
4022
- gap: 8px;
4023
- opacity: 1 !important;
4024
- visibility: visible !important;
4025
- }
4026
-
4027
- /* Force controls to be always visible in portrait mode */
4028
- .uvf-responsive-container .uvf-player-wrapper.uvf-controls-visible .uvf-controls-bar,
4029
- .uvf-responsive-container .uvf-player-wrapper:hover .uvf-controls-bar,
4030
- .uvf-responsive-container .uvf-controls-bar {
4031
- opacity: 1 !important;
4032
- transform: translateY(0) !important;
4033
- visibility: visible !important;
4034
- display: flex !important;
4035
- pointer-events: auto !important;
4036
- }
4037
-
4038
- /* Ensure all child elements are visible */
4039
- .uvf-responsive-container .uvf-controls-bar * {
4040
- opacity: 1 !important;
4041
- visibility: visible !important;
4042
- }
4043
-
4044
- /* Center play button positioned within video */
4045
- .uvf-center-play-container {
4046
- position: absolute;
4047
- top: 50%;
4048
- left: 50%;
4049
- transform: translate(-50%, -50%);
4050
- z-index: 8;
4051
- pointer-events: none;
4052
- }
4053
-
4054
- .uvf-center-play-btn {
4055
- pointer-events: auto;
4056
- }
4057
-
4058
- /* Top controls within video */
4059
- .uvf-top-controls {
4060
- position: absolute;
4061
- top: calc(12px + var(--uvf-safe-area-top));
4062
- right: calc(16px + var(--uvf-safe-area-right));
4063
- z-index: 9;
4064
- }
4065
-
4066
- /* Title bar within video */
4067
- .uvf-title-bar {
4068
- position: absolute;
4069
- top: calc(12px + var(--uvf-safe-area-top));
4070
- left: calc(16px + var(--uvf-safe-area-left));
4071
- right: calc(80px + var(--uvf-safe-area-right));
4072
- z-index: 9;
4073
- padding: 8px 0;
4074
- }
4075
3864
  }
4076
3865
 
4077
3866
  .uvf-player-wrapper {
@@ -4095,37 +3884,6 @@ export class WebPlayer extends BasePlayer {
4095
3884
  transform: translateZ(0);
4096
3885
  }
4097
3886
 
4098
- /* Mobile controls optimization for touch */
4099
- .uvf-control-btn {
4100
- min-width: 44px;
4101
- min-height: 44px;
4102
- display: flex;
4103
- align-items: center;
4104
- justify-content: center;
4105
- border-radius: 50%;
4106
- transition: all 0.2s ease;
4107
- background: rgba(255, 255, 255, 0.1);
4108
- backdrop-filter: blur(8px);
4109
- }
4110
-
4111
- .uvf-control-btn:active {
4112
- transform: scale(0.95);
4113
- background: rgba(255, 255, 255, 0.2);
4114
- }
4115
-
4116
- /* Play/pause button prominence */
4117
- .uvf-control-btn.play-pause {
4118
- background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
4119
- min-width: 52px;
4120
- min-height: 52px;
4121
- box-shadow: 0 2px 8px rgba(0,0,0,0.3);
4122
- }
4123
-
4124
- .uvf-control-btn.play-pause:active {
4125
- transform: scale(0.92);
4126
- box-shadow: 0 1px 4px rgba(0,0,0,0.4);
4127
- }
4128
-
4129
3887
  /* Fix for controls being cut off by virtual keyboard */
4130
3888
  .uvf-controls-bar {
4131
3889
  position: absolute !important;
@@ -4172,61 +3930,278 @@ export class WebPlayer extends BasePlayer {
4172
3930
  }
4173
3931
 
4174
3932
  /* Enhanced Responsive Media Queries with UX Best Practices */
4175
- /* Mobile devices (portrait) - Enhanced UX with Safe Areas */
3933
+ /* Mobile Portrait Layout - CENTERED PLAYER with TOP/BOTTOM BLACK AREAS */
4176
3934
  @media screen and (max-width: 767px) and (orientation: portrait) {
3935
+ /* CENTERED LAYOUT: 25% top black + 50% player + 25% bottom black */
4177
3936
  .uvf-responsive-container {
3937
+ display: flex;
3938
+ flex-direction: column;
3939
+ height: 100vh;
3940
+ height: 100dvh;
3941
+ background: #000;
3942
+ overflow: hidden;
3943
+ position: fixed;
3944
+ top: 0;
3945
+ left: 0;
3946
+ width: 100vw;
4178
3947
  padding: 0;
4179
- width: 100vw !important;
4180
- height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4181
3948
  margin: 0;
4182
- position: relative;
4183
- overflow: hidden;
4184
3949
  }
4185
3950
 
4186
- @supports (height: 100dvh) {
4187
- .uvf-responsive-container {
4188
- height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4189
- }
3951
+ /* TOP BLACK AREA - 25% of viewport - COMPLETELY EMPTY */
3952
+ .uvf-responsive-container::before {
3953
+ content: '';
3954
+ flex: 0 0 25vh;
3955
+ background: #000;
3956
+ pointer-events: none;
4190
3957
  }
4191
3958
 
4192
- .uvf-responsive-container .uvf-player-wrapper {
4193
- width: 100vw !important;
4194
- height: 100% !important;
4195
- min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
3959
+ /* BOTTOM BLACK AREA - 25% of viewport - COMPLETELY EMPTY */
3960
+ .uvf-responsive-container::after {
3961
+ content: '';
3962
+ flex: 0 0 25vh;
3963
+ background: #000;
3964
+ pointer-events: none;
4196
3965
  }
4197
3966
 
4198
- @supports (height: 100dvh) {
4199
- .uvf-responsive-container .uvf-player-wrapper {
4200
- min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4201
- }
3967
+ /* CENTERED VIDEO PLAYER WRAPPER - 50% of viewport */
3968
+ .uvf-responsive-container .uvf-player-wrapper {
3969
+ flex: 1; /* Takes remaining 50% */
3970
+ width: 100vw;
3971
+ display: flex;
3972
+ align-items: center;
3973
+ justify-content: center;
3974
+ background: #000;
3975
+ position: relative;
3976
+ overflow: hidden !important; /* CRITICAL: Ensure nothing extends beyond this area */
3977
+ /* STRICT CONTAINMENT - Force all child elements within bounds */
3978
+ contain: layout style paint size !important;
3979
+ isolation: isolate !important;
3980
+ /* Create strict clipping boundary */
3981
+ clip: rect(0, 100vw, 50vh, 0) !important;
4202
3982
  }
4203
3983
 
3984
+ /* Video container fills player wrapper */
4204
3985
  .uvf-responsive-container .uvf-video-container {
4205
- width: 100vw !important;
4206
- height: 100% !important;
4207
- aspect-ratio: unset !important;
4208
- min-height: inherit;
3986
+ width: 100%;
3987
+ height: 100%;
3988
+ position: relative;
3989
+ background: #000;
3990
+ border-radius: 0;
3991
+ overflow: hidden;
3992
+ }
3993
+
3994
+ /* Video element fills container */
3995
+ .uvf-responsive-container .uvf-video {
3996
+ width: 100%;
3997
+ height: 100%;
3998
+ object-fit: contain;
3999
+ background: #000;
4209
4000
  }
4210
4001
 
4211
- /* Enhanced mobile controls bar with safe area padding - iOS Safari specific fixes */
4002
+ /* CONTROLS STRICTLY CONTAINED WITHIN VIDEO AREA - NEVER EXTEND TO BLACK AREAS */
4212
4003
  .uvf-controls-bar {
4213
4004
  position: absolute !important;
4214
- bottom: 0 !important;
4215
- left: 0 !important;
4005
+ /* Keep controls INSIDE video container with margins from all edges */
4006
+ bottom: 20px !important; /* 20px margin from video bottom */
4007
+ left: 16px !important; /* 16px margin from video left */
4008
+ right: 16px !important; /* 16px margin from video right */
4009
+ top: auto !important;
4010
+ background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.7) 60%, transparent 100%);
4011
+ padding: 12px 16px;
4012
+ border-radius: 12px;
4013
+ z-index: 1000;
4014
+ /* Ensure controls are visible and contained */
4015
+ opacity: 1 !important;
4016
+ visibility: visible !important;
4017
+ display: flex !important;
4018
+ flex-direction: column !important;
4019
+ /* Hardware acceleration */
4020
+ -webkit-transform: translate3d(0,0,0);
4021
+ transform: translate3d(0,0,0);
4022
+ /* CRITICAL: Prevent any overflow into black areas */
4023
+ max-height: calc(100% - 40px) !important; /* Leave 20px margin from top and bottom */
4024
+ max-width: calc(100% - 32px) !important; /* Leave 16px margin from left and right */
4025
+ box-sizing: border-box !important;
4026
+ /* Visual containment indicators */
4027
+ border: 1px solid rgba(255, 255, 255, 0.1);
4028
+ backdrop-filter: blur(10px);
4029
+ /* STRICT CSS containment with size to prevent overflow */
4030
+ contain: layout style paint size !important;
4031
+ /* Absolute overflow prevention */
4032
+ overflow: hidden !important;
4033
+ /* Force clip to container bounds */
4034
+ clip-path: inset(0) !important;
4035
+ }
4036
+
4037
+ /* Force controls and all child elements to stay within video container */
4038
+ .uvf-responsive-container .uvf-controls-bar {
4039
+ opacity: 1 !important;
4040
+ visibility: visible !important;
4041
+ transform: translateY(0) !important;
4042
+ pointer-events: auto !important;
4043
+ }
4044
+
4045
+ /* CRITICAL: Prevent ALL child elements from extending beyond controls container */
4046
+ .uvf-responsive-container .uvf-controls-bar *,
4047
+ .uvf-responsive-container .uvf-controls-bar *::before,
4048
+ .uvf-responsive-container .uvf-controls-bar *::after {
4049
+ max-width: 100% !important;
4050
+ max-height: 100% !important;
4051
+ overflow: hidden !important;
4052
+ box-sizing: border-box !important;
4053
+ position: relative !important;
4054
+ }
4055
+
4056
+ /* Ensure settings menu stays within video container bounds */
4057
+ .uvf-responsive-container .uvf-settings-menu {
4058
+ max-height: calc(50vh - 80px) !important; /* Video height minus controls margin */
4059
+ max-width: calc(100vw - 64px) !important; /* Video width minus side margins */
4060
+ overflow-y: auto !important;
4061
+ position: absolute !important;
4062
+ /* Keep menu within video boundaries */
4063
+ bottom: 60px !important;
4216
4064
  right: 0 !important;
4217
- padding: 16px 12px;
4218
- padding-bottom: calc(16px + var(--uvf-safe-area-bottom, 0px));
4219
- padding-left: calc(12px + var(--uvf-safe-area-left, 0px));
4220
- padding-right: calc(12px + var(--uvf-safe-area-right, 0px));
4221
- background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
4065
+ left: auto !important;
4066
+ top: auto !important;
4067
+ /* Ensure no child elements extend beyond container */
4068
+ contain: layout style paint;
4069
+ }
4070
+
4071
+ /* Ensure all child elements of controls stay within bounds */
4072
+ .uvf-responsive-container .uvf-controls-bar * {
4073
+ max-width: 100%;
4222
4074
  box-sizing: border-box;
4223
- z-index: 1000 !important;
4224
- /* iOS Safari specific fixes */
4225
- transform: translateZ(0);
4226
- -webkit-transform: translateZ(0);
4227
- will-change: transform;
4228
- /* Ensure proper stacking */
4229
- isolation: isolate;
4075
+ }
4076
+
4077
+ /* Progress section contained within controls */
4078
+ .uvf-progress-section {
4079
+ width: 100%;
4080
+ margin-bottom: 8px;
4081
+ opacity: 1 !important;
4082
+ visibility: visible !important;
4083
+ display: block !important;
4084
+ }
4085
+
4086
+ /* Progress bar styling */
4087
+ .uvf-progress-bar-wrapper {
4088
+ opacity: 1 !important;
4089
+ visibility: visible !important;
4090
+ }
4091
+
4092
+ .uvf-progress-bar {
4093
+ height: 4px;
4094
+ background: rgba(255, 255, 255, 0.3);
4095
+ border-radius: 2px;
4096
+ }
4097
+
4098
+ .uvf-progress-filled {
4099
+ background: var(--uvf-accent-1, #8B5CF6);
4100
+ height: 100%;
4101
+ border-radius: 2px;
4102
+ }
4103
+
4104
+ /* Controls row alignment - ensure visibility */
4105
+ .uvf-controls-row {
4106
+ width: 100%;
4107
+ display: flex !important;
4108
+ align-items: center;
4109
+ justify-content: flex-start;
4110
+ gap: 12px;
4111
+ opacity: 1 !important;
4112
+ visibility: visible !important;
4113
+ margin-top: 8px;
4114
+ }
4115
+
4116
+ /* Time display visibility */
4117
+ .uvf-time-display {
4118
+ color: #fff;
4119
+ font-size: 12px;
4120
+ font-weight: 500;
4121
+ opacity: 1 !important;
4122
+ visibility: visible !important;
4123
+ display: block !important;
4124
+ }
4125
+
4126
+ /* Control buttons visibility */
4127
+ .uvf-control-btn {
4128
+ min-width: 44px;
4129
+ min-height: 44px;
4130
+ display: flex !important;
4131
+ align-items: center;
4132
+ justify-content: center;
4133
+ border-radius: 50%;
4134
+ background: rgba(255, 255, 255, 0.1);
4135
+ backdrop-filter: blur(8px);
4136
+ color: #fff;
4137
+ opacity: 1 !important;
4138
+ visibility: visible !important;
4139
+ transition: all 0.2s ease;
4140
+ }
4141
+
4142
+ .uvf-control-btn:active {
4143
+ transform: scale(0.95);
4144
+ background: rgba(255, 255, 255, 0.2);
4145
+ }
4146
+
4147
+ /* Play/pause button prominence */
4148
+ .uvf-control-btn.play-pause {
4149
+ background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
4150
+ min-width: 52px;
4151
+ min-height: 52px;
4152
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
4153
+ }
4154
+
4155
+ .uvf-control-btn.play-pause:active {
4156
+ transform: scale(0.92);
4157
+ box-shadow: 0 1px 4px rgba(0,0,0,0.4);
4158
+ }
4159
+
4160
+ .uvf-control-btn svg {
4161
+ fill: #fff;
4162
+ opacity: 1;
4163
+ }
4164
+
4165
+ /* Right controls */
4166
+ .uvf-right-controls {
4167
+ margin-left: auto;
4168
+ display: flex !important;
4169
+ align-items: center;
4170
+ gap: 8px;
4171
+ opacity: 1 !important;
4172
+ visibility: visible !important;
4173
+ }
4174
+
4175
+ /* Center play button positioned within video */
4176
+ .uvf-center-play-container {
4177
+ position: absolute;
4178
+ top: 50%;
4179
+ left: 50%;
4180
+ transform: translate(-50%, -50%);
4181
+ z-index: 8;
4182
+ pointer-events: none;
4183
+ }
4184
+
4185
+ .uvf-center-play-btn {
4186
+ pointer-events: auto;
4187
+ }
4188
+
4189
+ /* Top controls within video */
4190
+ .uvf-top-controls {
4191
+ position: absolute;
4192
+ top: calc(12px + var(--uvf-safe-area-top));
4193
+ right: calc(16px + var(--uvf-safe-area-right));
4194
+ z-index: 9;
4195
+ }
4196
+
4197
+ /* Title bar within video */
4198
+ .uvf-title-bar {
4199
+ position: absolute;
4200
+ top: calc(12px + var(--uvf-safe-area-top));
4201
+ left: calc(16px + var(--uvf-safe-area-left));
4202
+ right: calc(80px + var(--uvf-safe-area-right));
4203
+ z-index: 9;
4204
+ padding: 8px 0;
4230
4205
  }
4231
4206
 
4232
4207
  .uvf-progress-section {
@@ -4607,69 +4582,55 @@ export class WebPlayer extends BasePlayer {
4607
4582
  }
4608
4583
  }
4609
4584
 
4610
- /* Mobile devices (landscape) - Fullscreen with controls inside video */
4585
+ /* Mobile devices (landscape) - Optimized for fullscreen viewing with safe areas */
4611
4586
  @media screen and (max-width: 767px) and (orientation: landscape) {
4612
4587
  .uvf-responsive-container {
4613
- position: fixed;
4614
- top: 0;
4615
- left: 0;
4616
4588
  width: 100vw !important;
4617
- height: 100vh !important;
4618
- height: 100dvh !important;
4619
- background: #000;
4620
- z-index: 9999;
4621
- display: block; /* Override portrait flexbox */
4589
+ height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4622
4590
  margin: 0;
4623
4591
  padding: 0;
4592
+ position: relative;
4624
4593
  overflow: hidden;
4625
4594
  }
4626
4595
 
4627
- /* Remove pseudo-elements in landscape */
4628
- .uvf-responsive-container::before,
4629
- .uvf-responsive-container::after {
4630
- display: none !important;
4596
+ @supports (height: 100dvh) {
4597
+ .uvf-responsive-container {
4598
+ height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4599
+ }
4631
4600
  }
4632
4601
 
4633
4602
  .uvf-responsive-container .uvf-player-wrapper {
4634
4603
  width: 100vw !important;
4635
- height: 100vh !important;
4636
- height: 100dvh !important;
4637
- position: relative;
4638
- display: block;
4604
+ height: 100% !important;
4605
+ min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4639
4606
  }
4640
4607
 
4641
- .uvf-responsive-container .uvf-video-container {
4642
- width: 100vw !important;
4643
- height: 100vh !important;
4644
- height: 100dvh !important;
4645
- position: relative;
4646
- background: #000;
4647
- overflow: hidden;
4608
+ @supports (height: 100dvh) {
4609
+ .uvf-responsive-container .uvf-player-wrapper {
4610
+ min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4611
+ }
4648
4612
  }
4649
4613
 
4650
- .uvf-responsive-container .uvf-video {
4651
- width: 100%;
4652
- height: 100%;
4653
- object-fit: contain;
4654
- background: #000;
4614
+ .uvf-responsive-container .uvf-video-container {
4615
+ width: 100vw !important;
4616
+ height: 100% !important;
4617
+ aspect-ratio: unset !important;
4618
+ min-height: inherit;
4655
4619
  }
4656
4620
 
4657
- /* Compact controls for landscape - positioned inside video container */
4621
+ /* Compact controls for landscape with safe area padding */
4658
4622
  .uvf-controls-bar {
4659
- position: absolute !important;
4660
- bottom: 0 !important;
4661
- left: 0 !important;
4662
- right: 0 !important;
4623
+ position: absolute;
4624
+ bottom: 0;
4625
+ left: 0;
4626
+ right: 0;
4663
4627
  padding: 10px 12px;
4664
4628
  padding-bottom: calc(10px + var(--uvf-safe-area-bottom));
4665
4629
  padding-left: calc(12px + var(--uvf-safe-area-left));
4666
4630
  padding-right: calc(12px + var(--uvf-safe-area-right));
4667
- background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
4631
+ background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
4668
4632
  box-sizing: border-box;
4669
4633
  z-index: 1000;
4670
- /* Ensure hardware acceleration */
4671
- -webkit-transform: translate3d(0,0,0);
4672
- transform: translate3d(0,0,0);
4673
4634
  }
4674
4635
 
4675
4636
  .uvf-progress-section {
@@ -4705,36 +4666,16 @@ export class WebPlayer extends BasePlayer {
4705
4666
  height: 22px;
4706
4667
  }
4707
4668
 
4708
- /* Compact top controls with safe area padding - inside video container */
4669
+ /* Compact top controls with safe area padding */
4709
4670
  .uvf-top-controls {
4710
- position: absolute;
4711
4671
  top: calc(8px + var(--uvf-safe-area-top));
4712
4672
  right: calc(12px + var(--uvf-safe-area-right));
4713
4673
  gap: 6px;
4714
- z-index: 9;
4715
- }
4716
-
4717
- /* Center play button positioned within video container */
4718
- .uvf-center-play-container {
4719
- position: absolute;
4720
- top: 50%;
4721
- left: 50%;
4722
- transform: translate(-50%, -50%);
4723
- z-index: 8;
4724
- pointer-events: none;
4725
- }
4726
-
4727
- .uvf-center-play-btn {
4728
- pointer-events: auto;
4729
4674
  }
4730
4675
 
4731
4676
  .uvf-title-bar {
4732
- position: absolute;
4733
- top: calc(8px + var(--uvf-safe-area-top));
4734
- left: calc(12px + var(--uvf-safe-area-left));
4735
- right: calc(80px + var(--uvf-safe-area-right));
4736
- z-index: 9;
4737
- padding: 8px 0;
4677
+ padding: 8px 12px;
4678
+ padding-top: calc(8px + var(--uvf-safe-area-top));
4738
4679
  padding-left: calc(12px + var(--uvf-safe-area-left));
4739
4680
  padding-right: calc(12px + var(--uvf-safe-area-right));
4740
4681
  }
@@ -4922,234 +4863,13 @@ export class WebPlayer extends BasePlayer {
4922
4863
 
4923
4864
  /* Large screens - Enhanced desktop experience */
4924
4865
  @media screen and (min-width: 1024px) {
4925
- /* Reset mobile portrait styles for desktop */
4926
4866
  .uvf-responsive-container {
4927
- display: block !important; /* Override mobile flexbox */
4928
- position: relative !important; /* Override mobile fixed */
4929
- height: auto !important; /* Override mobile viewport height */
4930
- background: transparent !important; /* Override mobile black background */
4931
4867
  padding: 10px;
4932
4868
  }
4933
4869
 
4934
- /* Remove mobile pseudo-elements on desktop */
4935
- .uvf-responsive-container::before,
4936
- .uvf-responsive-container::after {
4937
- display: none !important;
4938
- }
4939
-
4940
- /* Desktop player wrapper */
4941
- .uvf-responsive-container .uvf-player-wrapper {
4942
- width: 100% !important; /* Override mobile width */
4943
- height: auto !important; /* Override mobile height */
4944
- display: block !important; /* Override mobile flexbox */
4945
- position: relative !important;
4946
- max-width: none; /* Allow full width if needed */
4947
- }
4948
-
4949
- /* Desktop video container */
4950
- .uvf-responsive-container .uvf-video-container {
4951
- width: 100% !important;
4952
- height: auto !important;
4953
- position: relative;
4954
- aspect-ratio: 16/9; /* Maintain desktop aspect ratio */
4955
- background: #000;
4956
- }
4957
-
4958
- /* Desktop controls positioning */
4959
4870
  .uvf-controls-bar {
4960
- position: absolute !important;
4961
- bottom: 0 !important;
4962
- left: 0 !important;
4963
- right: 0 !important;
4964
4871
  padding: 20px;
4965
4872
  background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 60%, var(--uvf-overlay-transparent) 100%);
4966
- /* Reset mobile overrides for desktop */
4967
- opacity: 0; /* Default hidden state on desktop */
4968
- transform: translateY(10px); /* Default hidden position */
4969
- transition: all 0.3s ease;
4970
- }
4971
-
4972
- /* Desktop hover behavior */
4973
- .uvf-player-wrapper:hover .uvf-controls-bar,
4974
- .uvf-player-wrapper.controls-visible .uvf-controls-bar {
4975
- opacity: 1 !important;
4976
- transform: translateY(0) !important;
4977
- }
4978
-
4979
- /* Desktop progress section */
4980
- .uvf-progress-section {
4981
- margin-bottom: 15px;
4982
- width: 100%;
4983
- }
4984
-
4985
- /* Desktop controls row */
4986
- .uvf-controls-row {
4987
- display: flex;
4988
- align-items: center;
4989
- justify-content: flex-start;
4990
- gap: 14px;
4991
- width: 100%;
4992
- }
4993
-
4994
- /* Desktop control buttons */
4995
- .uvf-control-btn {
4996
- width: 40px;
4997
- height: 40px;
4998
- min-width: 40px;
4999
- min-height: 40px;
5000
- display: flex;
5001
- align-items: center;
5002
- justify-content: center;
5003
- border: none;
5004
- border-radius: 50%;
5005
- background: rgba(255, 255, 255, 0.1);
5006
- color: #fff;
5007
- cursor: pointer;
5008
- transition: all 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
5009
- backdrop-filter: blur(8px);
5010
- }
5011
-
5012
- .uvf-control-btn:hover {
5013
- transform: scale(1.1);
5014
- background: rgba(255, 255, 255, 0.2);
5015
- }
5016
-
5017
- .uvf-control-btn.play-pause {
5018
- width: 50px;
5019
- height: 50px;
5020
- min-width: 50px;
5021
- min-height: 50px;
5022
- background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
5023
- box-shadow: 0 2px 8px rgba(0,0,0,0.2);
5024
- }
5025
-
5026
- .uvf-control-btn.play-pause:hover {
5027
- transform: scale(1.08);
5028
- box-shadow: 0 4px 12px rgba(0,0,0,0.3);
5029
- }
5030
-
5031
- .uvf-control-btn svg {
5032
- width: 20px;
5033
- height: 20px;
5034
- fill: #fff;
5035
- }
5036
-
5037
- .uvf-control-btn.play-pause svg {
5038
- width: 24px;
5039
- height: 24px;
5040
- }
5041
-
5042
- /* Desktop right controls */
5043
- .uvf-right-controls {
5044
- margin-left: auto;
5045
- display: flex;
5046
- align-items: center;
5047
- gap: 8px;
5048
- }
5049
-
5050
- /* Desktop time display */
5051
- .uvf-time-display {
5052
- color: #fff;
5053
- font-size: 14px;
5054
- font-weight: 500;
5055
- padding: 0 10px;
5056
- }
5057
-
5058
- /* Desktop volume control */
5059
- .uvf-volume-panel {
5060
- display: flex !important; /* Show volume slider on desktop */
5061
- align-items: center;
5062
- gap: 8px;
5063
- }
5064
-
5065
- .uvf-volume-slider {
5066
- width: 80px;
5067
- height: 4px;
5068
- background: rgba(255, 255, 255, 0.3);
5069
- border-radius: 2px;
5070
- cursor: pointer;
5071
- }
5072
-
5073
- /* Desktop settings and other controls */
5074
- .uvf-quality-badge {
5075
- display: block;
5076
- background: rgba(255, 255, 255, 0.1);
5077
- color: #fff;
5078
- padding: 4px 8px;
5079
- border-radius: 4px;
5080
- font-size: 11px;
5081
- font-weight: 500;
5082
- }
5083
-
5084
- /* Desktop progress bar */
5085
- .uvf-progress-bar {
5086
- height: 2px;
5087
- background: rgba(255, 255, 255, 0.2);
5088
- border-radius: 4px;
5089
- cursor: pointer;
5090
- transition: height 0.2s ease;
5091
- }
5092
-
5093
- .uvf-progress-bar-wrapper:hover .uvf-progress-bar {
5094
- height: 4px;
5095
- }
5096
-
5097
- .uvf-progress-filled {
5098
- background: var(--uvf-accent-1, #8B5CF6);
5099
- height: 100%;
5100
- border-radius: 4px;
5101
- }
5102
-
5103
- .uvf-progress-handle {
5104
- width: 12px;
5105
- height: 12px;
5106
- background: #fff;
5107
- border-radius: 50%;
5108
- position: absolute;
5109
- top: 50%;
5110
- transform: translateY(-50%);
5111
- cursor: grab;
5112
- opacity: 0;
5113
- transition: opacity 0.2s ease;
5114
- }
5115
-
5116
- .uvf-progress-bar-wrapper:hover .uvf-progress-handle {
5117
- opacity: 1;
5118
- }
5119
-
5120
- /* Desktop center play button */
5121
- .uvf-center-play-container {
5122
- position: absolute;
5123
- top: 50%;
5124
- left: 50%;
5125
- transform: translate(-50%, -50%);
5126
- z-index: 8;
5127
- }
5128
-
5129
- .uvf-center-play-btn {
5130
- width: clamp(56px, 10vw, 72px);
5131
- height: clamp(56px, 10vw, 72px);
5132
- background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
5133
- border: none;
5134
- border-radius: 50%;
5135
- display: flex;
5136
- align-items: center;
5137
- justify-content: center;
5138
- cursor: pointer;
5139
- box-shadow: 0 4px 16px rgba(0,0,0,0.3);
5140
- transition: all 0.25s ease;
5141
- }
5142
-
5143
- .uvf-center-play-btn:hover {
5144
- transform: scale(1.1);
5145
- box-shadow: 0 6px 20px rgba(0,0,0,0.4);
5146
- }
5147
-
5148
- .uvf-center-play-btn svg {
5149
- width: clamp(24px, 4vw, 30px);
5150
- height: clamp(24px, 4vw, 30px);
5151
- fill: #fff;
5152
- margin-left: 2px;
5153
4873
  }
5154
4874
 
5155
4875
  .uvf-progress-section {
@@ -5906,8 +5626,15 @@ export class WebPlayer extends BasePlayer {
5906
5626
  <rect x="19" y="3" width="2" height="2"/>
5907
5627
  <path d="M17 1v2h2V1h2v2h1c.55 0 1 .45 1 1v16c0 .55-.45 1-1 1H2c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h1V1h2v2h12z" fill="none" stroke="currentColor" stroke-width="0.5"/>
5908
5628
  </svg>`;
5909
- epgBtn.style.display = 'none';
5910
- rightControls.appendChild(epgBtn);
5629
+ epgBtn.style.display = 'none !important';
5630
+ const epgConfig = this.config.epg;
5631
+ if (epgConfig && epgConfig.enabled) {
5632
+ rightControls.appendChild(epgBtn);
5633
+ this.debugLog('EPG button created but hidden - will show when EPG data is loaded');
5634
+ }
5635
+ else {
5636
+ this.debugLog('EPG button not created - EPG functionality disabled');
5637
+ }
5911
5638
  const pipBtn = document.createElement('button');
5912
5639
  pipBtn.className = 'uvf-control-btn';
5913
5640
  pipBtn.id = 'uvf-pip-btn';
@@ -7858,51 +7585,22 @@ export class WebPlayer extends BasePlayer {
7858
7585
  });
7859
7586
  settingsMenu.querySelectorAll('.speed-option').forEach(option => {
7860
7587
  option.addEventListener('click', (e) => {
7861
- e.preventDefault();
7862
- e.stopPropagation();
7863
7588
  const speed = parseFloat(e.target.dataset.speed || '1');
7864
- this.updateSettingsActiveStates('speed-option', e.target);
7865
7589
  this.setPlaybackRateFromSettings(speed);
7866
- const speedLabel = speed === 1 ? 'Normal' : `${speed}x`;
7867
- const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
7868
- if (accordionCurrent) {
7869
- accordionCurrent.textContent = speedLabel;
7870
- }
7871
- this.debugLog(`Speed selected: ${speed}x`);
7872
7590
  this.updateAccordionAfterSelection('speed');
7873
7591
  });
7874
7592
  });
7875
7593
  settingsMenu.querySelectorAll('.quality-option').forEach(option => {
7876
7594
  option.addEventListener('click', (e) => {
7877
- e.preventDefault();
7878
- e.stopPropagation();
7879
7595
  const quality = e.target.dataset.quality || 'auto';
7880
- this.updateSettingsActiveStates('quality-option', e.target);
7881
7596
  this.setQualityFromSettings(quality);
7882
- const qualityItem = this.availableQualities.find(q => q.value === quality);
7883
- const qualityLabel = qualityItem ? qualityItem.label : 'Auto';
7884
- const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
7885
- if (accordionCurrent) {
7886
- accordionCurrent.textContent = qualityLabel;
7887
- }
7888
- this.debugLog(`Quality selected: ${quality} (${qualityLabel})`);
7889
7597
  this.updateAccordionAfterSelection('quality');
7890
7598
  });
7891
7599
  });
7892
7600
  settingsMenu.querySelectorAll('.subtitle-option').forEach(option => {
7893
7601
  option.addEventListener('click', (e) => {
7894
- e.preventDefault();
7895
- e.stopPropagation();
7896
7602
  const subtitle = e.target.dataset.subtitle || 'off';
7897
- this.updateSettingsActiveStates('subtitle-option', e.target);
7898
7603
  this.setSubtitle(subtitle);
7899
- const subtitleItem = this.availableSubtitles.find(s => s.value === subtitle);
7900
- const subtitleLabel = subtitleItem ? subtitleItem.label : 'Off';
7901
- const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
7902
- if (accordionCurrent) {
7903
- accordionCurrent.textContent = subtitleLabel;
7904
- }
7905
- this.debugLog(`Subtitle selected: ${subtitle} (${subtitleLabel})`);
7906
7604
  this.updateAccordionAfterSelection('subtitles');
7907
7605
  });
7908
7606
  });
@@ -7935,19 +7633,10 @@ export class WebPlayer extends BasePlayer {
7935
7633
  this.debugLog('Settings menu hidden via hideSettingsMenu()');
7936
7634
  }
7937
7635
  updateAccordionAfterSelection(section) {
7938
- const settingsMenu = document.getElementById('uvf-settings-menu');
7939
- if (settingsMenu) {
7940
- settingsMenu.querySelectorAll('.uvf-accordion-item.expanded').forEach(item => {
7941
- item.classList.remove('expanded');
7942
- });
7943
- }
7944
7636
  setTimeout(() => {
7945
7637
  this.generateAccordionMenu();
7946
7638
  this.setupSettingsEventListeners();
7947
- }, 50);
7948
- setTimeout(() => {
7949
- this.hideSettingsMenu();
7950
- }, 150);
7639
+ }, 100);
7951
7640
  }
7952
7641
  updateSettingsActiveStates(className, activeElement) {
7953
7642
  const settingsMenu = document.getElementById('uvf-settings-menu');
@@ -8425,8 +8114,8 @@ export class WebPlayer extends BasePlayer {
8425
8114
  showEPGButton() {
8426
8115
  const epgBtn = document.getElementById('uvf-epg-btn');
8427
8116
  if (epgBtn) {
8428
- epgBtn.style.display = 'block';
8429
- this.debugLog('EPG button shown');
8117
+ epgBtn.style.setProperty('display', 'block', 'important');
8118
+ this.debugLog('EPG button shown with !important override');
8430
8119
  }
8431
8120
  else {
8432
8121
  this.debugLog('EPG button not found in DOM');
@@ -8435,8 +8124,8 @@ export class WebPlayer extends BasePlayer {
8435
8124
  hideEPGButton() {
8436
8125
  const epgBtn = document.getElementById('uvf-epg-btn');
8437
8126
  if (epgBtn) {
8438
- epgBtn.style.display = 'none';
8439
- this.debugLog('EPG button hidden');
8127
+ epgBtn.style.setProperty('display', 'none', 'important');
8128
+ this.debugLog('EPG button hidden with !important');
8440
8129
  }
8441
8130
  }
8442
8131
  setEPGData(epgData) {
@@ -8452,7 +8141,26 @@ export class WebPlayer extends BasePlayer {
8452
8141
  }
8453
8142
  isEPGButtonVisible() {
8454
8143
  const epgBtn = document.getElementById('uvf-epg-btn');
8455
- return epgBtn ? epgBtn.style.display !== 'none' : false;
8144
+ if (epgBtn) {
8145
+ const isVisible = epgBtn.style.display !== 'none';
8146
+ this.debugLog(`EPG button visibility check: ${isVisible}, display style: ${epgBtn.style.display}`);
8147
+ return isVisible;
8148
+ }
8149
+ this.debugLog('EPG button visibility check: false (button not found in DOM)');
8150
+ return false;
8151
+ }
8152
+ debugEPGState() {
8153
+ const epgBtn = document.getElementById('uvf-epg-btn');
8154
+ const epgConfig = this.config.epg;
8155
+ this.debugLog('=== EPG DEBUG STATE ===');
8156
+ this.debugLog(`EPG Config Enabled: ${epgConfig?.enabled || false}`);
8157
+ this.debugLog(`EPG Button Exists: ${!!epgBtn}`);
8158
+ if (epgBtn) {
8159
+ this.debugLog(`EPG Button Display Style: ${epgBtn.style.display}`);
8160
+ this.debugLog(`EPG Button Computed Display: ${window.getComputedStyle(epgBtn).display}`);
8161
+ this.debugLog(`EPG Button Visible: ${this.isEPGButtonVisible()}`);
8162
+ }
8163
+ this.debugLog('=====================');
8456
8164
  }
8457
8165
  async cleanup() {
8458
8166
  if (this.hls) {