unified-video-framework 1.4.162 → 1.4.163

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.
@@ -4329,217 +4329,6 @@ export class WebPlayer extends BasePlayer {
4329
4329
  @media screen and (max-width: 767px) {
4330
4330
  html, body {
4331
4331
  overflow-x: hidden;
4332
- background: #000;
4333
- }
4334
-
4335
- /* Mobile Portrait Layout - Centered Player with Top/Bottom Black Areas */
4336
- @media screen and (orientation: portrait) {
4337
- .uvf-responsive-container {
4338
- display: flex;
4339
- flex-direction: column;
4340
- height: 100vh;
4341
- height: 100dvh;
4342
- background: #000;
4343
- overflow: hidden;
4344
- position: fixed;
4345
- top: 0;
4346
- left: 0;
4347
- width: 100vw;
4348
- }
4349
-
4350
- /* Top black area - 25% of viewport */
4351
- .uvf-responsive-container::before {
4352
- content: '';
4353
- flex: 0 0 25vh;
4354
- background: #000;
4355
- pointer-events: none;
4356
- }
4357
-
4358
- /* Bottom black area - 25% of viewport */
4359
- .uvf-responsive-container::after {
4360
- content: '';
4361
- flex: 0 0 25vh;
4362
- background: #000;
4363
- pointer-events: none;
4364
- }
4365
-
4366
- /* Centered video player wrapper - 50% of viewport */
4367
- .uvf-responsive-container .uvf-player-wrapper {
4368
- flex: 1;
4369
- width: 100vw;
4370
- display: flex;
4371
- align-items: center;
4372
- justify-content: center;
4373
- background: #000;
4374
- position: relative;
4375
- }
4376
-
4377
- /* Video container fills player wrapper */
4378
- .uvf-responsive-container .uvf-video-container {
4379
- width: 100%;
4380
- height: 100%;
4381
- position: relative;
4382
- background: #000;
4383
- border-radius: 0;
4384
- overflow: hidden;
4385
- }
4386
-
4387
- /* Video element fills container */
4388
- .uvf-responsive-container .uvf-video {
4389
- width: 100%;
4390
- height: 100%;
4391
- object-fit: contain;
4392
- background: #000;
4393
- }
4394
-
4395
- /* All controls positioned inside video container */
4396
- .uvf-controls-bar {
4397
- position: absolute !important;
4398
- bottom: 0 !important;
4399
- left: 0 !important;
4400
- right: 0 !important;
4401
- background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
4402
- padding: 12px 16px;
4403
- padding-bottom: calc(12px + var(--uvf-safe-area-bottom));
4404
- z-index: 1000;
4405
- /* Ensure controls are always visible */
4406
- opacity: 1 !important;
4407
- visibility: visible !important;
4408
- display: flex !important;
4409
- flex-direction: column !important;
4410
- /* Ensure hardware acceleration */
4411
- -webkit-transform: translate3d(0,0,0);
4412
- transform: translate3d(0,0,0);
4413
- }
4414
-
4415
- /* Force controls visibility on mobile portrait */
4416
- .uvf-responsive-container .uvf-controls-bar {
4417
- opacity: 1 !important;
4418
- visibility: visible !important;
4419
- transform: translateY(0) !important;
4420
- pointer-events: auto !important;
4421
- }
4422
-
4423
- /* Progress section - ensure visibility */
4424
- .uvf-progress-section {
4425
- width: 100%;
4426
- margin-bottom: 8px;
4427
- opacity: 1 !important;
4428
- visibility: visible !important;
4429
- display: block !important;
4430
- }
4431
-
4432
- /* Progress bar styling */
4433
- .uvf-progress-bar-wrapper {
4434
- opacity: 1 !important;
4435
- visibility: visible !important;
4436
- }
4437
-
4438
- .uvf-progress-bar {
4439
- height: 4px;
4440
- background: rgba(255, 255, 255, 0.3);
4441
- border-radius: 2px;
4442
- }
4443
-
4444
- .uvf-progress-filled {
4445
- background: var(--uvf-accent-1, #8B5CF6);
4446
- height: 100%;
4447
- border-radius: 2px;
4448
- }
4449
-
4450
- /* Controls row alignment - ensure visibility */
4451
- .uvf-controls-row {
4452
- width: 100%;
4453
- display: flex !important;
4454
- align-items: center;
4455
- justify-content: flex-start;
4456
- gap: 12px;
4457
- opacity: 1 !important;
4458
- visibility: visible !important;
4459
- margin-top: 8px;
4460
- }
4461
-
4462
- /* Time display visibility */
4463
- .uvf-time-display {
4464
- color: #fff;
4465
- font-size: 12px;
4466
- font-weight: 500;
4467
- opacity: 1 !important;
4468
- visibility: visible !important;
4469
- display: block !important;
4470
- }
4471
-
4472
- /* Control buttons visibility */
4473
- .uvf-control-btn {
4474
- opacity: 1 !important;
4475
- visibility: visible !important;
4476
- display: flex !important;
4477
- color: #fff;
4478
- }
4479
-
4480
- .uvf-control-btn svg {
4481
- fill: #fff;
4482
- opacity: 1;
4483
- }
4484
-
4485
- /* Right controls - ensure visibility */
4486
- .uvf-right-controls {
4487
- margin-left: auto;
4488
- display: flex !important;
4489
- align-items: center;
4490
- gap: 8px;
4491
- opacity: 1 !important;
4492
- visibility: visible !important;
4493
- }
4494
-
4495
- /* Force controls to be always visible in portrait mode */
4496
- .uvf-responsive-container .uvf-player-wrapper.uvf-controls-visible .uvf-controls-bar,
4497
- .uvf-responsive-container .uvf-player-wrapper:hover .uvf-controls-bar,
4498
- .uvf-responsive-container .uvf-controls-bar {
4499
- opacity: 1 !important;
4500
- transform: translateY(0) !important;
4501
- visibility: visible !important;
4502
- display: flex !important;
4503
- pointer-events: auto !important;
4504
- }
4505
-
4506
- /* Ensure all child elements are visible */
4507
- .uvf-responsive-container .uvf-controls-bar * {
4508
- opacity: 1 !important;
4509
- visibility: visible !important;
4510
- }
4511
-
4512
- /* Center play button positioned within video */
4513
- .uvf-center-play-container {
4514
- position: absolute;
4515
- top: 50%;
4516
- left: 50%;
4517
- transform: translate(-50%, -50%);
4518
- z-index: 8;
4519
- pointer-events: none;
4520
- }
4521
-
4522
- .uvf-center-play-btn {
4523
- pointer-events: auto;
4524
- }
4525
-
4526
- /* Top controls within video */
4527
- .uvf-top-controls {
4528
- position: absolute;
4529
- top: calc(12px + var(--uvf-safe-area-top));
4530
- right: calc(16px + var(--uvf-safe-area-right));
4531
- z-index: 9;
4532
- }
4533
-
4534
- /* Title bar within video */
4535
- .uvf-title-bar {
4536
- position: absolute;
4537
- top: calc(12px + var(--uvf-safe-area-top));
4538
- left: calc(16px + var(--uvf-safe-area-left));
4539
- right: calc(80px + var(--uvf-safe-area-right));
4540
- z-index: 9;
4541
- padding: 8px 0;
4542
- }
4543
4332
  }
4544
4333
 
4545
4334
  .uvf-player-wrapper {
@@ -4563,37 +4352,6 @@ export class WebPlayer extends BasePlayer {
4563
4352
  transform: translateZ(0);
4564
4353
  }
4565
4354
 
4566
- /* Mobile controls optimization for touch */
4567
- .uvf-control-btn {
4568
- min-width: 44px;
4569
- min-height: 44px;
4570
- display: flex;
4571
- align-items: center;
4572
- justify-content: center;
4573
- border-radius: 50%;
4574
- transition: all 0.2s ease;
4575
- background: rgba(255, 255, 255, 0.1);
4576
- backdrop-filter: blur(8px);
4577
- }
4578
-
4579
- .uvf-control-btn:active {
4580
- transform: scale(0.95);
4581
- background: rgba(255, 255, 255, 0.2);
4582
- }
4583
-
4584
- /* Play/pause button prominence */
4585
- .uvf-control-btn.play-pause {
4586
- background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
4587
- min-width: 52px;
4588
- min-height: 52px;
4589
- box-shadow: 0 2px 8px rgba(0,0,0,0.3);
4590
- }
4591
-
4592
- .uvf-control-btn.play-pause:active {
4593
- transform: scale(0.92);
4594
- box-shadow: 0 1px 4px rgba(0,0,0,0.4);
4595
- }
4596
-
4597
4355
  /* Fix for controls being cut off by virtual keyboard */
4598
4356
  .uvf-controls-bar {
4599
4357
  position: absolute !important;
@@ -4640,61 +4398,244 @@ export class WebPlayer extends BasePlayer {
4640
4398
  }
4641
4399
 
4642
4400
  /* Enhanced Responsive Media Queries with UX Best Practices */
4643
- /* Mobile devices (portrait) - Enhanced UX with Safe Areas */
4401
+ /* Mobile Portrait Layout - CENTERED PLAYER with TOP/BOTTOM BLACK AREAS */
4644
4402
  @media screen and (max-width: 767px) and (orientation: portrait) {
4403
+ /* CENTERED LAYOUT: 25% top black + 50% player + 25% bottom black */
4645
4404
  .uvf-responsive-container {
4405
+ display: flex;
4406
+ flex-direction: column;
4407
+ height: 100vh;
4408
+ height: 100dvh;
4409
+ background: #000;
4410
+ overflow: hidden;
4411
+ position: fixed;
4412
+ top: 0;
4413
+ left: 0;
4414
+ width: 100vw;
4646
4415
  padding: 0;
4647
- width: 100vw !important;
4648
- height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4649
4416
  margin: 0;
4650
- position: relative;
4651
- overflow: hidden;
4652
4417
  }
4653
4418
 
4654
- @supports (height: 100dvh) {
4655
- .uvf-responsive-container {
4656
- height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4657
- }
4419
+ /* TOP BLACK AREA - 25% of viewport - COMPLETELY EMPTY */
4420
+ .uvf-responsive-container::before {
4421
+ content: '';
4422
+ flex: 0 0 25vh;
4423
+ background: #000;
4424
+ pointer-events: none;
4658
4425
  }
4659
4426
 
4660
- .uvf-responsive-container .uvf-player-wrapper {
4661
- width: 100vw !important;
4662
- height: 100% !important;
4663
- min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4427
+ /* BOTTOM BLACK AREA - 25% of viewport - COMPLETELY EMPTY */
4428
+ .uvf-responsive-container::after {
4429
+ content: '';
4430
+ flex: 0 0 25vh;
4431
+ background: #000;
4432
+ pointer-events: none;
4664
4433
  }
4665
4434
 
4666
- @supports (height: 100dvh) {
4667
- .uvf-responsive-container .uvf-player-wrapper {
4668
- min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4669
- }
4435
+ /* CENTERED VIDEO PLAYER WRAPPER - 50% of viewport */
4436
+ .uvf-responsive-container .uvf-player-wrapper {
4437
+ flex: 1; /* Takes remaining 50% */
4438
+ width: 100vw;
4439
+ display: flex;
4440
+ align-items: center;
4441
+ justify-content: center;
4442
+ background: #000;
4443
+ position: relative;
4444
+ overflow: hidden; /* CRITICAL: Ensure nothing extends beyond this area */
4670
4445
  }
4671
4446
 
4447
+ /* Video container fills player wrapper */
4672
4448
  .uvf-responsive-container .uvf-video-container {
4673
- width: 100vw !important;
4674
- height: 100% !important;
4675
- aspect-ratio: unset !important;
4676
- min-height: inherit;
4449
+ width: 100%;
4450
+ height: 100%;
4451
+ position: relative;
4452
+ background: #000;
4453
+ border-radius: 0;
4454
+ overflow: hidden;
4455
+ }
4456
+
4457
+ /* Video element fills container */
4458
+ .uvf-responsive-container .uvf-video {
4459
+ width: 100%;
4460
+ height: 100%;
4461
+ object-fit: contain;
4462
+ background: #000;
4677
4463
  }
4678
4464
 
4679
- /* Enhanced mobile controls bar with safe area padding - iOS Safari specific fixes */
4465
+ /* CONTROLS STRICTLY CONTAINED WITHIN VIDEO AREA - NEVER EXTEND TO BLACK AREAS */
4680
4466
  .uvf-controls-bar {
4681
4467
  position: absolute !important;
4682
- bottom: 0 !important;
4683
- left: 0 !important;
4684
- right: 0 !important;
4685
- padding: 16px 12px;
4686
- padding-bottom: calc(16px + var(--uvf-safe-area-bottom, 0px));
4687
- padding-left: calc(12px + var(--uvf-safe-area-left, 0px));
4688
- padding-right: calc(12px + var(--uvf-safe-area-right, 0px));
4689
- background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
4468
+ /* Keep controls INSIDE video container with margins from all edges */
4469
+ bottom: 20px !important; /* 20px margin from video bottom */
4470
+ left: 16px !important; /* 16px margin from video left */
4471
+ right: 16px !important; /* 16px margin from video right */
4472
+ top: auto !important;
4473
+ background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.7) 60%, transparent 100%);
4474
+ padding: 12px 16px;
4475
+ border-radius: 12px;
4476
+ z-index: 1000;
4477
+ /* Ensure controls are visible and contained */
4478
+ opacity: 1 !important;
4479
+ visibility: visible !important;
4480
+ display: flex !important;
4481
+ flex-direction: column !important;
4482
+ /* Hardware acceleration */
4483
+ -webkit-transform: translate3d(0,0,0);
4484
+ transform: translate3d(0,0,0);
4485
+ /* CRITICAL: Prevent any overflow into black areas */
4486
+ max-height: calc(100% - 40px); /* Leave 20px margin from top and bottom */
4487
+ max-width: calc(100% - 32px); /* Leave 16px margin from left and right */
4690
4488
  box-sizing: border-box;
4691
- z-index: 1000 !important;
4692
- /* iOS Safari specific fixes */
4693
- transform: translateZ(0);
4694
- -webkit-transform: translateZ(0);
4695
- will-change: transform;
4696
- /* Ensure proper stacking */
4697
- isolation: isolate;
4489
+ /* Visual containment indicators */
4490
+ border: 1px solid rgba(255, 255, 255, 0.1);
4491
+ backdrop-filter: blur(10px);
4492
+ contain: layout style paint; /* CSS containment */
4493
+ }
4494
+
4495
+ /* Force controls and all child elements to stay within video container */
4496
+ .uvf-responsive-container .uvf-controls-bar {
4497
+ opacity: 1 !important;
4498
+ visibility: visible !important;
4499
+ transform: translateY(0) !important;
4500
+ pointer-events: auto !important;
4501
+ /* Ensure no child elements extend beyond container */
4502
+ contain: layout style paint;
4503
+ }
4504
+
4505
+ /* Ensure all child elements of controls stay within bounds */
4506
+ .uvf-responsive-container .uvf-controls-bar * {
4507
+ max-width: 100%;
4508
+ box-sizing: border-box;
4509
+ }
4510
+
4511
+ /* Progress section contained within controls */
4512
+ .uvf-progress-section {
4513
+ width: 100%;
4514
+ margin-bottom: 8px;
4515
+ opacity: 1 !important;
4516
+ visibility: visible !important;
4517
+ display: block !important;
4518
+ }
4519
+
4520
+ /* Progress bar styling */
4521
+ .uvf-progress-bar-wrapper {
4522
+ opacity: 1 !important;
4523
+ visibility: visible !important;
4524
+ }
4525
+
4526
+ .uvf-progress-bar {
4527
+ height: 4px;
4528
+ background: rgba(255, 255, 255, 0.3);
4529
+ border-radius: 2px;
4530
+ }
4531
+
4532
+ .uvf-progress-filled {
4533
+ background: var(--uvf-accent-1, #8B5CF6);
4534
+ height: 100%;
4535
+ border-radius: 2px;
4536
+ }
4537
+
4538
+ /* Controls row alignment - ensure visibility */
4539
+ .uvf-controls-row {
4540
+ width: 100%;
4541
+ display: flex !important;
4542
+ align-items: center;
4543
+ justify-content: flex-start;
4544
+ gap: 12px;
4545
+ opacity: 1 !important;
4546
+ visibility: visible !important;
4547
+ margin-top: 8px;
4548
+ }
4549
+
4550
+ /* Time display visibility */
4551
+ .uvf-time-display {
4552
+ color: #fff;
4553
+ font-size: 12px;
4554
+ font-weight: 500;
4555
+ opacity: 1 !important;
4556
+ visibility: visible !important;
4557
+ display: block !important;
4558
+ }
4559
+
4560
+ /* Control buttons visibility */
4561
+ .uvf-control-btn {
4562
+ min-width: 44px;
4563
+ min-height: 44px;
4564
+ display: flex !important;
4565
+ align-items: center;
4566
+ justify-content: center;
4567
+ border-radius: 50%;
4568
+ background: rgba(255, 255, 255, 0.1);
4569
+ backdrop-filter: blur(8px);
4570
+ color: #fff;
4571
+ opacity: 1 !important;
4572
+ visibility: visible !important;
4573
+ transition: all 0.2s ease;
4574
+ }
4575
+
4576
+ .uvf-control-btn:active {
4577
+ transform: scale(0.95);
4578
+ background: rgba(255, 255, 255, 0.2);
4579
+ }
4580
+
4581
+ /* Play/pause button prominence */
4582
+ .uvf-control-btn.play-pause {
4583
+ background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
4584
+ min-width: 52px;
4585
+ min-height: 52px;
4586
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
4587
+ }
4588
+
4589
+ .uvf-control-btn.play-pause:active {
4590
+ transform: scale(0.92);
4591
+ box-shadow: 0 1px 4px rgba(0,0,0,0.4);
4592
+ }
4593
+
4594
+ .uvf-control-btn svg {
4595
+ fill: #fff;
4596
+ opacity: 1;
4597
+ }
4598
+
4599
+ /* Right controls */
4600
+ .uvf-right-controls {
4601
+ margin-left: auto;
4602
+ display: flex !important;
4603
+ align-items: center;
4604
+ gap: 8px;
4605
+ opacity: 1 !important;
4606
+ visibility: visible !important;
4607
+ }
4608
+
4609
+ /* Center play button positioned within video */
4610
+ .uvf-center-play-container {
4611
+ position: absolute;
4612
+ top: 50%;
4613
+ left: 50%;
4614
+ transform: translate(-50%, -50%);
4615
+ z-index: 8;
4616
+ pointer-events: none;
4617
+ }
4618
+
4619
+ .uvf-center-play-btn {
4620
+ pointer-events: auto;
4621
+ }
4622
+
4623
+ /* Top controls within video */
4624
+ .uvf-top-controls {
4625
+ position: absolute;
4626
+ top: calc(12px + var(--uvf-safe-area-top));
4627
+ right: calc(16px + var(--uvf-safe-area-right));
4628
+ z-index: 9;
4629
+ }
4630
+
4631
+ /* Title bar within video */
4632
+ .uvf-title-bar {
4633
+ position: absolute;
4634
+ top: calc(12px + var(--uvf-safe-area-top));
4635
+ left: calc(16px + var(--uvf-safe-area-left));
4636
+ right: calc(80px + var(--uvf-safe-area-right));
4637
+ z-index: 9;
4638
+ padding: 8px 0;
4698
4639
  }
4699
4640
 
4700
4641
  .uvf-progress-section {
@@ -5075,69 +5016,55 @@ export class WebPlayer extends BasePlayer {
5075
5016
  }
5076
5017
  }
5077
5018
 
5078
- /* Mobile devices (landscape) - Fullscreen with controls inside video */
5019
+ /* Mobile devices (landscape) - Optimized for fullscreen viewing with safe areas */
5079
5020
  @media screen and (max-width: 767px) and (orientation: landscape) {
5080
5021
  .uvf-responsive-container {
5081
- position: fixed;
5082
- top: 0;
5083
- left: 0;
5084
5022
  width: 100vw !important;
5085
- height: 100vh !important;
5086
- height: 100dvh !important;
5087
- background: #000;
5088
- z-index: 9999;
5089
- display: block; /* Override portrait flexbox */
5023
+ height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
5090
5024
  margin: 0;
5091
5025
  padding: 0;
5026
+ position: relative;
5092
5027
  overflow: hidden;
5093
5028
  }
5094
5029
 
5095
- /* Remove pseudo-elements in landscape */
5096
- .uvf-responsive-container::before,
5097
- .uvf-responsive-container::after {
5098
- display: none !important;
5030
+ @supports (height: 100dvh) {
5031
+ .uvf-responsive-container {
5032
+ height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
5033
+ }
5099
5034
  }
5100
5035
 
5101
5036
  .uvf-responsive-container .uvf-player-wrapper {
5102
5037
  width: 100vw !important;
5103
- height: 100vh !important;
5104
- height: 100dvh !important;
5105
- position: relative;
5106
- display: block;
5038
+ height: 100% !important;
5039
+ min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
5040
+ }
5041
+
5042
+ @supports (height: 100dvh) {
5043
+ .uvf-responsive-container .uvf-player-wrapper {
5044
+ min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
5045
+ }
5107
5046
  }
5108
5047
 
5109
5048
  .uvf-responsive-container .uvf-video-container {
5110
5049
  width: 100vw !important;
5111
- height: 100vh !important;
5112
- height: 100dvh !important;
5113
- position: relative;
5114
- background: #000;
5115
- overflow: hidden;
5116
- }
5117
-
5118
- .uvf-responsive-container .uvf-video {
5119
- width: 100%;
5120
- height: 100%;
5121
- object-fit: contain;
5122
- background: #000;
5050
+ height: 100% !important;
5051
+ aspect-ratio: unset !important;
5052
+ min-height: inherit;
5123
5053
  }
5124
5054
 
5125
- /* Compact controls for landscape - positioned inside video container */
5055
+ /* Compact controls for landscape with safe area padding */
5126
5056
  .uvf-controls-bar {
5127
- position: absolute !important;
5128
- bottom: 0 !important;
5129
- left: 0 !important;
5130
- right: 0 !important;
5057
+ position: absolute;
5058
+ bottom: 0;
5059
+ left: 0;
5060
+ right: 0;
5131
5061
  padding: 10px 12px;
5132
5062
  padding-bottom: calc(10px + var(--uvf-safe-area-bottom));
5133
5063
  padding-left: calc(12px + var(--uvf-safe-area-left));
5134
5064
  padding-right: calc(12px + var(--uvf-safe-area-right));
5135
- background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
5065
+ background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
5136
5066
  box-sizing: border-box;
5137
5067
  z-index: 1000;
5138
- /* Ensure hardware acceleration */
5139
- -webkit-transform: translate3d(0,0,0);
5140
- transform: translate3d(0,0,0);
5141
5068
  }
5142
5069
 
5143
5070
  .uvf-progress-section {
@@ -5173,36 +5100,16 @@ export class WebPlayer extends BasePlayer {
5173
5100
  height: 22px;
5174
5101
  }
5175
5102
 
5176
- /* Compact top controls with safe area padding - inside video container */
5103
+ /* Compact top controls with safe area padding */
5177
5104
  .uvf-top-controls {
5178
- position: absolute;
5179
5105
  top: calc(8px + var(--uvf-safe-area-top));
5180
5106
  right: calc(12px + var(--uvf-safe-area-right));
5181
5107
  gap: 6px;
5182
- z-index: 9;
5183
- }
5184
-
5185
- /* Center play button positioned within video container */
5186
- .uvf-center-play-container {
5187
- position: absolute;
5188
- top: 50%;
5189
- left: 50%;
5190
- transform: translate(-50%, -50%);
5191
- z-index: 8;
5192
- pointer-events: none;
5193
- }
5194
-
5195
- .uvf-center-play-btn {
5196
- pointer-events: auto;
5197
5108
  }
5198
5109
 
5199
5110
  .uvf-title-bar {
5200
- position: absolute;
5201
- top: calc(8px + var(--uvf-safe-area-top));
5202
- left: calc(12px + var(--uvf-safe-area-left));
5203
- right: calc(80px + var(--uvf-safe-area-right));
5204
- z-index: 9;
5205
- padding: 8px 0;
5111
+ padding: 8px 12px;
5112
+ padding-top: calc(8px + var(--uvf-safe-area-top));
5206
5113
  padding-left: calc(12px + var(--uvf-safe-area-left));
5207
5114
  padding-right: calc(12px + var(--uvf-safe-area-right));
5208
5115
  }
@@ -5390,234 +5297,13 @@ export class WebPlayer extends BasePlayer {
5390
5297
 
5391
5298
  /* Large screens - Enhanced desktop experience */
5392
5299
  @media screen and (min-width: 1024px) {
5393
- /* Reset mobile portrait styles for desktop */
5394
5300
  .uvf-responsive-container {
5395
- display: block !important; /* Override mobile flexbox */
5396
- position: relative !important; /* Override mobile fixed */
5397
- height: auto !important; /* Override mobile viewport height */
5398
- background: transparent !important; /* Override mobile black background */
5399
5301
  padding: 10px;
5400
5302
  }
5401
5303
 
5402
- /* Remove mobile pseudo-elements on desktop */
5403
- .uvf-responsive-container::before,
5404
- .uvf-responsive-container::after {
5405
- display: none !important;
5406
- }
5407
-
5408
- /* Desktop player wrapper */
5409
- .uvf-responsive-container .uvf-player-wrapper {
5410
- width: 100% !important; /* Override mobile width */
5411
- height: auto !important; /* Override mobile height */
5412
- display: block !important; /* Override mobile flexbox */
5413
- position: relative !important;
5414
- max-width: none; /* Allow full width if needed */
5415
- }
5416
-
5417
- /* Desktop video container */
5418
- .uvf-responsive-container .uvf-video-container {
5419
- width: 100% !important;
5420
- height: auto !important;
5421
- position: relative;
5422
- aspect-ratio: 16/9; /* Maintain desktop aspect ratio */
5423
- background: #000;
5424
- }
5425
-
5426
- /* Desktop controls positioning */
5427
5304
  .uvf-controls-bar {
5428
- position: absolute !important;
5429
- bottom: 0 !important;
5430
- left: 0 !important;
5431
- right: 0 !important;
5432
5305
  padding: 20px;
5433
5306
  background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 60%, var(--uvf-overlay-transparent) 100%);
5434
- /* Reset mobile overrides for desktop */
5435
- opacity: 0; /* Default hidden state on desktop */
5436
- transform: translateY(10px); /* Default hidden position */
5437
- transition: all 0.3s ease;
5438
- }
5439
-
5440
- /* Desktop hover behavior */
5441
- .uvf-player-wrapper:hover .uvf-controls-bar,
5442
- .uvf-player-wrapper.controls-visible .uvf-controls-bar {
5443
- opacity: 1 !important;
5444
- transform: translateY(0) !important;
5445
- }
5446
-
5447
- /* Desktop progress section */
5448
- .uvf-progress-section {
5449
- margin-bottom: 15px;
5450
- width: 100%;
5451
- }
5452
-
5453
- /* Desktop controls row */
5454
- .uvf-controls-row {
5455
- display: flex;
5456
- align-items: center;
5457
- justify-content: flex-start;
5458
- gap: 14px;
5459
- width: 100%;
5460
- }
5461
-
5462
- /* Desktop control buttons */
5463
- .uvf-control-btn {
5464
- width: 40px;
5465
- height: 40px;
5466
- min-width: 40px;
5467
- min-height: 40px;
5468
- display: flex;
5469
- align-items: center;
5470
- justify-content: center;
5471
- border: none;
5472
- border-radius: 50%;
5473
- background: rgba(255, 255, 255, 0.1);
5474
- color: #fff;
5475
- cursor: pointer;
5476
- transition: all 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
5477
- backdrop-filter: blur(8px);
5478
- }
5479
-
5480
- .uvf-control-btn:hover {
5481
- transform: scale(1.1);
5482
- background: rgba(255, 255, 255, 0.2);
5483
- }
5484
-
5485
- .uvf-control-btn.play-pause {
5486
- width: 50px;
5487
- height: 50px;
5488
- min-width: 50px;
5489
- min-height: 50px;
5490
- background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
5491
- box-shadow: 0 2px 8px rgba(0,0,0,0.2);
5492
- }
5493
-
5494
- .uvf-control-btn.play-pause:hover {
5495
- transform: scale(1.08);
5496
- box-shadow: 0 4px 12px rgba(0,0,0,0.3);
5497
- }
5498
-
5499
- .uvf-control-btn svg {
5500
- width: 20px;
5501
- height: 20px;
5502
- fill: #fff;
5503
- }
5504
-
5505
- .uvf-control-btn.play-pause svg {
5506
- width: 24px;
5507
- height: 24px;
5508
- }
5509
-
5510
- /* Desktop right controls */
5511
- .uvf-right-controls {
5512
- margin-left: auto;
5513
- display: flex;
5514
- align-items: center;
5515
- gap: 8px;
5516
- }
5517
-
5518
- /* Desktop time display */
5519
- .uvf-time-display {
5520
- color: #fff;
5521
- font-size: 14px;
5522
- font-weight: 500;
5523
- padding: 0 10px;
5524
- }
5525
-
5526
- /* Desktop volume control */
5527
- .uvf-volume-panel {
5528
- display: flex !important; /* Show volume slider on desktop */
5529
- align-items: center;
5530
- gap: 8px;
5531
- }
5532
-
5533
- .uvf-volume-slider {
5534
- width: 80px;
5535
- height: 4px;
5536
- background: rgba(255, 255, 255, 0.3);
5537
- border-radius: 2px;
5538
- cursor: pointer;
5539
- }
5540
-
5541
- /* Desktop settings and other controls */
5542
- .uvf-quality-badge {
5543
- display: block;
5544
- background: rgba(255, 255, 255, 0.1);
5545
- color: #fff;
5546
- padding: 4px 8px;
5547
- border-radius: 4px;
5548
- font-size: 11px;
5549
- font-weight: 500;
5550
- }
5551
-
5552
- /* Desktop progress bar */
5553
- .uvf-progress-bar {
5554
- height: 2px;
5555
- background: rgba(255, 255, 255, 0.2);
5556
- border-radius: 4px;
5557
- cursor: pointer;
5558
- transition: height 0.2s ease;
5559
- }
5560
-
5561
- .uvf-progress-bar-wrapper:hover .uvf-progress-bar {
5562
- height: 4px;
5563
- }
5564
-
5565
- .uvf-progress-filled {
5566
- background: var(--uvf-accent-1, #8B5CF6);
5567
- height: 100%;
5568
- border-radius: 4px;
5569
- }
5570
-
5571
- .uvf-progress-handle {
5572
- width: 12px;
5573
- height: 12px;
5574
- background: #fff;
5575
- border-radius: 50%;
5576
- position: absolute;
5577
- top: 50%;
5578
- transform: translateY(-50%);
5579
- cursor: grab;
5580
- opacity: 0;
5581
- transition: opacity 0.2s ease;
5582
- }
5583
-
5584
- .uvf-progress-bar-wrapper:hover .uvf-progress-handle {
5585
- opacity: 1;
5586
- }
5587
-
5588
- /* Desktop center play button */
5589
- .uvf-center-play-container {
5590
- position: absolute;
5591
- top: 50%;
5592
- left: 50%;
5593
- transform: translate(-50%, -50%);
5594
- z-index: 8;
5595
- }
5596
-
5597
- .uvf-center-play-btn {
5598
- width: clamp(56px, 10vw, 72px);
5599
- height: clamp(56px, 10vw, 72px);
5600
- background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
5601
- border: none;
5602
- border-radius: 50%;
5603
- display: flex;
5604
- align-items: center;
5605
- justify-content: center;
5606
- cursor: pointer;
5607
- box-shadow: 0 4px 16px rgba(0,0,0,0.3);
5608
- transition: all 0.25s ease;
5609
- }
5610
-
5611
- .uvf-center-play-btn:hover {
5612
- transform: scale(1.1);
5613
- box-shadow: 0 6px 20px rgba(0,0,0,0.4);
5614
- }
5615
-
5616
- .uvf-center-play-btn svg {
5617
- width: clamp(24px, 4vw, 30px);
5618
- height: clamp(24px, 4vw, 30px);
5619
- fill: #fff;
5620
- margin-left: 2px;
5621
5307
  }
5622
5308
 
5623
5309
  .uvf-progress-section {
@@ -8765,27 +8451,8 @@ export class WebPlayer extends BasePlayer {
8765
8451
  // Speed options
8766
8452
  settingsMenu.querySelectorAll('.speed-option').forEach(option => {
8767
8453
  option.addEventListener('click', (e) => {
8768
- e.preventDefault();
8769
- e.stopPropagation();
8770
-
8771
8454
  const speed = parseFloat((e.target as HTMLElement).dataset.speed || '1');
8772
-
8773
- // Update active state immediately
8774
- this.updateSettingsActiveStates('speed-option', e.target as HTMLElement);
8775
-
8776
- // Set the speed
8777
8455
  this.setPlaybackRateFromSettings(speed);
8778
-
8779
- // Update the accordion header text immediately
8780
- const speedLabel = speed === 1 ? 'Normal' : `${speed}x`;
8781
- const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
8782
- if (accordionCurrent) {
8783
- accordionCurrent.textContent = speedLabel;
8784
- }
8785
-
8786
- this.debugLog(`Speed selected: ${speed}x`);
8787
-
8788
- // Update accordion after selection
8789
8456
  this.updateAccordionAfterSelection('speed');
8790
8457
  });
8791
8458
  });
@@ -8793,28 +8460,8 @@ export class WebPlayer extends BasePlayer {
8793
8460
  // Quality options
8794
8461
  settingsMenu.querySelectorAll('.quality-option').forEach(option => {
8795
8462
  option.addEventListener('click', (e) => {
8796
- e.preventDefault();
8797
- e.stopPropagation();
8798
-
8799
8463
  const quality = (e.target as HTMLElement).dataset.quality || 'auto';
8800
-
8801
- // Update active state immediately
8802
- this.updateSettingsActiveStates('quality-option', e.target as HTMLElement);
8803
-
8804
- // Set the quality
8805
8464
  this.setQualityFromSettings(quality);
8806
-
8807
- // Update the accordion header text immediately
8808
- const qualityItem = this.availableQualities.find(q => q.value === quality);
8809
- const qualityLabel = qualityItem ? qualityItem.label : 'Auto';
8810
- const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
8811
- if (accordionCurrent) {
8812
- accordionCurrent.textContent = qualityLabel;
8813
- }
8814
-
8815
- this.debugLog(`Quality selected: ${quality} (${qualityLabel})`);
8816
-
8817
- // Update accordion after selection
8818
8465
  this.updateAccordionAfterSelection('quality');
8819
8466
  });
8820
8467
  });
@@ -8822,28 +8469,8 @@ export class WebPlayer extends BasePlayer {
8822
8469
  // Subtitle options
8823
8470
  settingsMenu.querySelectorAll('.subtitle-option').forEach(option => {
8824
8471
  option.addEventListener('click', (e) => {
8825
- e.preventDefault();
8826
- e.stopPropagation();
8827
-
8828
8472
  const subtitle = (e.target as HTMLElement).dataset.subtitle || 'off';
8829
-
8830
- // Update active state immediately
8831
- this.updateSettingsActiveStates('subtitle-option', e.target as HTMLElement);
8832
-
8833
- // Set the subtitle
8834
8473
  this.setSubtitle(subtitle);
8835
-
8836
- // Update the accordion header text immediately
8837
- const subtitleItem = this.availableSubtitles.find(s => s.value === subtitle);
8838
- const subtitleLabel = subtitleItem ? subtitleItem.label : 'Off';
8839
- const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
8840
- if (accordionCurrent) {
8841
- accordionCurrent.textContent = subtitleLabel;
8842
- }
8843
-
8844
- this.debugLog(`Subtitle selected: ${subtitle} (${subtitleLabel})`);
8845
-
8846
- // Update accordion after selection
8847
8474
  this.updateAccordionAfterSelection('subtitles');
8848
8475
  });
8849
8476
  });
@@ -8899,25 +8526,13 @@ export class WebPlayer extends BasePlayer {
8899
8526
  * Update accordion after user makes a selection
8900
8527
  */
8901
8528
  private updateAccordionAfterSelection(section: string): void {
8902
- // Close the accordion section after selection
8903
- const settingsMenu = document.getElementById('uvf-settings-menu');
8904
- if (settingsMenu) {
8905
- settingsMenu.querySelectorAll('.uvf-accordion-item.expanded').forEach(item => {
8906
- item.classList.remove('expanded');
8907
- });
8908
- }
8909
-
8910
- // Update the current values and refresh the menu
8529
+ // Just update the current values without closing
8530
+ // User can manually close or it will close when they click outside
8911
8531
  setTimeout(() => {
8912
8532
  // Refresh the menu to update current values
8913
8533
  this.generateAccordionMenu();
8914
8534
  this.setupSettingsEventListeners();
8915
- }, 50);
8916
-
8917
- // Auto-hide the settings menu after selection (optional)
8918
- setTimeout(() => {
8919
- this.hideSettingsMenu();
8920
- }, 150);
8535
+ }, 100);
8921
8536
  }
8922
8537
 
8923
8538
  /**