@arraypress/waveform-bar 1.0.0

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.
@@ -0,0 +1,943 @@
1
+ /**
2
+ * WaveformBar Styles
3
+ * Layout: [Left: fixed] — [Centre: flex] — [Right: fixed]
4
+ */
5
+
6
+ /* ==========================================================================
7
+ Variables
8
+ ========================================================================== */
9
+
10
+ .waveform-bar,
11
+ .wb-queue-panel {
12
+ --wb-bg: rgba(17, 17, 17, 0.95);
13
+ --wb-border: rgba(255, 255, 255, 0.1);
14
+ --wb-text: #ffffff;
15
+ --wb-text-muted: rgba(255, 255, 255, 0.5);
16
+ --wb-accent: #a855f7;
17
+ --wb-accent-light: #c084fc;
18
+ --wb-hover: rgba(255, 255, 255, 0.08);
19
+ --wb-tag-bg: rgba(255, 255, 255, 0.08);
20
+ --wb-tag-text: rgba(255, 255, 255, 0.7);
21
+ --wb-fav-color: #ef4444;
22
+ --wb-cart-color: #4ade80;
23
+ }
24
+
25
+ .waveform-bar.wb-light,
26
+ .wb-queue-panel.wb-light {
27
+ --wb-bg: rgba(255, 255, 255, 0.95);
28
+ --wb-border: rgba(0, 0, 0, 0.1);
29
+ --wb-text: #1a1a1a;
30
+ --wb-text-muted: rgba(0, 0, 0, 0.5);
31
+ --wb-hover: rgba(0, 0, 0, 0.05);
32
+ --wb-tag-bg: rgba(0, 0, 0, 0.06);
33
+ --wb-tag-text: rgba(0, 0, 0, 0.6);
34
+ }
35
+
36
+ .waveform-bar.wb-light {
37
+ box-shadow: 0 -1px 8px rgba(0, 0, 0, 0.08);
38
+ }
39
+
40
+ .wb-queue-panel.wb-light {
41
+ box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.1);
42
+ }
43
+
44
+ .wb-light .wb-volume-popup {
45
+ box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1);
46
+ }
47
+
48
+ /* ==========================================================================
49
+ Bar Shell
50
+ ========================================================================== */
51
+
52
+ .waveform-bar {
53
+ position: fixed;
54
+ bottom: 0;
55
+ left: 0;
56
+ right: 0;
57
+ background: var(--wb-bg);
58
+ backdrop-filter: blur(20px);
59
+ -webkit-backdrop-filter: blur(20px);
60
+ border-top: 1px solid var(--wb-border);
61
+ z-index: 9999;
62
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
63
+ color: var(--wb-text);
64
+ transform: translateY(100%);
65
+ opacity: 0;
66
+ transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
67
+ opacity 0.4s ease;
68
+ }
69
+
70
+ .waveform-bar.wb-active {
71
+ transform: translateY(0);
72
+ opacity: 1;
73
+ }
74
+
75
+ .waveform-bar * {
76
+ box-sizing: border-box;
77
+ }
78
+
79
+ /* ==========================================================================
80
+ Three-Zone Layout
81
+ ========================================================================== */
82
+
83
+ .wb-inner {
84
+ max-width: 1400px;
85
+ margin: 0 auto;
86
+ padding: 0.5rem 1.5rem;
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 0.75rem;
90
+ }
91
+
92
+ .wb-left {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 0.75rem;
96
+ flex-shrink: 0;
97
+ }
98
+
99
+ .wb-centre {
100
+ flex: 1;
101
+ min-width: 120px;
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 0.75rem;
105
+ }
106
+
107
+ .wb-right {
108
+ display: flex;
109
+ align-items: center;
110
+ gap: 0.5rem;
111
+ flex-shrink: 0;
112
+ }
113
+
114
+ /* ==========================================================================
115
+ Controls
116
+ ========================================================================== */
117
+
118
+ .wb-controls {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 0.125rem;
122
+ flex-shrink: 0;
123
+ }
124
+
125
+ .wb-btn {
126
+ width: 36px;
127
+ height: 36px;
128
+ border-radius: 50%;
129
+ border: none;
130
+ background: transparent;
131
+ color: var(--wb-text);
132
+ cursor: pointer;
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ transition: all 0.15s;
137
+ padding: 0;
138
+ }
139
+
140
+ .wb-btn:hover {
141
+ background: var(--wb-hover);
142
+ color: var(--wb-accent);
143
+ }
144
+
145
+ .wb-btn.wb-disabled {
146
+ opacity: 0.25;
147
+ pointer-events: none;
148
+ }
149
+
150
+ .wb-btn-sm {
151
+ width: 32px;
152
+ height: 32px;
153
+ }
154
+
155
+ .wb-play {
156
+ width: 40px;
157
+ height: 40px;
158
+ background: var(--wb-accent);
159
+ color: #fff;
160
+ }
161
+
162
+ .wb-play:hover {
163
+ background: var(--wb-accent-light);
164
+ color: #fff;
165
+ transform: scale(1.05);
166
+ }
167
+
168
+ /* ==========================================================================
169
+ Track Info
170
+ ========================================================================== */
171
+
172
+ .wb-track {
173
+ display: flex;
174
+ align-items: center;
175
+ gap: 0.625rem;
176
+ min-width: 0;
177
+ max-width: 200px;
178
+ overflow: hidden;
179
+ }
180
+
181
+ .wb-artwork {
182
+ width: 40px;
183
+ height: 40px;
184
+ border-radius: 6px;
185
+ background: linear-gradient(135deg, var(--wb-accent), var(--wb-accent-light));
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ flex-shrink: 0;
190
+ overflow: hidden;
191
+ }
192
+
193
+ .wb-artwork img {
194
+ width: 100%;
195
+ height: 100%;
196
+ object-fit: cover;
197
+ }
198
+
199
+ .wb-track-text {
200
+ min-width: 0;
201
+ overflow: hidden;
202
+ width: 140px;
203
+ }
204
+
205
+ .wb-title,
206
+ .wb-artist {
207
+ white-space: nowrap;
208
+ line-height: 1.3;
209
+ display: block;
210
+ overflow: hidden;
211
+ }
212
+
213
+ .wb-title {
214
+ font-size: 0.8rem;
215
+ font-weight: 600;
216
+ color: var(--wb-text);
217
+ }
218
+
219
+ .wb-artist {
220
+ font-size: 0.7rem;
221
+ color: var(--wb-text-muted);
222
+ }
223
+
224
+ /* Auto-scroll: applied by JS when text overflows */
225
+ .wb-title.wb-scrolling,
226
+ .wb-artist.wb-scrolling {
227
+ overflow: visible;
228
+ }
229
+
230
+ .wb-title.wb-scrolling .wb-scroll-inner,
231
+ .wb-artist.wb-scrolling .wb-scroll-inner {
232
+ display: inline-block;
233
+ padding-right: 3rem;
234
+ animation: wb-marquee var(--wb-scroll-duration, 8s) ease-in-out infinite;
235
+ }
236
+
237
+ @keyframes wb-marquee {
238
+ 0%, 10% {
239
+ transform: translateX(0);
240
+ }
241
+ 45%, 55% {
242
+ transform: translateX(var(--wb-scroll-distance, -100px));
243
+ }
244
+ 90%, 100% {
245
+ transform: translateX(0);
246
+ }
247
+ }
248
+
249
+ /* ==========================================================================
250
+ Time Display
251
+ ========================================================================== */
252
+
253
+ .wb-time {
254
+ font-size: 0.7rem;
255
+ color: var(--wb-text-muted);
256
+ white-space: nowrap;
257
+ flex-shrink: 0;
258
+ font-variant-numeric: tabular-nums;
259
+ min-width: 70px;
260
+ text-align: left;
261
+ }
262
+
263
+ /* ==========================================================================
264
+ Waveform
265
+ ========================================================================== */
266
+
267
+ .wb-waveform-container {
268
+ flex: 1;
269
+ min-width: 0;
270
+ width: 100%;
271
+ }
272
+
273
+ /* Strip waveform-player cosmetics when inside the bar and ensure
274
+ width propagates through the full DOM chain. The player's own
275
+ elements are block divs that don't inherit flex sizing. */
276
+ .wb-waveform-container .waveform-player {
277
+ width: 100%;
278
+ background: transparent !important;
279
+ border: none !important;
280
+ }
281
+
282
+ .wb-waveform-container .waveform-player-inner {
283
+ width: 100%;
284
+ padding: 0 !important;
285
+ }
286
+
287
+ .wb-waveform-container .waveform-body {
288
+ width: 100%;
289
+ gap: 0 !important;
290
+ }
291
+
292
+ .wb-waveform-container .waveform-track {
293
+ width: 100%;
294
+ padding: 0 !important;
295
+ }
296
+
297
+ /* Active marker pulse */
298
+ .wb-waveform-container .waveform-marker.wb-marker-active {
299
+ animation: wb-marker-pulse 2s ease-in-out infinite;
300
+ }
301
+
302
+ @keyframes wb-marker-pulse {
303
+ 0%, 100% {
304
+ opacity: 1;
305
+ }
306
+ 50% {
307
+ opacity: 0.3;
308
+ }
309
+ }
310
+
311
+ /* ==========================================================================
312
+ Metadata Tags
313
+ ========================================================================== */
314
+
315
+ .wb-meta {
316
+ display: none;
317
+ align-items: center;
318
+ gap: 0.375rem;
319
+ flex-shrink: 0;
320
+ }
321
+
322
+ .wb-tag {
323
+ display: inline-block;
324
+ padding: 0.15rem 0.5rem;
325
+ background: var(--wb-tag-bg);
326
+ color: var(--wb-tag-text);
327
+ border-radius: 4px;
328
+ font-size: 0.6rem;
329
+ font-weight: 600;
330
+ text-transform: uppercase;
331
+ letter-spacing: 0.03em;
332
+ white-space: nowrap;
333
+ }
334
+
335
+ .wb-tag-bpm {
336
+ color: var(--wb-accent);
337
+ background: rgba(168, 85, 247, 0.12);
338
+ }
339
+
340
+ .wb-tag-key {
341
+ color: #4ade80;
342
+ background: rgba(74, 222, 128, 0.12);
343
+ }
344
+
345
+ /* ==========================================================================
346
+ Action Buttons
347
+ ========================================================================== */
348
+
349
+ .wb-actions {
350
+ display: flex;
351
+ align-items: center;
352
+ gap: 0.25rem;
353
+ flex-shrink: 0;
354
+ }
355
+
356
+ .wb-fav-active {
357
+ color: var(--wb-fav-color) !important;
358
+ }
359
+
360
+ .wb-fav-active:hover {
361
+ background: rgba(239, 68, 68, 0.1);
362
+ }
363
+
364
+ .wb-action-done {
365
+ color: var(--wb-cart-color) !important;
366
+ animation: wb-flash 0.3s ease;
367
+ }
368
+
369
+ @keyframes wb-flash {
370
+ 0% {
371
+ transform: scale(1);
372
+ }
373
+ 50% {
374
+ transform: scale(1.3);
375
+ }
376
+ 100% {
377
+ transform: scale(1);
378
+ }
379
+ }
380
+
381
+ /* ==========================================================================
382
+ Volume — popup panel above mute button
383
+ ========================================================================== */
384
+
385
+ .wb-volume {
386
+ position: relative;
387
+ flex-shrink: 0;
388
+ }
389
+
390
+ .wb-mute.wb-muted {
391
+ opacity: 0.4;
392
+ }
393
+
394
+ .wb-volume-popup {
395
+ position: absolute;
396
+ bottom: calc(100% + 12px);
397
+ left: 50%;
398
+ transform: translateX(-50%) translateY(8px);
399
+ background: var(--wb-bg);
400
+ backdrop-filter: blur(20px);
401
+ -webkit-backdrop-filter: blur(20px);
402
+ border: 1px solid var(--wb-border);
403
+ border-radius: 10px;
404
+ padding: 1rem 0.5rem;
405
+ box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.4);
406
+ z-index: 10000;
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+ opacity: 0;
411
+ visibility: hidden;
412
+ pointer-events: none;
413
+ transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
414
+ }
415
+
416
+ .wb-volume-popup.wb-volume-open {
417
+ opacity: 1;
418
+ visibility: visible;
419
+ pointer-events: auto;
420
+ transform: translateX(-50%) translateY(0);
421
+ }
422
+
423
+ .wb-volume-slider {
424
+ -webkit-appearance: none;
425
+ appearance: none;
426
+ writing-mode: vertical-lr;
427
+ direction: rtl;
428
+ width: 6px;
429
+ height: 100px;
430
+ background: transparent;
431
+ outline: none;
432
+ cursor: pointer;
433
+ }
434
+
435
+ /* Track — Webkit (Chrome/Safari/Edge) */
436
+ .wb-volume-slider::-webkit-slider-runnable-track {
437
+ width: 6px;
438
+ background: var(--wb-border);
439
+ border-radius: 3px;
440
+ }
441
+
442
+ /* Thumb — Webkit */
443
+ .wb-volume-slider::-webkit-slider-thumb {
444
+ -webkit-appearance: none;
445
+ width: 16px;
446
+ height: 16px;
447
+ background: var(--wb-accent);
448
+ border-radius: 50%;
449
+ cursor: pointer;
450
+ margin-left: -5px;
451
+ transition: transform 0.15s;
452
+ }
453
+
454
+ .wb-volume-slider::-webkit-slider-thumb:hover {
455
+ transform: scale(1.2);
456
+ }
457
+
458
+ /* Track — Firefox */
459
+ .wb-volume-slider::-moz-range-track {
460
+ width: 6px;
461
+ background: var(--wb-border);
462
+ border-radius: 3px;
463
+ border: none;
464
+ }
465
+
466
+ /* Thumb — Firefox */
467
+ .wb-volume-slider::-moz-range-thumb {
468
+ width: 16px;
469
+ height: 16px;
470
+ background: var(--wb-accent);
471
+ border: none;
472
+ border-radius: 50%;
473
+ cursor: pointer;
474
+ }
475
+
476
+ .wb-volume-slider::-moz-range-thumb:hover {
477
+ transform: scale(1.2);
478
+ }
479
+
480
+ /* ==========================================================================
481
+ Repeat Button
482
+ ========================================================================== */
483
+
484
+ .wb-repeat {
485
+ opacity: 0.4;
486
+ transition: opacity 0.15s, color 0.15s;
487
+ }
488
+
489
+ .wb-repeat.wb-repeat-active {
490
+ opacity: 1;
491
+ color: var(--wb-accent);
492
+ }
493
+
494
+ .wb-repeat.wb-repeat-active:hover {
495
+ background: rgba(168, 85, 247, 0.12);
496
+ }
497
+
498
+ /* ==========================================================================
499
+ Queue Button
500
+ ========================================================================== */
501
+
502
+ .wb-queue-btn.wb-active {
503
+ color: var(--wb-accent);
504
+ background: rgba(168, 85, 247, 0.12);
505
+ }
506
+
507
+ /* ==========================================================================
508
+ Queue Panel — anchored above queue button
509
+ ========================================================================== */
510
+
511
+ .wb-queue-panel {
512
+ position: fixed;
513
+ bottom: 68px;
514
+ width: 340px;
515
+ max-height: 400px;
516
+ background: var(--wb-bg);
517
+ backdrop-filter: blur(20px);
518
+ -webkit-backdrop-filter: blur(20px);
519
+ border: 1px solid var(--wb-border);
520
+ border-radius: 12px;
521
+ z-index: 9999;
522
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
523
+ color: var(--wb-text);
524
+ display: flex;
525
+ flex-direction: column;
526
+ box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.4);
527
+ overflow: hidden;
528
+ opacity: 0;
529
+ visibility: hidden;
530
+ pointer-events: none;
531
+ transform: translateY(8px);
532
+ transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
533
+ }
534
+
535
+ .wb-queue-panel.wb-queue-open {
536
+ opacity: 1;
537
+ visibility: visible;
538
+ pointer-events: auto;
539
+ transform: translateY(0);
540
+ }
541
+
542
+ .wb-queue-header {
543
+ display: flex;
544
+ align-items: center;
545
+ justify-content: space-between;
546
+ padding: 0.75rem 1rem;
547
+ border-bottom: 1px solid var(--wb-border);
548
+ flex-shrink: 0;
549
+ }
550
+
551
+ .wb-queue-title {
552
+ font-size: 0.85rem;
553
+ font-weight: 600;
554
+ display: flex;
555
+ align-items: center;
556
+ gap: 0.5rem;
557
+ }
558
+
559
+ .wb-queue-title svg {
560
+ width: 16px;
561
+ height: 16px;
562
+ }
563
+
564
+ .wb-queue-count {
565
+ background: rgba(168, 85, 247, 0.15);
566
+ color: var(--wb-accent);
567
+ padding: 0.1rem 0.45rem;
568
+ border-radius: 10px;
569
+ font-size: 0.7rem;
570
+ font-weight: 600;
571
+ }
572
+
573
+ .wb-queue-clear {
574
+ background: transparent;
575
+ border: none;
576
+ color: var(--wb-text-muted);
577
+ cursor: pointer;
578
+ font-size: 0.7rem;
579
+ padding: 0.25rem 0.5rem;
580
+ border-radius: 4px;
581
+ transition: all 0.15s;
582
+ width: auto;
583
+ height: auto;
584
+ }
585
+
586
+ .wb-queue-clear:hover {
587
+ color: var(--wb-accent);
588
+ background: var(--wb-hover);
589
+ }
590
+
591
+ .wb-queue-body {
592
+ flex: 1;
593
+ overflow-y: auto;
594
+ padding: 0.375rem;
595
+ }
596
+
597
+ .wb-queue-body::-webkit-scrollbar {
598
+ width: 5px;
599
+ }
600
+
601
+ .wb-queue-body::-webkit-scrollbar-track {
602
+ background: transparent;
603
+ }
604
+
605
+ .wb-queue-body::-webkit-scrollbar-thumb {
606
+ background: var(--wb-border);
607
+ border-radius: 3px;
608
+ }
609
+
610
+ .wb-queue-label {
611
+ padding: 0.4rem 0.5rem 0.2rem;
612
+ font-size: 0.6rem;
613
+ font-weight: 600;
614
+ text-transform: uppercase;
615
+ letter-spacing: 0.08em;
616
+ color: var(--wb-text-muted);
617
+ }
618
+
619
+ .wb-queue-item {
620
+ display: flex;
621
+ align-items: center;
622
+ gap: 0.5rem;
623
+ padding: 0.4rem 0.5rem;
624
+ border-radius: 6px;
625
+ transition: background 0.15s;
626
+ cursor: pointer;
627
+ }
628
+
629
+ .wb-queue-item:hover {
630
+ background: var(--wb-hover);
631
+ }
632
+
633
+ .wb-queue-current {
634
+ background: rgba(168, 85, 247, 0.1);
635
+ }
636
+
637
+ .wb-queue-num {
638
+ width: 18px;
639
+ text-align: center;
640
+ font-size: 0.7rem;
641
+ color: var(--wb-text-muted);
642
+ flex-shrink: 0;
643
+ display: flex;
644
+ align-items: center;
645
+ justify-content: center;
646
+ }
647
+
648
+ .wb-queue-current .wb-queue-num {
649
+ color: var(--wb-accent);
650
+ }
651
+
652
+ .wb-queue-info {
653
+ flex: 1;
654
+ min-width: 0;
655
+ }
656
+
657
+ .wb-queue-item-title {
658
+ font-size: 0.75rem;
659
+ font-weight: 500;
660
+ color: var(--wb-text);
661
+ white-space: nowrap;
662
+ overflow: hidden;
663
+ text-overflow: ellipsis;
664
+ }
665
+
666
+ .wb-queue-current .wb-queue-item-title {
667
+ color: var(--wb-accent);
668
+ }
669
+
670
+ .wb-queue-played .wb-queue-item-title {
671
+ color: var(--wb-text-muted);
672
+ }
673
+
674
+ .wb-queue-item-artist {
675
+ font-size: 0.65rem;
676
+ color: var(--wb-text-muted);
677
+ white-space: nowrap;
678
+ overflow: hidden;
679
+ text-overflow: ellipsis;
680
+ }
681
+
682
+ .wb-queue-remove {
683
+ opacity: 0;
684
+ transition: opacity 0.15s;
685
+ background: transparent;
686
+ border: none;
687
+ color: var(--wb-text-muted);
688
+ cursor: pointer;
689
+ padding: 0.2rem;
690
+ border-radius: 4px;
691
+ display: flex;
692
+ align-items: center;
693
+ justify-content: center;
694
+ flex-shrink: 0;
695
+ }
696
+
697
+ .wb-queue-item:hover .wb-queue-remove {
698
+ opacity: 1;
699
+ }
700
+
701
+ .wb-queue-remove:hover {
702
+ color: #ef4444;
703
+ background: rgba(239, 68, 68, 0.1);
704
+ }
705
+
706
+ .wb-queue-empty {
707
+ display: flex;
708
+ flex-direction: column;
709
+ align-items: center;
710
+ padding: 2.5rem 1rem;
711
+ color: var(--wb-text-muted);
712
+ text-align: center;
713
+ }
714
+
715
+ .wb-queue-empty svg {
716
+ opacity: 0.3;
717
+ margin-bottom: 0.5rem;
718
+ }
719
+
720
+ .wb-queue-empty p {
721
+ font-size: 0.8rem;
722
+ margin: 0;
723
+ }
724
+
725
+ /* ==========================================================================
726
+ Helper CSS Classes
727
+ ========================================================================== */
728
+
729
+ .wb-icon-swap .wb-show-pause {
730
+ display: none;
731
+ }
732
+
733
+ .wb-icon-swap .wb-show-play {
734
+ display: inline;
735
+ }
736
+
737
+ .wb-icon-swap.wb-playing .wb-show-pause {
738
+ display: inline;
739
+ }
740
+
741
+ .wb-icon-swap.wb-playing .wb-show-play {
742
+ display: none;
743
+ }
744
+
745
+ .wb-eq-bars {
746
+ display: inline-flex;
747
+ gap: 2px;
748
+ align-items: flex-end;
749
+ height: 14px;
750
+ vertical-align: middle;
751
+ }
752
+
753
+ .wb-eq-bars span {
754
+ width: 3px;
755
+ height: 4px;
756
+ background: currentColor;
757
+ border-radius: 1px;
758
+ opacity: 0.3;
759
+ }
760
+
761
+ .wb-playing .wb-eq-bars span {
762
+ opacity: 1;
763
+ animation: wb-eq 0.8s ease-in-out infinite;
764
+ }
765
+
766
+ .wb-playing .wb-eq-bars span:nth-child(1) {
767
+ animation-delay: 0s;
768
+ }
769
+
770
+ .wb-playing .wb-eq-bars span:nth-child(2) {
771
+ animation-delay: 0.15s;
772
+ }
773
+
774
+ .wb-playing .wb-eq-bars span:nth-child(3) {
775
+ animation-delay: 0.3s;
776
+ }
777
+
778
+ .wb-playing .wb-eq-bars span:nth-child(4) {
779
+ animation-delay: 0.45s;
780
+ }
781
+
782
+ @keyframes wb-eq {
783
+ 0%, 100% {
784
+ height: 4px;
785
+ }
786
+ 50% {
787
+ height: 14px;
788
+ }
789
+ }
790
+
791
+ .wb-card-highlight {
792
+ transition: border-color 0.2s, box-shadow 0.2s;
793
+ }
794
+
795
+ .wb-card-highlight.wb-current {
796
+ border-color: var(--wb-accent, #a855f7);
797
+ box-shadow: 0 0 0 1px var(--wb-accent, #a855f7);
798
+ }
799
+
800
+ .wb-current .wb-accent-current {
801
+ color: var(--wb-accent, #a855f7);
802
+ }
803
+
804
+ .wb-pulse-playing.wb-playing {
805
+ animation: wb-pulse 2s ease-in-out infinite;
806
+ }
807
+
808
+ @keyframes wb-pulse {
809
+ 0%, 100% {
810
+ opacity: 1;
811
+ }
812
+ 50% {
813
+ opacity: 0.7;
814
+ }
815
+ }
816
+
817
+ /* ==========================================================================
818
+ Page State Helper Classes (for trigger elements)
819
+ ========================================================================== */
820
+
821
+ /*
822
+ * .wb-favorited — applied to triggers whose track is favorited
823
+ * .wb-in-cart — applied to triggers whose track is in cart
824
+ *
825
+ * Usage in your site CSS:
826
+ * .my-card.wb-favorited .heart-icon { color: red; fill: red; }
827
+ * .my-card.wb-in-cart .cart-badge { display: block; }
828
+ */
829
+
830
+ /* Convenience: hide/show elements based on favorite state */
831
+ .wb-show-if-fav {
832
+ display: none;
833
+ }
834
+
835
+ .wb-favorited .wb-show-if-fav {
836
+ display: inline;
837
+ }
838
+
839
+ .wb-favorited .wb-hide-if-fav {
840
+ display: none;
841
+ }
842
+
843
+ .wb-show-if-cart {
844
+ display: none;
845
+ }
846
+
847
+ .wb-in-cart .wb-show-if-cart {
848
+ display: inline;
849
+ }
850
+
851
+ .wb-in-cart .wb-hide-if-cart {
852
+ display: none;
853
+ }
854
+
855
+ /* ==========================================================================
856
+ Responsive — Stacking on mobile
857
+ ========================================================================== */
858
+
859
+ @media (max-width: 768px) {
860
+ .wb-inner {
861
+ padding: 0.5rem 1rem;
862
+ gap: 0.5rem;
863
+ flex-wrap: wrap;
864
+ }
865
+
866
+ /* Top row: controls + track info fill width */
867
+ .wb-left {
868
+ width: auto;
869
+ min-width: auto;
870
+ flex: 1;
871
+ }
872
+
873
+ /* Bottom row: waveform spans full width */
874
+ .wb-centre {
875
+ order: 10;
876
+ flex-basis: 100%;
877
+ min-width: 100%;
878
+ }
879
+
880
+ /* Right zone stays on top row */
881
+ .wb-right {
882
+ order: 2;
883
+ }
884
+
885
+ .wb-track-text {
886
+ width: auto;
887
+ max-width: 200px;
888
+ }
889
+
890
+ .wb-meta {
891
+ display: none !important;
892
+ }
893
+
894
+ .wb-actions {
895
+ display: none;
896
+ }
897
+
898
+ .wb-time {
899
+ display: none;
900
+ }
901
+
902
+ .wb-queue-panel {
903
+ left: 0;
904
+ right: 0;
905
+ width: auto;
906
+ bottom: 90px;
907
+ border-radius: 12px 12px 0 0;
908
+ max-height: 50vh;
909
+ }
910
+
911
+ .wb-volume-popup {
912
+ left: auto;
913
+ right: 0;
914
+ transform: none;
915
+ }
916
+ }
917
+
918
+ @media (max-width: 480px) {
919
+ .wb-left {
920
+ gap: 0.5rem;
921
+ }
922
+
923
+ .wb-track-text {
924
+ width: auto;
925
+ max-width: 140px;
926
+ }
927
+
928
+ .wb-prev, .wb-next {
929
+ display: none;
930
+ }
931
+
932
+ .wb-repeat {
933
+ display: none;
934
+ }
935
+
936
+ .wb-volume {
937
+ display: none;
938
+ }
939
+
940
+ .wb-queue-panel {
941
+ bottom: 85px;
942
+ }
943
+ }