@livepeer-frameworks/player-svelte 0.1.1 → 0.1.2

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 (88) hide show
  1. package/dist/DevModePanel.svelte +266 -127
  2. package/dist/DevModePanel.svelte.d.ts +1 -1
  3. package/dist/DvdLogo.svelte +17 -21
  4. package/dist/Icons.svelte +5 -3
  5. package/dist/Icons.svelte.d.ts +6 -19
  6. package/dist/IdleScreen.svelte +277 -186
  7. package/dist/IdleScreen.svelte.d.ts +1 -1
  8. package/dist/LoadingScreen.svelte +190 -162
  9. package/dist/Player.svelte +244 -111
  10. package/dist/Player.svelte.d.ts +1 -1
  11. package/dist/PlayerControls.svelte +263 -168
  12. package/dist/PlayerControls.svelte.d.ts +1 -1
  13. package/dist/SeekBar.svelte +61 -35
  14. package/dist/SkipIndicator.svelte +4 -4
  15. package/dist/SkipIndicator.svelte.d.ts +1 -1
  16. package/dist/SpeedIndicator.svelte +1 -1
  17. package/dist/StatsPanel.svelte +76 -57
  18. package/dist/StatsPanel.svelte.d.ts +1 -1
  19. package/dist/StreamStateOverlay.svelte +143 -107
  20. package/dist/StreamStateOverlay.svelte.d.ts +1 -1
  21. package/dist/SubtitleRenderer.svelte +46 -43
  22. package/dist/ThumbnailOverlay.svelte +22 -19
  23. package/dist/TitleOverlay.svelte +6 -11
  24. package/dist/components/VolumeIcons.svelte +12 -6
  25. package/dist/global.d.ts +3 -3
  26. package/dist/icons/FullscreenExitIcon.svelte +1 -5
  27. package/dist/icons/FullscreenIcon.svelte +1 -5
  28. package/dist/icons/PauseIcon.svelte +1 -5
  29. package/dist/icons/PictureInPictureIcon.svelte +12 -6
  30. package/dist/icons/PlayIcon.svelte +1 -5
  31. package/dist/icons/SeekToLiveIcon.svelte +1 -5
  32. package/dist/icons/SettingsIcon.svelte +1 -5
  33. package/dist/icons/SkipBackIcon.svelte +1 -5
  34. package/dist/icons/SkipForwardIcon.svelte +1 -5
  35. package/dist/icons/StatsIcon.svelte +1 -5
  36. package/dist/icons/VolumeOffIcon.svelte +1 -5
  37. package/dist/icons/VolumeUpIcon.svelte +1 -5
  38. package/dist/icons/index.d.ts +12 -12
  39. package/dist/icons/index.js +12 -12
  40. package/dist/index.d.ts +24 -24
  41. package/dist/index.js +21 -21
  42. package/dist/stores/index.d.ts +6 -6
  43. package/dist/stores/index.js +6 -6
  44. package/dist/stores/playbackQuality.d.ts +2 -2
  45. package/dist/stores/playbackQuality.js +7 -7
  46. package/dist/stores/playerContext.d.ts +2 -2
  47. package/dist/stores/playerContext.js +17 -17
  48. package/dist/stores/playerController.d.ts +13 -4
  49. package/dist/stores/playerController.js +80 -56
  50. package/dist/stores/playerSelection.d.ts +2 -2
  51. package/dist/stores/playerSelection.js +7 -7
  52. package/dist/stores/streamState.d.ts +2 -2
  53. package/dist/stores/streamState.js +56 -56
  54. package/dist/stores/viewerEndpoints.d.ts +3 -3
  55. package/dist/stores/viewerEndpoints.js +21 -21
  56. package/dist/types.d.ts +1 -1
  57. package/dist/ui/Badge.svelte +9 -10
  58. package/dist/ui/Badge.svelte.d.ts +8 -29
  59. package/dist/ui/Button.svelte +16 -16
  60. package/dist/ui/Button.svelte.d.ts +8 -29
  61. package/dist/ui/Slider.svelte +21 -55
  62. package/dist/ui/badge.js +1 -1
  63. package/dist/ui/button.js +2 -2
  64. package/dist/ui/context-menu/ContextMenuCheckboxItem.svelte +5 -7
  65. package/dist/ui/context-menu/ContextMenuCheckboxItem.svelte.d.ts +6 -27
  66. package/dist/ui/context-menu/ContextMenuContent.svelte +2 -9
  67. package/dist/ui/context-menu/ContextMenuItem.svelte +1 -5
  68. package/dist/ui/context-menu/ContextMenuLabel.svelte +1 -5
  69. package/dist/ui/context-menu/ContextMenuRadioItem.svelte +5 -7
  70. package/dist/ui/context-menu/ContextMenuRadioItem.svelte.d.ts +6 -27
  71. package/dist/ui/context-menu/ContextMenuSeparator.svelte +2 -8
  72. package/dist/ui/context-menu/ContextMenuShortcut.svelte +2 -12
  73. package/dist/ui/context-menu/ContextMenuSubContent.svelte +1 -5
  74. package/package.json +15 -7
  75. package/src/DevModePanel.svelte +1 -0
  76. package/src/Icons.svelte +5 -3
  77. package/src/IdleScreen.svelte +21 -14
  78. package/src/LoadingScreen.svelte +20 -13
  79. package/src/Player.svelte +48 -2
  80. package/src/PlayerControls.svelte +36 -17
  81. package/src/SeekBar.svelte +33 -0
  82. package/src/StreamStateOverlay.svelte +2 -2
  83. package/src/stores/playerController.ts +39 -1
  84. package/src/stores/viewerEndpoints.ts +1 -1
  85. package/src/ui/Badge.svelte +7 -4
  86. package/src/ui/Button.svelte +13 -13
  87. package/src/ui/context-menu/ContextMenuCheckboxItem.svelte +4 -2
  88. package/src/ui/context-menu/ContextMenuRadioItem.svelte +4 -2
@@ -12,16 +12,16 @@
12
12
  - Animated background gradient shifts
13
13
  -->
14
14
  <script lang="ts">
15
- import { onMount, onDestroy } from 'svelte';
16
- import DvdLogo from './DvdLogo.svelte';
17
- import logomarkAsset from './assets/logomark.svg';
15
+ import { onMount, onDestroy } from "svelte";
16
+ import DvdLogo from "./DvdLogo.svelte";
17
+ import logomarkAsset from "./assets/logomark.svg";
18
18
 
19
19
  interface Props {
20
20
  message?: string;
21
21
  logoSrc?: string;
22
22
  }
23
23
 
24
- let { message = 'Waiting for source...', logoSrc }: Props = $props();
24
+ let { message = "Waiting for source...", logoSrc }: Props = $props();
25
25
 
26
26
  // Use imported asset as default if logoSrc not provided
27
27
  let effectiveLogoSrc = $derived(logoSrc || logomarkAsset);
@@ -44,26 +44,26 @@
44
44
 
45
45
  // Tokyo Night inspired pastel colors for bubbles
46
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
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
55
  ];
56
56
 
57
57
  // Particle colors
58
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
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
67
  ];
68
68
 
69
69
  // Generate random particles
@@ -130,7 +130,11 @@
130
130
 
131
131
  const oscillator1 = audioContext.createOscillator();
132
132
  const oscillator2 = audioContext.createOscillator();
133
- const noiseBuffer = audioContext.createBuffer(1, audioContext.sampleRate * 0.1, audioContext.sampleRate);
133
+ const noiseBuffer = audioContext.createBuffer(
134
+ 1,
135
+ audioContext.sampleRate * 0.1,
136
+ audioContext.sampleRate
137
+ );
134
138
  const noiseSource = audioContext.createBufferSource();
135
139
 
136
140
  // Generate white noise for the initial "crack"
@@ -161,8 +165,8 @@
161
165
  oscillator2.frequency.setValueAtTime(3600, audioContext.currentTime);
162
166
  oscillator2.frequency.exponentialRampToValueAtTime(1800, audioContext.currentTime + 0.04);
163
167
 
164
- oscillator1.type = 'triangle';
165
- oscillator2.type = 'sine';
168
+ oscillator1.type = "triangle";
169
+ oscillator2.type = "sine";
166
170
 
167
171
  // Sharp attack, quick decay
168
172
  gainNode1.gain.setValueAtTime(0, audioContext.currentTime);
@@ -198,50 +202,51 @@
198
202
  function playHitmarkerSound() {
199
203
  try {
200
204
  // Embedded hitmarker sound as base64 data URL (matches React implementation)
201
- const hitmarkerDataUrl = 'data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA' +
202
- 'AAD/+1QAAAAAAAAAAAAAAAAAAAAA' +
203
- 'AAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAYAAAnAADs7Ozs7Ozs7Ozs7Ozs7OztiYmJiYmJiYmJi' +
204
- 'YmJiYmJiYomJiYmJiYmJiYmJiYmJiYmxsbGxsbGxsbGxsbGxsbGxsdjY2NjY2NjY2NjY2NjY2NjY////' +
205
- '/////////////////wAAAABMYXZjNTcuMTAAAAAAAAAAAAAAAAAkAkAAAAAAAAAJwOuMZun/+5RkAA8S' +
206
- '/F23AGAaAi0AF0AAAAAInXsEAIRXyQ8D4OQgjEhE3cO7ujuHF0XCOu4G7xKbi3Funu7u7p9dw7unu7u7' +
207
- 'p7u7u6fXcW7om7u7uiU3dxdT67u7p7uHdxelN3cW6fXcW7oXXd3eJTd3d0+u4t3iXdw4up70W4uiPruL' +
208
- 'DzMw8Pz79Y99JfkyfPv5/h9uTJoy79Y99Y97q3vyZPJk0ZfrL6x73Vn+J35dKKS/STQyQ8CAiCPNuRAO' +
209
- 'OqquAx+fzJeBKDAsgAMBuWcBsHKhjJTcCwIALyAvABbI0ZIcCmP8jHJe8gZAdVRp2TpnU/kUXV4iQuBA' +
210
- 'AkAQgisLPvwQ2Jz7wIkIpQ8QOl/KFy75w+2HpTFnRqXLQo0fzlSYRe5Ce9yZMEzRM4xesu95Mo8QQsoM' +
211
- 'H4gLg+fJqkmY3GZJE2kwGfMECJiAdIttoEa2yotfC7jsS2mjKgbzAfEMeiwZpGSUFCQwPKQiWXh0TnkN' +
212
- 'or5SmrKvwHlX2zFxKxPCzRL/+5RkIwADvUxLawwb0GdF6Y1hJlgNNJk+DSRwyQwI6AD2JCiBmhaff0dz' +
213
- 'CEBjgFABAcDNFc3YAEV4hQn0L/QvQnevom+n13eIjoTvABLrHg/L9RzdWXYonHbbbE2K0pX+gkL2g56R' +
214
- 'iwrbuWwhoABzQoMKOAIGAfE4UKk6BhSIJpECBq0CEYmZKYIiAJt72H24dNou7y/Ee7a/3v+MgySemSTY' +
215
- 'mnBAFwIAAGfCJ8/D9YfkwQEBcP38uA1d/EB1T5dZKEsgnuhwZirY5fIMRMdRn7U4OcN2m5NWeYdcPBwX' +
216
- 'DBOsJF1DBYks62pAURqz1hGoGHH/QIoRC80tYAJ8g4f3MPD51sywAbhAn/X9P/75tvZww3gZ3pYPDx/+' +
217
- 'ACO/7//ffHj/D/AAfATC4DYGFA3MRABo0lqWjBOl2yAda1C1BdhduXgm8FGnAQB/lDiEi6j9qw9EHigI' +
218
- 'IOLB6F1eIPd+T6Agc4//lMo6+k3tdttJY2gArU7cN07m2FLSm4gCjyz/+5RECwACwSRZawkdLFGi2mVh' +
219
- '5h4LfFdPVPGACViTavaeMAAV0UkkEsDhxxJwqF04on002mZah8w9+5ItfSAoyZa1dchnPpLmAEKrVMRA' +
220
- '//sD8w0WsB4xiw4JqaZMB45TdpIuXXUPf8Bpa35p/jQIAOAuZkmUeJoM5W6L2gqqO6rTuHjUTDnhy4Qi' +
221
- 'K348vtFysOizShoHbBpsPRYcSINCbiN4XOLPPAgq3dW2Ga7SlyiKXBV7W1RQl5BiiVGkwayJfEnPxgXk' +
222
- 'QeZxxzyhTuLO2XFUDDstoc6CkM1J8QZAjUN3bM8580cRygNfmPAELGjIH0Z/0A+8csyH/4eHvgAf8APg' +
223
- 'ABmZ98AARAADP////Dw8PHEmIpgGttpJQJsmZjq5nPQ8j5VqWW1evqdjP182PA6tHJZgkC5iSbEQkyJS' +
224
- 'z/BvP3eucLKN0+Wiza4feKKFBqiAEBAMXyYni5NZc16CDl/QY9j6BAcWSmQYcIcoMHYoQNBiIBgIBUAz' +
225
- 'QUMSnjj/+5RkCwADsFLffjEAAjrJe63JHACO6WtlnPMACKaCK1uMMADU5dI6JhW2cam98UlRmY4ihyKF' +
226
- 'rNsgpZd5PYgBALnYofKEt82De0GbW1DLibvFDK+bSeOm8qKdqUFZ7uiK8XMPHyqm3pTxUvcunUfxXEo9' +
227
- 'RNe5b/8vfCD3kzDN7vTtHyaIcntVDAYBAUBAAAAQBI2vguYNsHWm5AR3mZtZib8WAHFvz2Kf9//iYvlR' +
228
- 'B/+n///////////+UH7XoIDMoJAEAMtj8JshJPRwklVqNSpYnalfE+VzNCAISCoxVHEpIo/WrTiMvP7V' +
229
- 'TujOPnOglLbMLN/pq/d2Y4lRJIkSnPlUSJEjSKJqM41d88zWtMzP+fCOORmc9NeM+f1nnO//efM52/fG' +
230
- '/ef385+5u+u1bRJkwU8FAkEItZpkRYeQYcAgZTEYlaZa2yROLeC0qdX73rZJJ/d2f6v6Or0u/+5FBYcn' +
231
- 'g0MlCiQTR9GUU5LScmSuSlH00IWqXA6jlw4BEcD/+5REEAAi3RtU+eYbGF1E+lk9g0YJzLUgh7BlQVGT' +
232
- 'ZJD0jKhhTNVilqrMzFRK+x/szcMKBWKep4NP1A0DR6RESkTp5Z1Q9Y8REgqMg1DpUBPleeqlRQcerBpM' +
233
- 'jiURHVD4XwAALhAgbxxlxYD5OFkG8oQRPB2EpsxSCNVlgcYUqoAyiVJmaARlkwplICfPoUy/zWEzM2pc' +
234
- 'NYzAQNJDSniEYecSEqxFEzQqEvUFGnvzwUfcRlpZ9T2LCR5QdDQDDhKICAjpJCagpRo9UQRPClZZlg6E' +
235
- 'p9DMTkTl+okuhRIVIzAQEf9L+Mx/DUjqmqN6kX7M36lS4zgLyJV3iV6j3xF8kJduJawVw1nndAlBaLLg' +
236
- 'JupwsTcLkxmJgFLgSzoCmHjSNGSqkGPCpnNqTXIwolf6qlVWN+q/su37HzgrES1pWGg3KnWh0FXCVniJ' +
237
- '9K5b4iCrpLEuIcFTqwkVLFiqgaDqCCSMVWqxBAVCFOLVrVahm2ahUThUKJnmFCw15hD0Qhb/+5REEAhC' +
238
- 'YSRCSQEb4FOGaBUMI6JIRYC0QIB2SQsgGpgwDghgIlS6FU8VBXDoiBp5Y9gtkVnhEhYBdJFQ7kQ3w1yp' +
239
- '0NB2CoNPEttZ1/aeDUAAA26FEghWgEKNVAVWkFAQEmMK2Uwk/qI0hqUb/4epVIZH1ai6szf6kzH1f2ar' +
240
- 'xYGS9FcOsN5UlJLQt///+oo0FRDTUQ0FBQr9f5LxXP+mEUfk0AIrf/5GRmQ0//mX//ZbLP5b5GrWSz+W' +
241
- 'SkZMrWyyyy2GRqyggVRyMv////////st//sn/yyVDI1l8mVgoYGDCOqiqIQBxmvxWCggTpZZZD//aWfy' +
242
- 'yWf/y/7KGDA0ssBggTof9k/+WS/8slQyMp/5Nfln8WAqGcUbULCrKxT9ISF+kKsxQWpMQU1FMy4xMDCq' +
243
- 'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq' +
244
- 'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=';
205
+ const hitmarkerDataUrl =
206
+ "data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA" +
207
+ "AAD/+1QAAAAAAAAAAAAAAAAAAAAA" +
208
+ "AAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAYAAAnAADs7Ozs7Ozs7Ozs7Ozs7OztiYmJiYmJiYmJi" +
209
+ "YmJiYmJiYomJiYmJiYmJiYmJiYmJiYmxsbGxsbGxsbGxsbGxsbGxsdjY2NjY2NjY2NjY2NjY2NjY////" +
210
+ "/////////////////wAAAABMYXZjNTcuMTAAAAAAAAAAAAAAAAAkAkAAAAAAAAAJwOuMZun/+5RkAA8S" +
211
+ "/F23AGAaAi0AF0AAAAAInXsEAIRXyQ8D4OQgjEhE3cO7ujuHF0XCOu4G7xKbi3Funu7u7p9dw7unu7u7" +
212
+ "p7u7u6fXcW7om7u7uiU3dxdT67u7p7uHdxelN3cW6fXcW7oXXd3eJTd3d0+u4t3iXdw4up70W4uiPruL" +
213
+ "DzMw8Pz79Y99JfkyfPv5/h9uTJoy79Y99Y97q3vyZPJk0ZfrL6x73Vn+J35dKKS/STQyQ8CAiCPNuRAO" +
214
+ "OqquAx+fzJeBKDAsgAMBuWcBsHKhjJTcCwIALyAvABbI0ZIcCmP8jHJe8gZAdVRp2TpnU/kUXV4iQuBA" +
215
+ "AkAQgisLPvwQ2Jz7wIkIpQ8QOl/KFy75w+2HpTFnRqXLQo0fzlSYRe5Ce9yZMEzRM4xesu95Mo8QQsoM" +
216
+ "H4gLg+fJqkmY3GZJE2kwGfMECJiAdIttoEa2yotfC7jsS2mjKgbzAfEMeiwZpGSUFCQwPKQiWXh0TnkN" +
217
+ "or5SmrKvwHlX2zFxKxPCzRL/+5RkIwADvUxLawwb0GdF6Y1hJlgNNJk+DSRwyQwI6AD2JCiBmhaff0dz" +
218
+ "CEBjgFABAcDNFc3YAEV4hQn0L/QvQnevom+n13eIjoTvABLrHg/L9RzdWXYonHbbbE2K0pX+gkL2g56R" +
219
+ "iwrbuWwhoABzQoMKOAIGAfE4UKk6BhSIJpECBq0CEYmZKYIiAJt72H24dNou7y/Ee7a/3v+MgySemSTY" +
220
+ "mnBAFwIAAGfCJ8/D9YfkwQEBcP38uA1d/EB1T5dZKEsgnuhwZirY5fIMRMdRn7U4OcN2m5NWeYdcPBwX" +
221
+ "DBOsJF1DBYks62pAURqz1hGoGHH/QIoRC80tYAJ8g4f3MPD51sywAbhAn/X9P/75tvZww3gZ3pYPDx/+" +
222
+ "ACO/7//ffHj/D/AAfATC4DYGFA3MRABo0lqWjBOl2yAda1C1BdhduXgm8FGnAQB/lDiEi6j9qw9EHigI" +
223
+ "IOLB6F1eIPd+T6Agc4//lMo6+k3tdttJY2gArU7cN07m2FLSm4gCjyz/+5RECwACwSRZawkdLFGi2mVh" +
224
+ "5h4LfFdPVPGACViTavaeMAAV0UkkEsDhxxJwqF04on002mZah8w9+5ItfSAoyZa1dchnPpLmAEKrVMRA" +
225
+ "//sD8w0WsB4xiw4JqaZMB45TdpIuXXUPf8Bpa35p/jQIAOAuZkmUeJoM5W6L2gqqO6rTuHjUTDnhy4Qi" +
226
+ "K348vtFysOizShoHbBpsPRYcSINCbiN4XOLPPAgq3dW2Ga7SlyiKXBV7W1RQl5BiiVGkwayJfEnPxgXk" +
227
+ "QeZxxzyhTuLO2XFUDDstoc6CkM1J8QZAjUN3bM8580cRygNfmPAELGjIH0Z/0A+8csyH/4eHvgAf8APg" +
228
+ "ABmZ98AARAADP////Dw8PHEmIpgGttpJQJsmZjq5nPQ8j5VqWW1evqdjP182PA6tHJZgkC5iSbEQkyJS" +
229
+ "z/BvP3eucLKN0+Wiza4feKKFBqiAEBAMXyYni5NZc16CDl/QY9j6BAcWSmQYcIcoMHYoQNBiIBgIBUAz" +
230
+ "QUMSnjj/+5RkCwADsFLffjEAAjrJe63JHACO6WtlnPMACKaCK1uMMADU5dI6JhW2cam98UlRmY4ihyKF" +
231
+ "rNsgpZd5PYgBALnYofKEt82De0GbW1DLibvFDK+bSeOm8qKdqUFZ7uiK8XMPHyqm3pTxUvcunUfxXEo9" +
232
+ "RNe5b/8vfCD3kzDN7vTtHyaIcntVDAYBAUBAAAAQBI2vguYNsHWm5AR3mZtZib8WAHFvz2Kf9//iYvlR" +
233
+ "B/+n///////////+UH7XoIDMoJAEAMtj8JshJPRwklVqNSpYnalfE+VzNCAISCoxVHEpIo/WrTiMvP7V" +
234
+ "TujOPnOglLbMLN/pq/d2Y4lRJIkSnPlUSJEjSKJqM41d88zWtMzP+fCOORmc9NeM+f1nnO//efM52/fG" +
235
+ "/ef385+5u+u1bRJkwU8FAkEItZpkRYeQYcAgZTEYlaZa2yROLeC0qdX73rZJJ/d2f6v6Or0u/+5FBYcn" +
236
+ "g0MlCiQTR9GUU5LScmSuSlH00IWqXA6jlw4BEcD/+5REEAAi3RtU+eYbGF1E+lk9g0YJzLUgh7BlQVGT" +
237
+ "ZJD0jKhhTNVilqrMzFRK+x/szcMKBWKep4NP1A0DR6RESkTp5Z1Q9Y8REgqMg1DpUBPleeqlRQcerBpM" +
238
+ "jiURHVD4XwAALhAgbxxlxYD5OFkG8oQRPB2EpsxSCNVlgcYUqoAyiVJmaARlkwplICfPoUy/zWEzM2pc" +
239
+ "NYzAQNJDSniEYecSEqxFEzQqEvUFGnvzwUfcRlpZ9T2LCR5QdDQDDhKICAjpJCagpRo9UQRPClZZlg6E" +
240
+ "p9DMTkTl+okuhRIVIzAQEf9L+Mx/DUjqmqN6kX7M36lS4zgLyJV3iV6j3xF8kJduJawVw1nndAlBaLLg" +
241
+ "JupwsTcLkxmJgFLgSzoCmHjSNGSqkGPCpnNqTXIwolf6qlVWN+q/su37HzgrES1pWGg3KnWh0FXCVniJ" +
242
+ "9K5b4iCrpLEuIcFTqwkVLFiqgaDqCCSMVWqxBAVCFOLVrVahm2ahUThUKJnmFCw15hD0Qhb/+5REEAhC" +
243
+ "YSRCSQEb4FOGaBUMI6JIRYC0QIB2SQsgGpgwDghgIlS6FU8VBXDoiBp5Y9gtkVnhEhYBdJFQ7kQ3w1yp" +
244
+ "0NB2CoNPEttZ1/aeDUAAA26FEghWgEKNVAVWkFAQEmMK2Uwk/qI0hqUb/4epVIZH1ai6szf6kzH1f2ar" +
245
+ "xYGS9FcOsN5UlJLQt///+oo0FRDTUQ0FBQr9f5LxXP+mEUfk0AIrf/5GRmQ0//mX//ZbLP5b5GrWSz+W" +
246
+ "SkZMrWyyyy2GRqyggVRyMv////////st//sn/yyVDI1l8mVgoYGDCOqiqIQBxmvxWCggTpZZZD//aWfy" +
247
+ "yWf/y/7KGDA0ssBggTof9k/+WS/8slQyMp/5Nfln8WAqGcUbULCrKxT9ISF+kKsxQWpMQU1FMy4xMDCq" +
248
+ "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" +
249
+ "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=";
245
250
 
246
251
  const audio = new Audio(hitmarkerDataUrl);
247
252
  audio.volume = 0.3;
@@ -273,7 +278,7 @@
273
278
 
274
279
  // Remove hitmarker after animation
275
280
  setTimeout(() => {
276
- hitmarkers = hitmarkers.filter(h => h.id !== newHitmarker.id);
281
+ hitmarkers = hitmarkers.filter((h) => h.id !== newHitmarker.id);
277
282
  }, 600);
278
283
  }
279
284
 
@@ -346,20 +351,111 @@
346
351
 
347
352
  // Cleanup on destroy
348
353
  onDestroy(() => {
349
- bubbles.forEach(bubble => {
354
+ bubbles.forEach((bubble) => {
350
355
  if (bubble.timeoutId) clearTimeout(bubble.timeoutId);
351
356
  });
352
357
  });
353
358
  </script>
354
359
 
360
+ <div
361
+ bind:this={containerRef}
362
+ class="loading-container fw-player-root"
363
+ role="status"
364
+ aria-label="Loading"
365
+ onmousemove={handleMouseMove}
366
+ onmouseleave={handleMouseLeave}
367
+ >
368
+ <!-- Hitmarkers -->
369
+ {#each hitmarkers as hitmarker (hitmarker.id)}
370
+ <div class="hitmarker" style="left: {hitmarker.x}px; top: {hitmarker.y}px;">
371
+ <div class="hitmarker-line tl"></div>
372
+ <div class="hitmarker-line tr"></div>
373
+ <div class="hitmarker-line bl"></div>
374
+ <div class="hitmarker-line br"></div>
375
+ </div>
376
+ {/each}
377
+
378
+ <!-- Floating particles -->
379
+ {#each particles as particle, _i}
380
+ <div
381
+ class="particle"
382
+ style="
383
+ left: {particle.left}%;
384
+ width: {particle.size}px;
385
+ height: {particle.size}px;
386
+ background: {particle.color};
387
+ animation-duration: {particle.duration}s;
388
+ animation-delay: {particle.delay}s;
389
+ "
390
+ ></div>
391
+ {/each}
392
+
393
+ <!-- Animated bubbles -->
394
+ {#each bubbles as bubble, _i}
395
+ <div
396
+ class="bubble"
397
+ style="
398
+ top: {bubble.position.top}%;
399
+ left: {bubble.position.left}%;
400
+ width: {bubble.size}px;
401
+ height: {bubble.size}px;
402
+ background: {bubble.color};
403
+ opacity: {bubble.opacity};
404
+ "
405
+ ></div>
406
+ {/each}
407
+
408
+ <!-- Center logo with push-away effect -->
409
+ <div
410
+ class="center-logo"
411
+ style="transform: translate(-50%, -50%) translate({offset.x}px, {offset.y}px);"
412
+ >
413
+ <!-- Pulsing circle background -->
414
+ <div
415
+ class="logo-pulse"
416
+ class:hovered={isHovered}
417
+ style="width: {logoSize * 1.4}px; height: {logoSize * 1.4}px;"
418
+ ></div>
419
+
420
+ <!-- Logo image -->
421
+ <button type="button" class="logo-button" onclick={handleLogoClick} aria-label="Logo">
422
+ <img
423
+ src={effectiveLogoSrc}
424
+ alt=""
425
+ class="logo-image"
426
+ class:hovered={isHovered}
427
+ style="width: {logoSize}px; height: {logoSize}px;"
428
+ draggable="false"
429
+ />
430
+ </button>
431
+ </div>
432
+
433
+ <!-- Bouncing DVD Logo -->
434
+ <DvdLogo parentRef={containerRef} scale={0.08} />
435
+
436
+ <!-- Message -->
437
+ <div class="message">
438
+ {message}
439
+ </div>
440
+
441
+ <!-- Subtle overlay texture -->
442
+ <div class="overlay-texture"></div>
443
+ </div>
444
+
355
445
  <style>
356
446
  @keyframes fadeInOut {
357
- 0%, 100% { opacity: 0.6; }
358
- 50% { opacity: 0.9; }
447
+ 0%,
448
+ 100% {
449
+ opacity: 0.6;
450
+ }
451
+ 50% {
452
+ opacity: 0.9;
453
+ }
359
454
  }
360
455
 
361
456
  @keyframes logoPulse {
362
- 0%, 100% {
457
+ 0%,
458
+ 100% {
363
459
  opacity: 0.15;
364
460
  transform: scale(1);
365
461
  }
@@ -374,8 +470,12 @@
374
470
  transform: translateY(100vh) rotate(0deg);
375
471
  opacity: 0;
376
472
  }
377
- 10% { opacity: 0.6; }
378
- 90% { opacity: 0.6; }
473
+ 10% {
474
+ opacity: 0.6;
475
+ }
476
+ 90% {
477
+ opacity: 0.6;
478
+ }
379
479
  100% {
380
480
  transform: translateY(-100px) rotate(360deg);
381
481
  opacity: 0;
@@ -383,8 +483,13 @@
383
483
  }
384
484
 
385
485
  @keyframes gradientShift {
386
- 0%, 100% { background-position: 0% 50%; }
387
- 50% { background-position: 100% 50%; }
486
+ 0%,
487
+ 100% {
488
+ background-position: 0% 50%;
489
+ }
490
+ 50% {
491
+ background-position: 100% 50%;
492
+ }
388
493
  }
389
494
 
390
495
  @keyframes hitmarkerFade {
@@ -437,7 +542,8 @@
437
542
  width: 100%;
438
543
  height: 100%;
439
544
  min-height: 300px;
440
- background: linear-gradient(135deg,
545
+ background: linear-gradient(
546
+ 135deg,
441
547
  hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,
442
548
  hsl(var(--tn-bg, 233 23% 17%)) 25%,
443
549
  hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,
@@ -509,6 +615,12 @@
509
615
  transform: scale(1.2);
510
616
  }
511
617
 
618
+ .fw-player-root .logo-button {
619
+ all: unset;
620
+ cursor: pointer;
621
+ display: block;
622
+ }
623
+
512
624
  .fw-player-root .logo-image {
513
625
  position: relative;
514
626
  z-index: 1;
@@ -538,7 +650,7 @@
538
650
  text-align: center;
539
651
  animation: fadeInOut 2s ease-in-out infinite;
540
652
  text-shadow: 0 2px 4px rgba(36, 40, 59, 0.5);
541
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
653
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
542
654
  -webkit-user-select: none;
543
655
  -moz-user-select: none;
544
656
  user-select: none;
@@ -603,87 +715,3 @@
603
715
  animation: hitmarkerFade45 0.6s ease-out forwards;
604
716
  }
605
717
  </style>
606
-
607
- <div
608
- bind:this={containerRef}
609
- class="loading-container fw-player-root"
610
- role="status"
611
- aria-label="Loading"
612
- onmousemove={handleMouseMove}
613
- onmouseleave={handleMouseLeave}
614
- >
615
- <!-- Hitmarkers -->
616
- {#each hitmarkers as hitmarker (hitmarker.id)}
617
- <div class="hitmarker" style="left: {hitmarker.x}px; top: {hitmarker.y}px;">
618
- <div class="hitmarker-line tl"></div>
619
- <div class="hitmarker-line tr"></div>
620
- <div class="hitmarker-line bl"></div>
621
- <div class="hitmarker-line br"></div>
622
- </div>
623
- {/each}
624
-
625
- <!-- Floating particles -->
626
- {#each particles as particle, _i}
627
- <div
628
- class="particle"
629
- style="
630
- left: {particle.left}%;
631
- width: {particle.size}px;
632
- height: {particle.size}px;
633
- background: {particle.color};
634
- animation-duration: {particle.duration}s;
635
- animation-delay: {particle.delay}s;
636
- "
637
- />
638
- {/each}
639
-
640
- <!-- Animated bubbles -->
641
- {#each bubbles as bubble, _i}
642
- <div
643
- class="bubble"
644
- style="
645
- top: {bubble.position.top}%;
646
- left: {bubble.position.left}%;
647
- width: {bubble.size}px;
648
- height: {bubble.size}px;
649
- background: {bubble.color};
650
- opacity: {bubble.opacity};
651
- "
652
- />
653
- {/each}
654
-
655
- <!-- Center logo with push-away effect -->
656
- <div
657
- class="center-logo"
658
- style="transform: translate(-50%, -50%) translate({offset.x}px, {offset.y}px);"
659
- >
660
- <!-- Pulsing circle background -->
661
- <div
662
- class="logo-pulse"
663
- class:hovered={isHovered}
664
- style="width: {logoSize * 1.4}px; height: {logoSize * 1.4}px;"
665
- />
666
-
667
- <!-- Logo image -->
668
- <img
669
- src={effectiveLogoSrc}
670
- alt="Logo"
671
- class="logo-image"
672
- class:hovered={isHovered}
673
- style="width: {logoSize}px; height: {logoSize}px;"
674
- onclick={handleLogoClick}
675
- draggable="false"
676
- />
677
- </div>
678
-
679
- <!-- Bouncing DVD Logo -->
680
- <DvdLogo parentRef={containerRef} scale={0.08} />
681
-
682
- <!-- Message -->
683
- <div class="message">
684
- {message}
685
- </div>
686
-
687
- <!-- Subtle overlay texture -->
688
- <div class="overlay-texture" />
689
- </div>