@livepeer-frameworks/player-svelte 0.1.3 → 0.2.3

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.
Files changed (59) hide show
  1. package/dist/DevModePanel.svelte +34 -25
  2. package/dist/IdleScreen.svelte +14 -4
  3. package/dist/LoadingScreen.svelte +92 -50
  4. package/dist/LoadingScreen.svelte.bak +702 -0
  5. package/dist/Player.svelte +206 -55
  6. package/dist/Player.svelte.d.ts +6 -1
  7. package/dist/PlayerControls.svelte +159 -74
  8. package/dist/PlayerControls.svelte.d.ts +7 -0
  9. package/dist/SeekBar.svelte +15 -14
  10. package/dist/SeekBar.svelte.d.ts +4 -4
  11. package/dist/StreamStateOverlay.svelte +20 -6
  12. package/dist/SubtitleRenderer.svelte +3 -3
  13. package/dist/SubtitleRenderer.svelte.d.ts +1 -1
  14. package/dist/controls/FullscreenButton.svelte +28 -0
  15. package/dist/controls/FullscreenButton.svelte.d.ts +3 -0
  16. package/dist/controls/LiveBadge.svelte +25 -0
  17. package/dist/controls/LiveBadge.svelte.d.ts +3 -0
  18. package/dist/controls/PlayButton.svelte +28 -0
  19. package/dist/controls/PlayButton.svelte.d.ts +3 -0
  20. package/dist/controls/SettingsMenu.svelte +210 -0
  21. package/dist/controls/SettingsMenu.svelte.d.ts +28 -0
  22. package/dist/controls/SkipButton.svelte +36 -0
  23. package/dist/controls/SkipButton.svelte.d.ts +7 -0
  24. package/dist/controls/TimeDisplay.svelte +18 -0
  25. package/dist/controls/TimeDisplay.svelte.d.ts +3 -0
  26. package/dist/controls/VolumeControl.svelte +28 -0
  27. package/dist/controls/VolumeControl.svelte.d.ts +3 -0
  28. package/dist/controls/index.d.ts +7 -0
  29. package/dist/controls/index.js +7 -0
  30. package/dist/index.d.ts +3 -2
  31. package/dist/index.js +3 -1
  32. package/dist/stores/i18n.d.ts +3 -0
  33. package/dist/stores/i18n.js +4 -0
  34. package/dist/stores/index.d.ts +1 -0
  35. package/dist/stores/index.js +2 -0
  36. package/dist/stores/playerController.d.ts +4 -4
  37. package/dist/stores/playerController.js +1 -1
  38. package/package.json +8 -8
  39. package/src/DevModePanel.svelte +34 -25
  40. package/src/IdleScreen.svelte +14 -4
  41. package/src/LoadingScreen.svelte +92 -50
  42. package/src/LoadingScreen.svelte.bak +702 -0
  43. package/src/Player.svelte +206 -55
  44. package/src/PlayerControls.svelte +159 -74
  45. package/src/SeekBar.svelte +15 -14
  46. package/src/StreamStateOverlay.svelte +20 -6
  47. package/src/SubtitleRenderer.svelte +3 -3
  48. package/src/controls/FullscreenButton.svelte +28 -0
  49. package/src/controls/LiveBadge.svelte +25 -0
  50. package/src/controls/PlayButton.svelte +28 -0
  51. package/src/controls/SettingsMenu.svelte +210 -0
  52. package/src/controls/SkipButton.svelte +36 -0
  53. package/src/controls/TimeDisplay.svelte +18 -0
  54. package/src/controls/VolumeControl.svelte +28 -0
  55. package/src/controls/index.ts +7 -0
  56. package/src/index.ts +10 -0
  57. package/src/stores/i18n.ts +7 -0
  58. package/src/stores/index.ts +3 -0
  59. package/src/stores/playerController.ts +5 -5
@@ -67,7 +67,7 @@
67
67
  let internalIsOpen = $state(false);
68
68
  let activeTab = $state<"config" | "stats">("config");
69
69
  let hoveredComboIndex = $state<number | null>(null);
70
- let tooltipAbove = $state(false);
70
+ let tooltipPos = $state<{ top: number; left: number } | null>(null);
71
71
  let showDisabledPlayers = $state(false);
72
72
  let comboListRef: HTMLDivElement | undefined = $state();
73
73
 
@@ -163,14 +163,12 @@
163
163
 
164
164
  function handleComboHover(index: number, e: MouseEvent) {
165
165
  hoveredComboIndex = index;
166
- if (comboListRef) {
167
- const container = comboListRef;
168
- const row = e.currentTarget as HTMLElement;
169
- const containerRect = container.getBoundingClientRect();
170
- const rowRect = row.getBoundingClientRect();
171
- const relativePosition = (rowRect.top - containerRect.top) / containerRect.height;
172
- tooltipAbove = relativePosition > 0.6;
173
- }
166
+ const row = e.currentTarget as HTMLElement;
167
+ const rowRect = row.getBoundingClientRect();
168
+ tooltipPos = {
169
+ top: Math.max(8, Math.min(rowRect.top, window.innerHeight - 200)),
170
+ left: Math.max(8, rowRect.left - 228),
171
+ };
174
172
  }
175
173
 
176
174
  // Quality monitoring
@@ -377,7 +375,9 @@
377
375
  {:else}
378
376
  {#each allCombinations as combo, index}
379
377
  {@const isCodecIncompat = (combo as any).codecIncompatible === true}
380
- {@const shouldShow = combo.compatible || isCodecIncompat || showDisabledPlayers}
378
+ {@const isPartial = ((combo as any).missingTracks?.length ?? 0) > 0}
379
+ {@const isWarn = isCodecIncompat || isPartial}
380
+ {@const shouldShow = combo.compatible || isWarn || showDisabledPlayers}
381
381
  {@const isActive = activeComboIndex === index}
382
382
  {@const typeLabel =
383
383
  SOURCE_TYPE_LABELS[combo.sourceType] || combo.sourceType.split("/").pop()}
@@ -387,7 +387,10 @@
387
387
  class="fw-dev-combo"
388
388
  role="listitem"
389
389
  onmouseenter={(e) => handleComboHover(index, e)}
390
- onmouseleave={() => (hoveredComboIndex = null)}
390
+ onmouseleave={() => {
391
+ hoveredComboIndex = null;
392
+ tooltipPos = null;
393
+ }}
391
394
  >
392
395
  <button
393
396
  type="button"
@@ -395,8 +398,8 @@
395
398
  class={cn(
396
399
  "fw-dev-combo-btn",
397
400
  isActive && "fw-dev-combo-btn--active",
398
- !combo.compatible && !isCodecIncompat && "fw-dev-combo-btn--disabled",
399
- isCodecIncompat && "fw-dev-combo-btn--codec-warn"
401
+ !combo.compatible && !isWarn && "fw-dev-combo-btn--disabled",
402
+ isWarn && "fw-dev-combo-btn--codec-warn"
400
403
  )}
401
404
  >
402
405
  <!-- Rank -->
@@ -405,14 +408,14 @@
405
408
  "fw-dev-combo-rank",
406
409
  isActive
407
410
  ? "fw-dev-combo-rank--active"
408
- : !combo.compatible && !isCodecIncompat
411
+ : !combo.compatible && !isWarn
409
412
  ? "fw-dev-combo-rank--disabled"
410
- : isCodecIncompat
413
+ : isWarn
411
414
  ? "fw-dev-combo-rank--warn"
412
415
  : ""
413
416
  )}
414
417
  >
415
- {combo.compatible ? index + 1 : isCodecIncompat ? "⚠" : "—"}
418
+ {combo.compatible && !isPartial ? index + 1 : isWarn ? "⚠" : "—"}
416
419
  </span>
417
420
  <!-- Player + Protocol -->
418
421
  <span class="fw-dev-combo-name">
@@ -421,8 +424,8 @@
421
424
  <span
422
425
  class={cn(
423
426
  "fw-dev-combo-type",
424
- isCodecIncompat && "fw-dev-combo-type--warn",
425
- !combo.compatible && !isCodecIncompat && "fw-dev-combo-type--disabled"
427
+ isWarn && "fw-dev-combo-type--warn",
428
+ !combo.compatible && !isWarn && "fw-dev-combo-type--disabled"
426
429
  )}>{typeLabel}</span
427
430
  >
428
431
  </span>
@@ -430,9 +433,9 @@
430
433
  <span
431
434
  class={cn(
432
435
  "fw-dev-combo-score",
433
- !combo.compatible && !isCodecIncompat
436
+ !combo.compatible && !isWarn
434
437
  ? "fw-dev-combo-score--disabled"
435
- : isCodecIncompat
438
+ : isWarn
436
439
  ? "fw-dev-combo-score--low"
437
440
  : combo.score >= 2
438
441
  ? "fw-dev-combo-score--high"
@@ -446,12 +449,10 @@
446
449
  </button>
447
450
 
448
451
  <!-- Tooltip -->
449
- {#if hoveredComboIndex === index}
452
+ {#if hoveredComboIndex === index && tooltipPos}
450
453
  <div
451
- class={cn(
452
- "fw-dev-tooltip",
453
- tooltipAbove ? "fw-dev-tooltip--above" : "fw-dev-tooltip--below"
454
- )}
454
+ class="fw-dev-tooltip"
455
+ style="top: {tooltipPos.top}px; left: {tooltipPos.left}px;"
455
456
  >
456
457
  <div class="fw-dev-tooltip-header">
457
458
  <div class="fw-dev-tooltip-title">{combo.playerName}</div>
@@ -464,6 +465,14 @@
464
465
  </div>
465
466
  {/if}
466
467
  </div>
468
+ {#if combo.note}
469
+ <div class="fw-dev-tooltip-note">{combo.note}</div>
470
+ {/if}
471
+ {#if isPartial}
472
+ <div class="fw-dev-tooltip-note">
473
+ No compatible {(combo as any).missingTracks.join(", ")} codec
474
+ </div>
475
+ {/if}
467
476
  {#if combo.compatible && combo.scoreBreakdown}
468
477
  <div class="fw-dev-tooltip-score">Score: {combo.score.toFixed(2)}</div>
469
478
  <div class="fw-dev-tooltip-row">
@@ -13,7 +13,10 @@
13
13
  - Status overlay at bottom
14
14
  -->
15
15
  <script lang="ts">
16
- import { onMount, onDestroy } from "svelte";
16
+ import { onMount, onDestroy, getContext } from "svelte";
17
+ import { readable } from "svelte/store";
18
+ import type { Readable } from "svelte/store";
19
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
17
20
  import type { StreamStatus } from "@livepeer-frameworks/player-core";
18
21
  import DvdLogo from "./DvdLogo.svelte";
19
22
  import logomarkAsset from "./assets/logomark.svg";
@@ -26,14 +29,21 @@
26
29
  onRetry?: () => void;
27
30
  }
28
31
 
32
+ const translatorStore: Readable<TranslateFn> =
33
+ getContext<Readable<TranslateFn> | undefined>("fw-translator") ??
34
+ readable(createTranslator({ locale: "en" }));
35
+ let t: TranslateFn = $derived($translatorStore);
36
+
29
37
  let {
30
38
  status = "OFFLINE",
31
- message = "Waiting for stream...",
39
+ message = undefined,
32
40
  percentage = undefined,
33
41
  error = undefined,
34
42
  onRetry = undefined,
35
43
  }: Props = $props();
36
44
 
45
+ let effectiveMessage = $derived(message ?? t("waitingForStream"));
46
+
37
47
  // Container ref for mouse tracking
38
48
  let containerRef: HTMLDivElement | undefined = $state();
39
49
 
@@ -316,7 +326,7 @@
316
326
  let _statusLabel = $derived(getStatusLabel(status));
317
327
  let showRetry = $derived((status === "ERROR" || status === "INVALID") && onRetry);
318
328
  let showProgress = $derived(status === "INITIALIZING" && percentage !== undefined);
319
- let displayMessage = $derived(error || message);
329
+ let displayMessage = $derived(error || effectiveMessage);
320
330
  let isLoading = $derived(
321
331
  status === "INITIALIZING" || status === "BOOTING" || status === "WAITING_FOR_DATA" || !status
322
332
  );
@@ -522,7 +532,7 @@
522
532
 
523
533
  <!-- Retry button -->
524
534
  {#if showRetry}
525
- <button type="button" class="retry-button" onclick={onRetry}> Retry </button>
535
+ <button type="button" class="retry-button" onclick={onRetry}> {t("retry")} </button>
526
536
  {/if}
527
537
  </div>
528
538
 
@@ -12,16 +12,25 @@
12
12
  - Animated background gradient shifts
13
13
  -->
14
14
  <script lang="ts">
15
- import { onMount, onDestroy } from "svelte";
15
+ import { onMount, onDestroy, getContext } from "svelte";
16
+ import { readable } from "svelte/store";
17
+ import type { Readable } from "svelte/store";
18
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
16
19
  import DvdLogo from "./DvdLogo.svelte";
17
20
  import logomarkAsset from "./assets/logomark.svg";
18
21
 
22
+ const translatorStore: Readable<TranslateFn> =
23
+ getContext<Readable<TranslateFn> | undefined>("fw-translator") ??
24
+ readable(createTranslator({ locale: "en" }));
25
+ let t: TranslateFn = $derived($translatorStore);
26
+
19
27
  interface Props {
20
28
  message?: string;
21
29
  logoSrc?: string;
22
30
  }
23
31
 
24
- let { message = "Waiting for source...", logoSrc }: Props = $props();
32
+ let { message = undefined, logoSrc }: Props = $props();
33
+ let effectiveMessage = $derived(message ?? t("waitingForSource"));
25
34
 
26
35
  // Use imported asset as default if logoSrc not provided
27
36
  let effectiveLogoSrc = $derived(logoSrc || logomarkAsset);
@@ -42,35 +51,10 @@
42
51
  let offset = $state({ x: 0, y: 0 });
43
52
  let isHovered = $state(false);
44
53
 
45
- // Tokyo Night inspired pastel colors for bubbles
46
- const bubbleColors = [
47
- "rgba(122, 162, 247, 0.2)", // Terminal Blue
48
- "rgba(187, 154, 247, 0.2)", // Terminal Magenta
49
- "rgba(158, 206, 106, 0.2)", // Strings/CSS classes
50
- "rgba(115, 218, 202, 0.2)", // Terminal Green
51
- "rgba(125, 207, 255, 0.2)", // Terminal Cyan
52
- "rgba(247, 118, 142, 0.2)", // Keywords/Terminal Red
53
- "rgba(224, 175, 104, 0.2)", // Terminal Yellow
54
- "rgba(42, 195, 222, 0.2)", // Language functions
55
- ];
56
-
57
- // Particle colors
58
- const particleColors = [
59
- "#7aa2f7", // Terminal Blue
60
- "#bb9af7", // Terminal Magenta
61
- "#9ece6a", // Strings/CSS classes
62
- "#73daca", // Terminal Green
63
- "#7dcfff", // Terminal Cyan
64
- "#f7768e", // Keywords/Terminal Red
65
- "#e0af68", // Terminal Yellow
66
- "#2ac3de", // Language functions
67
- ];
68
-
69
54
  // Generate random particles
70
- const particles = Array.from({ length: 12 }, (_, i) => ({
55
+ const particles = Array.from({ length: 12 }, () => ({
71
56
  left: Math.random() * 100,
72
57
  size: Math.random() * 4 + 2,
73
- color: particleColors[i % 8],
74
58
  duration: 8 + Math.random() * 4,
75
59
  delay: Math.random() * 8,
76
60
  }));
@@ -80,16 +64,14 @@
80
64
  position: { top: number; left: number };
81
65
  size: number;
82
66
  opacity: number;
83
- color: string;
84
67
  timeoutId: ReturnType<typeof setTimeout> | null;
85
68
  }
86
69
 
87
70
  let bubbles = $state<BubbleState[]>(
88
- Array.from({ length: 8 }, (_, i) => ({
71
+ Array.from({ length: 8 }, () => ({
89
72
  position: { top: Math.random() * 80 + 10, left: Math.random() * 80 + 10 },
90
73
  size: Math.random() * 60 + 30,
91
74
  opacity: 0,
92
- color: bubbleColors[i % bubbleColors.length],
93
75
  timeoutId: null,
94
76
  }))
95
77
  );
@@ -361,7 +343,7 @@
361
343
  bind:this={containerRef}
362
344
  class="loading-container fw-player-root"
363
345
  role="status"
364
- aria-label="Loading"
346
+ aria-label={t("loading")}
365
347
  onmousemove={handleMouseMove}
366
348
  onmouseleave={handleMouseLeave}
367
349
  >
@@ -383,7 +365,6 @@
383
365
  left: {particle.left}%;
384
366
  width: {particle.size}px;
385
367
  height: {particle.size}px;
386
- background: {particle.color};
387
368
  animation-duration: {particle.duration}s;
388
369
  animation-delay: {particle.delay}s;
389
370
  "
@@ -399,7 +380,6 @@
399
380
  left: {bubble.position.left}%;
400
381
  width: {bubble.size}px;
401
382
  height: {bubble.size}px;
402
- background: {bubble.color};
403
383
  opacity: {bubble.opacity};
404
384
  "
405
385
  ></div>
@@ -435,7 +415,7 @@
435
415
 
436
416
  <!-- Message -->
437
417
  <div class="message">
438
- {message}
418
+ {effectiveMessage}
439
419
  </div>
440
420
 
441
421
  <!-- Subtle overlay texture -->
@@ -544,11 +524,11 @@
544
524
  min-height: 300px;
545
525
  background: linear-gradient(
546
526
  135deg,
547
- hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,
548
- hsl(var(--tn-bg, 233 23% 17%)) 25%,
549
- hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,
550
- hsl(var(--tn-bg, 233 23% 17%)) 75%,
551
- hsl(var(--tn-bg-dark, 235 21% 11%)) 100%
527
+ hsl(var(--fw-surface-deep, 235 21% 11%)) 0%,
528
+ hsl(var(--fw-surface, 233 23% 17%)) 25%,
529
+ hsl(var(--fw-surface-deep, 235 21% 11%)) 50%,
530
+ hsl(var(--fw-surface, 233 23% 17%)) 75%,
531
+ hsl(var(--fw-surface-deep, 235 21% 11%)) 100%
552
532
  );
553
533
  background-size: 400% 400%;
554
534
  animation: gradientShift 16s ease-in-out infinite;
@@ -584,6 +564,56 @@
584
564
  user-select: none;
585
565
  }
586
566
 
567
+ .particle:nth-child(8n + 1) {
568
+ background: hsl(var(--fw-accent, 218 79% 73%));
569
+ }
570
+ .particle:nth-child(8n + 2) {
571
+ background: hsl(var(--fw-accent-secondary, 268 75% 76%));
572
+ }
573
+ .particle:nth-child(8n + 3) {
574
+ background: hsl(var(--fw-success, 97 52% 51%));
575
+ }
576
+ .particle:nth-child(8n + 4) {
577
+ background: hsl(var(--fw-info, 197 95% 74%));
578
+ }
579
+ .particle:nth-child(8n + 5) {
580
+ background: hsl(var(--fw-danger, 352 86% 71%));
581
+ }
582
+ .particle:nth-child(8n + 6) {
583
+ background: hsl(var(--fw-warning, 33 81% 64%));
584
+ }
585
+ .particle:nth-child(8n + 7) {
586
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.8);
587
+ }
588
+ .particle:nth-child(8n + 8) {
589
+ background: hsl(var(--fw-accent-secondary, 268 75% 76%) / 0.8);
590
+ }
591
+
592
+ .bubble:nth-child(8n + 1) {
593
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.2);
594
+ }
595
+ .bubble:nth-child(8n + 2) {
596
+ background: hsl(var(--fw-accent-secondary, 268 75% 76%) / 0.2);
597
+ }
598
+ .bubble:nth-child(8n + 3) {
599
+ background: hsl(var(--fw-success, 97 52% 51%) / 0.2);
600
+ }
601
+ .bubble:nth-child(8n + 4) {
602
+ background: hsl(var(--fw-info, 197 95% 74%) / 0.2);
603
+ }
604
+ .bubble:nth-child(8n + 5) {
605
+ background: hsl(var(--fw-danger, 352 86% 71%) / 0.2);
606
+ }
607
+ .bubble:nth-child(8n + 6) {
608
+ background: hsl(var(--fw-warning, 33 81% 64%) / 0.2);
609
+ }
610
+ .bubble:nth-child(8n + 7) {
611
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.15);
612
+ }
613
+ .bubble:nth-child(8n + 8) {
614
+ background: hsl(var(--fw-accent-secondary, 268 75% 76%) / 0.15);
615
+ }
616
+
587
617
  .center-logo {
588
618
  position: absolute;
589
619
  top: 50%;
@@ -601,7 +631,7 @@
601
631
  .logo-pulse {
602
632
  position: absolute;
603
633
  border-radius: 50%;
604
- background: rgba(122, 162, 247, 0.15);
634
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.15);
605
635
  animation: logoPulse 3s ease-in-out infinite;
606
636
  -webkit-user-select: none;
607
637
  -moz-user-select: none;
@@ -624,7 +654,7 @@
624
654
  .logo-image {
625
655
  position: relative;
626
656
  z-index: 1;
627
- filter: drop-shadow(0 4px 8px rgba(36, 40, 59, 0.3));
657
+ filter: drop-shadow(0 4px 8px hsl(var(--fw-surface-deep, 235 21% 11%) / 0.3));
628
658
  transition: all 0.3s ease-out;
629
659
  -webkit-user-select: none;
630
660
  -moz-user-select: none;
@@ -634,7 +664,7 @@
634
664
  }
635
665
 
636
666
  .logo-image.hovered {
637
- filter: drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1);
667
+ filter: drop-shadow(0 6px 12px hsl(var(--fw-surface-deep, 235 21% 11%) / 0.4)) brightness(1.1);
638
668
  transform: scale(1.1);
639
669
  cursor: pointer;
640
670
  }
@@ -644,12 +674,12 @@
644
674
  bottom: 20%;
645
675
  left: 50%;
646
676
  transform: translateX(-50%);
647
- color: #a9b1d6;
677
+ color: hsl(var(--fw-text-muted, 227 24% 74%));
648
678
  font-size: 16px;
649
679
  font-weight: 500;
650
680
  text-align: center;
651
681
  animation: fadeInOut 2s ease-in-out infinite;
652
- text-shadow: 0 2px 4px rgba(36, 40, 59, 0.5);
682
+ text-shadow: 0 2px 4px hsl(var(--fw-surface-deep, 235 21% 11%) / 0.5);
653
683
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
654
684
  -webkit-user-select: none;
655
685
  -moz-user-select: none;
@@ -664,9 +694,21 @@
664
694
  right: 0;
665
695
  bottom: 0;
666
696
  background:
667
- radial-gradient(circle at 20% 80%, rgba(122, 162, 247, 0.03) 0%, transparent 50%),
668
- radial-gradient(circle at 80% 20%, rgba(187, 154, 247, 0.03) 0%, transparent 50%),
669
- radial-gradient(circle at 40% 40%, rgba(158, 206, 106, 0.02) 0%, transparent 50%);
697
+ radial-gradient(
698
+ circle at 20% 80%,
699
+ hsl(var(--fw-accent, 218 79% 73%) / 0.03) 0%,
700
+ transparent 50%
701
+ ),
702
+ radial-gradient(
703
+ circle at 80% 20%,
704
+ hsl(var(--fw-accent-secondary, 268 75% 76%) / 0.03) 0%,
705
+ transparent 50%
706
+ ),
707
+ radial-gradient(
708
+ circle at 40% 40%,
709
+ hsl(var(--fw-success, 97 52% 51%) / 0.02) 0%,
710
+ transparent 50%
711
+ );
670
712
  pointer-events: none;
671
713
  -webkit-user-select: none;
672
714
  -moz-user-select: none;
@@ -686,8 +728,8 @@
686
728
  position: absolute;
687
729
  width: 12px;
688
730
  height: 3px;
689
- background-color: #ffffff;
690
- box-shadow: 0 0 8px rgba(255, 255, 255, 0.8);
731
+ background-color: hsl(var(--fw-text-bright, 220 13% 91%));
732
+ box-shadow: 0 0 8px hsl(var(--fw-text-bright, 220 13% 91%) / 0.8);
691
733
  border-radius: 1px;
692
734
  }
693
735