@zezosoft/react-player 1.0.1 → 1.0.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.
package/README.md CHANGED
@@ -1,370 +1,137 @@
1
1
  # @zezosoft/react-player 🎬
2
2
 
3
- A powerful and flexible **React video player** by **Zezosoft**, supporting HLS, MP4, DASH, YouTube, preview thumbnails, tracking, subtitles, episode playback, ads, and advanced controls.
3
+ A React video player by Zezosoft supporting HLS, MP4, DASH, preview thumbnails, tracking, subtitles, episode playback, and ads.
4
4
 
5
- ---
5
+ ## ✨ Features
6
6
 
7
- ## 🚀 Features
8
-
9
- **Multiple Video Formats** - HLS, MP4, DASH, YouTube
10
- **Preview Thumbnails on Hover** - Show video previews while scrubbing
11
- **Event Tracking** - Track views, watch time, and user interactions
12
- **Customizable Player Size & Controls** - Full control over player appearance
13
- ✅ **Time-Stamped Labels** - Video chapters with time markers
14
- **Subtitles (WebVTT)** - Multi-language subtitle support with custom styling
15
- ✅ **Intro Skipping** - Automatic skip intro button
16
- ✅ **Episode Playback** - Next episode auto-play and playlist support
17
- ✅ **Ad Support** - Pre-roll, mid-roll, post-roll, and overlay ads
18
- ✅ **Watch History** - Track user progress and resume playback
19
-
20
- ---
7
+ - **Formats** — HLS, MP4, DASH (via hls.js and dash.js)
8
+ - 🖼️ **Preview thumbnails** — Hover over seek bar for scrubbing previews
9
+ - 📊 **Event tracking** Views, watch time, user interactions
10
+ - 💬 **Subtitles** WebVTT with customizable styling
11
+ - ⏭️ **Intro skip** Skip intro button with configurable time range
12
+ - 📺 **Episodes** Next episode auto-play and playlist
13
+ - 📢 **Ads** — Pre-roll, mid-roll, post-roll video ads
14
+ - 📚 **Watch history** Resume playback, progress tracking
21
15
 
22
16
  ## 📦 Installation
23
17
 
24
- Install the package using **npm** or **yarn**:
25
-
26
18
  ```sh
27
19
  npm install @zezosoft/react-player
28
- ```
29
-
30
- or
31
-
32
- ```sh
20
+ # or
21
+ pnpm add @zezosoft/react-player
22
+ # or
33
23
  yarn add @zezosoft/react-player
34
24
  ```
35
25
 
36
- ---
26
+ **Peer dependencies:** `react`, `react-dom`, `hls.js`, `lucide-react`, `zustand`
37
27
 
38
- ## 🛠️ Quick Start
39
-
40
- Here's a simple example to get you started:
28
+ ## 🚀 Quick Start
41
29
 
42
30
  ```tsx
43
31
  import { VideoPlayer } from "@zezosoft/react-player";
44
32
 
45
33
  function App() {
46
34
  return (
47
- <VideoPlayer
48
- video={{
49
- src: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8",
50
- title: "My Video",
51
- poster: "https://example.com/poster.jpg",
52
- }}
53
- style={{
54
- width: "100%",
55
- height: "auto",
56
- }}
57
- />
58
- );
59
- }
60
- ```
61
-
62
- ---
63
-
64
- ## 📖 Complete Example
65
-
66
- Here's a comprehensive example showing all available features:
67
-
68
- ```tsx
69
- import { useCallback, useRef } from "react";
70
- import { VideoPlayer } from "@zezosoft/react-player";
71
-
72
- function App() {
73
- const previewImage = useRef("");
74
-
75
- const updatePreviewImage = (hoverTime: number) => {
76
- const url = `https://fakeimg.pl/720x405?text=${hoverTime}`;
77
- const image = document.createElement("img");
78
- image.src = url;
79
- image.onload = () => {
80
- previewImage.current = url;
81
- };
82
- };
83
-
84
- const handleGettingPreview = useCallback((hoverTime: number) => {
85
- updatePreviewImage(hoverTime);
86
- return previewImage.current;
87
- }, []);
88
-
89
- return (
90
- <div style={{ width: "720px", margin: "0 auto" }}>
35
+ <div style={{ position: "relative", width: "100%", aspectRatio: "16/9" }}>
91
36
  <VideoPlayer
92
37
  video={{
93
- src: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8",
94
- title: "Mehmaan",
95
- poster: "https://i.ytimg.com/vi/VAUfyxw-Yvk/maxresdefault.jpg",
96
- type: "hls",
97
- isTrailer: false,
98
- showControls: true,
99
- isMute: false,
100
- startFrom: 0,
101
- }}
102
- style={{
103
- width: "720px",
104
- height: "405px",
105
- className: "my-video-player",
106
- subtitleStyle: {
107
- fontSize: "1.5rem",
108
- backgroundColor: "rgba(0, 0, 0, 0.8)",
109
- textColor: "#ffffff",
110
- position: "bottom",
111
- borderRadius: "8px",
112
- padding: "8px 16px",
113
- maxWidth: "80%",
114
- },
115
- }}
116
- events={{
117
- onEnded: (e) => console.log("Video ended", e),
118
- onError: (e) => console.error("Video error", e),
119
- onClose: () => console.log("Player closed"),
120
- onWatchHistoryUpdate: (data) => {
121
- console.log("Watch history:", data);
122
- // Save to your backend
123
- },
124
- }}
125
- features={{
126
- timeCodes: [
127
- { fromMs: 0, description: "Introduction" },
128
- { fromMs: 130000, description: "Exciting Scene" },
129
- { fromMs: 270000, description: "Climax" },
130
- ],
131
- getPreviewScreenUrl: handleGettingPreview,
132
- tracking: {
133
- onViewed: () => console.log("Video Viewed"),
134
- onWatchTimeUpdated: (e) => {
135
- console.log("Watch Time Updated", {
136
- watchTime: e.watchTime,
137
- currentTime: e.currentTime,
138
- duration: e.duration,
139
- });
140
- },
141
- },
142
- subtitles: [
143
- {
144
- lang: "en",
145
- label: "English",
146
- url: "https://example.com/subtitles-en.vtt",
147
- },
148
- {
149
- lang: "hi",
150
- label: "Hindi",
151
- url: "https://example.com/subtitles-hi.vtt",
152
- },
153
- ],
154
- episodeList: [
155
- { id: 1, title: "Episode 1", url: "https://example.com/ep1.m3u8" },
156
- { id: 2, title: "Episode 2", url: "https://example.com/ep2.m3u8" },
157
- ],
158
- currentEpisodeIndex: 0,
159
- intro: { start: 5, end: 20 },
160
- nextEpisodeConfig: { showAtTime: 300, showAtEnd: true },
161
- ads: {
162
- preRoll: {
163
- id: "preroll-1",
164
- type: "pre-roll",
165
- time: 0,
166
- adUrl: "https://example.com/ad.mp4",
167
- skipable: true,
168
- skipAfter: 5,
169
- },
170
- midRoll: [
171
- {
172
- id: "midroll-1",
173
- type: "mid-roll",
174
- time: 120,
175
- adUrl: "https://example.com/mid-ad.mp4",
176
- skipable: false,
177
- },
178
- ],
179
- onAdStart: (adBreak) => console.log("Ad started", adBreak),
180
- onAdEnd: (adBreak) => console.log("Ad ended", adBreak),
181
- },
38
+ src: "https://example.com/playlist.m3u8",
39
+ title: "My Video",
40
+ poster: "https://example.com/poster.jpg",
182
41
  }}
42
+ style={{ width: "100%", height: "100%" }}
183
43
  />
184
44
  </div>
185
45
  );
186
46
  }
187
-
188
- export default App;
189
47
  ```
190
48
 
191
- ---
192
-
193
- ## 📚 Props Reference
194
-
195
- The `VideoPlayer` component accepts four main prop objects:
196
-
197
- ### `video` (Required)
198
-
199
- Video source and basic configuration.
200
-
201
- | Prop | Type | Default | Description |
202
- | -------------- | -------------------------------------------------- | ------------ | ------------------------------------------------------- |
203
- | `src` | `string` | **Required** | Video source URL (MP4, HLS, DASH, YouTube, etc.) |
204
- | `title` | `string` | `""` | Title of the video displayed in the player header |
205
- | `poster` | `string` | `""` | URL of the poster/thumbnail image shown before playback |
206
- | `type` | `"hls" \| "dash" \| "mp4" \| "youtube" \| "other"` | `undefined` | Video format type (auto-detected if not provided) |
207
- | `isTrailer` | `boolean` | `false` | If `true`, shows trailer-specific UI elements |
208
- | `showControls` | `boolean` | `true` | Show/hide player controls |
209
- | `isMute` | `boolean` | `false` | Start video muted |
210
- | `startFrom` | `number` | `0` | Start playback from specific time in seconds |
211
-
212
- ### `style` (Optional)
213
-
214
- Styling and appearance configuration.
215
-
216
- | Prop | Type | Default | Description |
217
- | --------------- | --------------------- | ----------- | ---------------------------------------------- |
218
- | `className` | `string` | `undefined` | Custom CSS class name for the player container |
219
- | `width` | `string` | `"100%"` | Player width (e.g., `"720px"`, `"100%"`) |
220
- | `height` | `string` | `"auto"` | Player height (e.g., `"405px"`, `"auto"`) |
221
- | `subtitleStyle` | `SubtitleStyleConfig` | `undefined` | Custom styling for subtitles (see below) |
222
-
223
- **SubtitleStyleConfig:**
224
-
225
- | Prop | Type | Default | Description |
226
- | ----------------- | ------------------------------- | --------------------------------------------- | ---------------------------------- |
227
- | `fontSize` | `string` | `"1.75rem"` | Subtitle font size |
228
- | `backgroundColor` | `string` | `"linear-gradient(135deg, #fbbf24, #f59e0b)"` | Subtitle background color/gradient |
229
- | `textColor` | `string` | `"#000000"` | Subtitle text color |
230
- | `position` | `"top" \| "center" \| "bottom"` | `"bottom"` | Vertical position of subtitles |
231
- | `borderRadius` | `string` | `"12px"` | Border radius of subtitle box |
232
- | `padding` | `string` | `"12px 20px"` | Padding inside subtitle box |
233
- | `maxWidth` | `string` | `"80%"` | Maximum width of subtitle box |
234
-
235
- ### `events` (Optional)
236
-
237
- Event callbacks for player lifecycle.
238
-
239
- | Prop | Type | Description |
240
- | ---------------------- | ------------------------------------------------------------- | -------------------------------------------------- |
241
- | `onEnded` | `(e: React.SyntheticEvent<HTMLVideoElement>) => void` | Called when video playback ends |
242
- | `onError` | `(e?: React.SyntheticEvent<HTMLVideoElement, Event>) => void` | Called when video encounters an error |
243
- | `onClose` | `() => void` | Called when player is closed |
244
- | `onWatchHistoryUpdate` | `(data: WatchHistoryData) => void` | Called when player closes with watch progress data |
245
-
246
- **WatchHistoryData:**
247
-
248
- ```typescript
249
- {
250
- currentTime: number; // Current playback time in seconds
251
- duration: number; // Total video duration in seconds
252
- progress: number; // Progress percentage (0-100)
253
- isCompleted: boolean; // Whether video was fully watched
254
- watchedAt: number; // Timestamp when watch session ended
255
- }
256
- ```
257
-
258
- ### `features` (Optional)
259
-
260
- Advanced features and functionality.
261
-
262
- | Prop | Type | Default | Description |
263
- | --------------------- | ------------------------------------------------ | ----------- | ------------------------------------------------------------------------ |
264
- | `timeCodes` | `Array<{ fromMs: number, description: string }>` | `[]` | Time-based chapter markers (in milliseconds) |
265
- | `getPreviewScreenUrl` | `(hoverTimeValue: number) => string` | `undefined` | Function to generate preview thumbnail URLs while hovering over seek bar |
266
- | `tracking` | `TrackingConfig` | `undefined` | Event tracking configuration (see below) |
267
- | `subtitles` | `Array<SubtitleTrack>` | `[]` | Subtitle tracks in WebVTT format |
268
- | `episodeList` | `Array<Episode>` | `[]` | List of episodes for playlist/autoplay |
269
- | `currentEpisodeIndex` | `number` | `0` | Index of currently playing episode |
270
- | `intro` | `{ start: number, end: number }` | `undefined` | Intro skip configuration (times in seconds) |
271
- | `nextEpisodeConfig` | `{ showAtTime?: number, showAtEnd?: boolean }` | `undefined` | Configuration for next episode button |
272
- | `ads` | `AdConfig` | `undefined` | Advertisement configuration (see below) |
273
-
274
- **TrackingConfig:**
275
-
276
- ```typescript
277
- {
278
- onViewed?: () => void;
279
- onWatchTimeUpdated?: (e: {
280
- watchTime?: number; // Total watch time in seconds
281
- currentTime: number; // Current playback position
282
- duration: number; // Total video duration
283
- }) => void;
284
- }
285
- ```
286
-
287
- **SubtitleTrack:**
49
+ ## 📖 Props
50
+
51
+ The player accepts four props: `video` (required), `style`, `events`, and `features`.
52
+
53
+ ### `video` (required)
54
+
55
+ | Prop | Type | Default | Description |
56
+ | -------------- | --------- | --------- | ---------------------------------------- |
57
+ | `src` | `string` | required | Video URL (HLS, DASH, MP4) |
58
+ | `title` | `string` | `""` | Title shown in header |
59
+ | `poster` | `string` | `""` | Poster image URL |
60
+ | `type` | `string` | auto | `"hls"` \| `"dash"` \| `"mp4"` \| `"other"` |
61
+ | `isTrailer` | `boolean` | `false` | Trailer mode (hides ads) |
62
+ | `showControls`| `boolean` | `true` | Show/hide controls |
63
+ | `isMute` | `boolean` | `false` | Start muted |
64
+ | `startFrom` | `number` | `0` | Start time in seconds |
65
+ | `isLive` | `boolean` | `false` | Live stream mode |
66
+
67
+ ### `style`
68
+
69
+ | Prop | Type | Description |
70
+ | --------------- | --------------------- | ------------------------------------------------ |
71
+ | `className` | `string` | Custom class for video element |
72
+ | `width` | `string` | Player width (e.g. `"100%"`, `"720px"`) |
73
+ | `height` | `string` | Player height (e.g. `"400px"`, `"auto"`) |
74
+ | `subtitleStyle` | `SubtitleStyleConfig` | Subtitle styling |
75
+ | `qualityConfig` | `VideoQualityConfig` | `defaultQuality`, `showInSettings` |
76
+ | `seekBarConfig` | `SeekBarConfig` | `trackColor`, `bufferColor`, `getPreviewScreenUrl`, etc. |
77
+ | `playPauseButtonConfig` | `PlayPauseButtonConfig` | `backgroundColor`, `borderRadius`, `padding` |
78
+
79
+ **SubtitleStyleConfig:** `fontSize`, `backgroundColor`, `textColor`, `position` (`"top"` \| `"center"` \| `"bottom"`), `borderRadius`, `padding`, `maxWidth`
80
+
81
+ ### `events`
82
+
83
+ | Prop | Type | Description |
84
+ | ---------------------- | -------- | ---------------------------------------- |
85
+ | `onEnded` | `(e) => void` | When video ends |
86
+ | `onError` | `(e?) => void` | On error (retry available) |
87
+ | `onClose` | `() => void` | When close button is clicked |
88
+ | `onWatchHistoryUpdate` | `(data: WatchHistoryData) => void` | On close, with progress data |
89
+
90
+ **WatchHistoryData:** `{ currentTime, duration, progress, isCompleted, watchedAt }`
91
+
92
+ ### `features`
93
+
94
+ | Prop | Type | Description |
95
+ | ----------------------- | -------- | ------------------------------------------------ |
96
+ | `timeCodes` | `Array<{ fromMs, description }>` | Chapter markers (ms) |
97
+ | `getPreviewScreenUrl` | `(hoverTimeValue: number) => string` | Preview thumbnail URL |
98
+ | `tracking` | `{ onViewed?, onWatchTimeUpdated? }` | Tracking callbacks |
99
+ | `subtitles` | `Array<{ lang, label, url }>` | WebVTT subtitle tracks |
100
+ | `episodeList` | `Array<{ id, title, url }>` | Episodes for playlist |
101
+ | `currentEpisodeIndex` | `number` | Active episode index (default `0`) |
102
+ | `intro` | `{ start, end }` | Intro skip range (seconds) |
103
+ | `nextEpisodeConfig` | `{ showAtTime?, showAtEnd? }` | Next episode button |
104
+ | `ads` | `AdConfig` | Pre-roll, mid-roll, post-roll ads |
105
+
106
+ ### Ads (`AdConfig`)
288
107
 
289
108
  ```typescript
290
109
  {
291
- lang: string; // Language code (e.g., "en", "hi", "fr")
292
- label: string; // Display label (e.g., "English", "Hindi")
293
- url: string; // URL to WebVTT subtitle file
294
- }
295
- ```
296
-
297
- **Episode:**
298
-
299
- ```typescript
300
- {
301
- id: number; // Unique episode identifier
302
- title: string; // Episode title
303
- url: string; // Episode video URL
304
- }
305
- ```
306
-
307
- **AdConfig:**
308
-
309
- ```typescript
310
- {
311
- preRoll?: AdBreak; // Pre-roll ad (plays before video)
312
- midRoll?: AdBreak[]; // Mid-roll ads (plays during video)
313
- postRoll?: AdBreak; // Post-roll ad (plays after video)
314
- overlay?: { // Overlay ad (image overlay)
315
- imageUrl: string;
316
- clickUrl?: string;
317
- showDuration: number;
318
- position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
319
- };
320
- smartPlacement?: { // Smart ad placement
321
- enabled: boolean;
322
- minVideoDuration?: number;
323
- minGapBetweenAds?: number;
324
- avoidNearEnd?: number;
325
- preferNaturalBreaks?: boolean;
326
- };
110
+ preRoll?: AdBreak;
111
+ midRoll?: AdBreak[];
112
+ postRoll?: AdBreak;
327
113
  onAdStart?: (adBreak: AdBreak) => void;
328
114
  onAdEnd?: (adBreak: AdBreak) => void;
329
115
  onAdSkip?: (adBreak: AdBreak) => void;
330
116
  onAdError?: (adBreak: AdBreak, error: Error) => void;
331
117
  }
332
- ```
333
118
 
334
- **AdBreak:**
335
-
336
- ```typescript
119
+ // AdBreak
337
120
  {
338
- id: string; // Unique ad identifier
339
- type: "pre-roll" | "mid-roll" | "post-roll" | "overlay";
340
- time: number; // Time in seconds when ad should play
341
- adUrl: string; // URL to ad video
342
- skipable?: boolean; // Whether ad can be skipped
343
- skipAfter?: number; // Seconds before skip button appears
344
- duration?: number; // Ad duration in seconds
345
- sponsoredUrl?: string; // URL for sponsored content
346
- title?: string; // Ad title
347
- description?: string; // Ad description
348
- relevance?: "high" | "medium" | "low";
121
+ id: string;
122
+ type: "pre-roll" | "mid-roll" | "post-roll";
123
+ time: number; // seconds (0 for pre-roll)
124
+ adUrl: string;
125
+ skipable?: boolean;
126
+ skipAfter?: number; // seconds before skip button
127
+ duration?: number; // optional fixed duration
128
+ sponsoredUrl?: string;
349
129
  }
350
130
  ```
351
131
 
352
- ---
132
+ ## 📋 Examples
353
133
 
354
- ## 🎯 Usage Examples
355
-
356
- ### Basic Video Player
357
-
358
- ```tsx
359
- <VideoPlayer
360
- video={{
361
- src: "https://example.com/video.mp4",
362
- title: "My Video",
363
- }}
364
- />
365
- ```
366
-
367
- ### HLS Video with Poster
134
+ ### 📺 HLS with poster
368
135
 
369
136
  ```tsx
370
137
  <VideoPlayer
@@ -374,171 +141,92 @@ Advanced features and functionality.
374
141
  poster: "https://example.com/poster.jpg",
375
142
  title: "Streaming Video",
376
143
  }}
377
- style={{
378
- width: "100%",
379
- height: "450px",
380
- }}
144
+ style={{ width: "100%", height: "450px" }}
381
145
  />
382
146
  ```
383
147
 
384
- ### Video with Preview Thumbnails
148
+ ### 🖼️ Preview thumbnails
385
149
 
386
150
  ```tsx
387
- const getPreview = (hoverTime: number) => {
388
- // Generate thumbnail URL based on hover time
389
- return `https://example.com/thumbnails/${Math.floor(hoverTime)}.jpg`;
390
- };
391
-
392
151
  <VideoPlayer
393
152
  video={{ src: "https://example.com/video.mp4" }}
394
153
  features={{
395
- getPreviewScreenUrl: getPreview,
154
+ getPreviewScreenUrl: (ms) =>
155
+ `https://example.com/thumbs/${Math.floor(ms / 1000)}.jpg`,
396
156
  }}
397
- />;
157
+ />
398
158
  ```
399
159
 
400
- ### Video with Chapters
160
+ ### 📑 Chapters
401
161
 
402
162
  ```tsx
403
163
  <VideoPlayer
404
164
  video={{ src: "https://example.com/video.mp4" }}
405
165
  features={{
406
166
  timeCodes: [
407
- { fromMs: 0, description: "Introduction" },
167
+ { fromMs: 0, description: "Intro" },
408
168
  { fromMs: 60000, description: "Chapter 1" },
409
169
  { fromMs: 120000, description: "Chapter 2" },
410
- { fromMs: 180000, description: "Conclusion" },
411
170
  ],
412
171
  }}
413
172
  />
414
173
  ```
415
174
 
416
- ### Video with Subtitles
175
+ ### 💬 Subtitles
417
176
 
418
177
  ```tsx
419
178
  <VideoPlayer
420
179
  video={{ src: "https://example.com/video.mp4" }}
421
180
  features={{
422
181
  subtitles: [
423
- {
424
- lang: "en",
425
- label: "English",
426
- url: "https://example.com/subtitles-en.vtt",
427
- },
428
- {
429
- lang: "es",
430
- label: "Spanish",
431
- url: "https://example.com/subtitles-es.vtt",
432
- },
182
+ { lang: "en", label: "English", url: "https://example.com/en.vtt" },
183
+ { lang: "es", label: "Spanish", url: "https://example.com/es.vtt" },
433
184
  ],
434
185
  }}
435
186
  style={{
436
187
  subtitleStyle: {
437
188
  fontSize: "1.25rem",
438
- backgroundColor: "rgba(0, 0, 0, 0.75)",
439
- textColor: "#ffffff",
189
+ backgroundColor: "rgba(0,0,0,0.75)",
190
+ textColor: "#fff",
440
191
  position: "bottom",
441
192
  },
442
193
  }}
443
194
  />
444
195
  ```
445
196
 
446
- ### Video with Intro Skip
197
+ ### ⏭️ Intro skip
447
198
 
448
199
  ```tsx
449
200
  <VideoPlayer
450
201
  video={{ src: "https://example.com/video.mp4" }}
451
202
  features={{
452
- intro: {
453
- start: 10, // Intro starts at 10 seconds
454
- end: 45, // Intro ends at 45 seconds
455
- },
203
+ intro: { start: 10, end: 45 },
456
204
  }}
457
205
  />
458
206
  ```
459
207
 
460
- ### Episode Playlist
208
+ ### 📺 Episodes
461
209
 
462
210
  ```tsx
463
- const [currentEpisode, setCurrentEpisode] = useState(0);
464
-
465
211
  const episodes = [
466
212
  { id: 1, title: "Episode 1", url: "https://example.com/ep1.m3u8" },
467
213
  { id: 2, title: "Episode 2", url: "https://example.com/ep2.m3u8" },
468
- { id: 3, title: "Episode 3", url: "https://example.com/ep3.m3u8" },
469
214
  ];
470
215
 
471
216
  <VideoPlayer
472
217
  video={{
473
- src: episodes[currentEpisode].url,
474
- title: episodes[currentEpisode].title,
218
+ src: episodes[0].url,
219
+ title: episodes[0].title,
475
220
  }}
476
221
  features={{
477
222
  episodeList: episodes,
478
- currentEpisodeIndex: currentEpisode,
479
- nextEpisodeConfig: {
480
- showAtTime: 300, // Show next episode button 5 minutes before end
481
- showAtEnd: true, // Also show at video end
482
- },
483
- }}
484
- events={{
485
- onEnded: () => {
486
- if (currentEpisode < episodes.length - 1) {
487
- setCurrentEpisode(currentEpisode + 1);
488
- }
489
- },
490
- }}
491
- />;
492
- ```
493
-
494
- ### Video with Tracking
495
-
496
- ```tsx
497
- <VideoPlayer
498
- video={{ src: "https://example.com/video.mp4" }}
499
- features={{
500
- tracking: {
501
- onViewed: () => {
502
- // Track video view
503
- analytics.track("video_viewed", { videoId: "123" });
504
- },
505
- onWatchTimeUpdated: ({ watchTime, currentTime, duration }) => {
506
- // Track watch time
507
- analytics.track("watch_time_updated", {
508
- watchTime,
509
- progress: (currentTime / duration) * 100,
510
- });
511
- },
512
- },
513
- }}
514
- />
515
- ```
516
-
517
- ### Video with Watch History
518
-
519
- ```tsx
520
- <VideoPlayer
521
- video={{ src: "https://example.com/video.mp4" }}
522
- events={{
523
- onWatchHistoryUpdate: async (data) => {
524
- // Save watch history to backend
525
- await fetch("/api/watch-history", {
526
- method: "POST",
527
- headers: { "Content-Type": "application/json" },
528
- body: JSON.stringify({
529
- videoId: "123",
530
- currentTime: data.currentTime,
531
- duration: data.duration,
532
- progress: data.progress,
533
- isCompleted: data.isCompleted,
534
- }),
535
- });
536
- },
223
+ currentEpisodeIndex: 0,
224
+ nextEpisodeConfig: { showAtTime: 300, showAtEnd: true },
537
225
  }}
538
226
  />
539
227
  ```
540
228
 
541
- ### Video with Ads
229
+ ### 📢 Ads
542
230
 
543
231
  ```tsx
544
232
  <VideoPlayer
@@ -549,7 +237,7 @@ const episodes = [
549
237
  id: "preroll-1",
550
238
  type: "pre-roll",
551
239
  time: 0,
552
- adUrl: "https://example.com/pre-roll-ad.mp4",
240
+ adUrl: "https://example.com/ad.mp4",
553
241
  skipable: true,
554
242
  skipAfter: 5,
555
243
  },
@@ -558,124 +246,77 @@ const episodes = [
558
246
  id: "midroll-1",
559
247
  type: "mid-roll",
560
248
  time: 120,
561
- adUrl: "https://example.com/mid-roll-ad.mp4",
249
+ adUrl: "https://example.com/mid-ad.mp4",
562
250
  skipable: false,
563
251
  },
564
252
  ],
565
- onAdStart: (adBreak) => {
566
- console.log("Ad started:", adBreak.id);
567
- },
568
- onAdEnd: (adBreak) => {
569
- console.log("Ad ended:", adBreak.id);
570
- },
253
+ onAdStart: (ad) => console.log("Ad started", ad.id),
254
+ onAdEnd: (ad) => console.log("Ad ended", ad.id),
571
255
  },
572
256
  }}
573
257
  />
574
258
  ```
575
259
 
576
- ### Resume from Last Position
260
+ ### ▶️ Resume playback
577
261
 
578
262
  ```tsx
579
- const [watchHistory, setWatchHistory] = useState(null);
580
-
581
- // Load watch history on mount
582
- useEffect(() => {
583
- fetch("/api/watch-history/123")
584
- .then((res) => res.json())
585
- .then((data) => setWatchHistory(data));
586
- }, []);
263
+ const [savedTime, setSavedTime] = useState(0);
587
264
 
588
265
  <VideoPlayer
589
266
  video={{
590
267
  src: "https://example.com/video.mp4",
591
- startFrom: watchHistory?.currentTime || 0,
268
+ startFrom: savedTime,
592
269
  }}
593
270
  events={{
594
271
  onWatchHistoryUpdate: (data) => {
595
- // Save progress
596
- setWatchHistory(data);
272
+ setSavedTime(data.currentTime);
273
+ // or save to backend
597
274
  },
598
275
  }}
599
- />;
600
- ```
601
-
602
- ---
603
-
604
- ## ❓ Troubleshooting
605
-
606
- ### Video Not Playing?
607
-
608
- - **Check the video URL**: Ensure `video.src` is a valid, accessible URL
609
- - **Check video format**: Verify the video format is supported (HLS, MP4, DASH, YouTube)
610
- - **CORS issues**: If using HLS or external sources, ensure CORS headers are properly configured
611
- - **Specify video type**: Try explicitly setting `video.type` to help with format detection
612
-
613
- ```tsx
614
- <VideoPlayer
615
- video={{
616
- src: "https://example.com/video.m3u8",
617
- type: "hls", // Explicitly specify type
618
- }}
619
276
  />
620
277
  ```
621
278
 
622
- ### Subtitles Not Showing?
623
-
624
- - **Check VTT file URL**: Ensure subtitle URLs are publicly accessible
625
- - **Verify VTT format**: Ensure WebVTT files are properly formatted
626
- - **Check CORS**: Subtitle files must be accessible from your domain
627
- - **Test subtitle URL**: Open the subtitle URL directly in a browser to verify it loads
628
-
629
- ### Preview Thumbnails Not Loading?
630
-
631
- - **Verify function returns URL**: Ensure `getPreviewScreenUrl` returns a valid image URL
632
- - **Check image loading**: The function should return a URL that loads successfully
633
- - **Use browser console**: Check for image loading errors in the browser console (F12)
634
-
635
- ### Player Not Responsive?
636
-
637
- - **Use percentage widths**: Set `style.width` to `"100%"` for responsive behavior
638
- - **Container styling**: Wrap the player in a container with appropriate CSS
639
- - **Height auto**: Use `style.height: "auto"` to maintain aspect ratio
640
-
641
- ```tsx
642
- <div style={{ maxWidth: "1200px", margin: "0 auto" }}>
643
- <VideoPlayer
644
- video={{ src: "https://example.com/video.mp4" }}
645
- style={{
646
- width: "100%",
647
- height: "auto",
648
- }}
649
- />
650
- </div>
279
+ ## 📤 Exports
280
+
281
+ ```ts
282
+ import {
283
+ VideoPlayer,
284
+ useVideoStore,
285
+ } from "@zezosoft/react-player";
286
+
287
+ import type {
288
+ VideoPlayerProps,
289
+ Episode,
290
+ SubtitleTrack,
291
+ IntroConfig,
292
+ NextEpisodeConfig,
293
+ WatchHistoryData,
294
+ SubtitleStyleConfig,
295
+ VideoQualityConfig,
296
+ SeekBarConfig,
297
+ PlayPauseButtonConfig,
298
+ } from "@zezosoft/react-player";
651
299
  ```
652
300
 
653
- ### Ads Not Playing?
654
-
655
- - **Check ad URLs**: Ensure ad video URLs are valid and accessible
656
- - **Verify ad timing**: For mid-roll ads, ensure `time` is less than video duration
657
- - **Check ad format**: Ad videos should be in supported formats (MP4, HLS)
301
+ ## 🔧 Troubleshooting
658
302
 
659
- ---
303
+ **Video not playing**
304
+ - Use a valid, accessible URL
305
+ - Set `type: "hls"` or `type: "dash"` explicitly for streaming
306
+ - Check CORS for external sources
660
307
 
661
- ## 🔗 Related Links
308
+ **Subtitles not showing**
309
+ - Ensure WebVTT URLs are accessible
310
+ - Verify CORS for subtitle files
662
311
 
663
- - 📚 [Official Documentation](https://github.com/zezosoft/react-player)
664
- - 🛠 [Issues & Support](https://github.com/zezosoft/react-player/issues)
312
+ **Preview thumbnails**
313
+ - `getPreviewScreenUrl` must return a valid image URL
314
+ - URL is called with `hoverTimeValue` in milliseconds
665
315
 
666
- ---
316
+ ## 📄 License
667
317
 
668
- ## 📝 License
669
-
670
- Licensed under the MIT License.
671
- Developed by [Zezosoft](https://zezosoft.com). 🚀
672
-
673
- ---
318
+ MIT · [Zezosoft](https://zezosoft.com)
674
319
 
675
320
  ## 🙌 Credits
676
321
 
677
- This project includes modifications of the seek bar functionality inspired by [`react-video-seek-slider`](https://www.npmjs.com/package/react-video-seek-slider).
678
-
679
- ---
680
-
681
- # 🌟 Enjoy seamless video playback with @zezosoft/react-player! 🎥
322
+ Seek bar inspired by [react-video-seek-slider](https://www.npmjs.com/package/react-video-seek-slider).
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ function styleInject(css, ref) {
36
36
  }
37
37
  }
38
38
 
39
- var css_248z$4 = "/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-red-400: oklch(70.4% 0.191 22.216);\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-red-700: oklch(50.5% 0.213 27.518);\n --color-green-500: oklch(72.3% 0.219 149.579);\n --color-sky-300: oklch(82.8% 0.111 230.318);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-purple-500: oklch(62.7% 0.265 303.9);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-3xl: 1.875rem;\n --text-3xl--line-height: calc(2.25 / 1.875);\n --font-weight-normal: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wider: 0.05em;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\n --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --blur-sm: 8px;\n --blur-md: 12px;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=\"until-found\"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .absolute {\n position: absolute;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .-top-2 {\n top: calc(var(--spacing) * -2);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1 {\n top: calc(var(--spacing) * 1);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .top-full {\n top: 100%;\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-32 {\n right: calc(var(--spacing) * 32);\n }\n .right-full {\n right: 100%;\n }\n .bottom-36 {\n bottom: calc(var(--spacing) * 36);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1 {\n left: calc(var(--spacing) * 1);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-32 {\n left: calc(var(--spacing) * 32);\n }\n .left-full {\n left: 100%;\n }\n .z-40 {\n z-index: 40;\n }\n .z-50 {\n z-index: 50;\n }\n .z-\\[-1\\] {\n z-index: -1;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .mx-2 {\n margin-inline: calc(var(--spacing) * 2);\n }\n .mx-auto {\n margin-inline: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-2 {\n margin-top: calc(var(--spacing) * 2);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .-mr-1 {\n margin-right: calc(var(--spacing) * -1);\n }\n .mr-2 {\n margin-right: calc(var(--spacing) * 2);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .ml-1 {\n margin-left: calc(var(--spacing) * 1);\n }\n .ml-2 {\n margin-left: calc(var(--spacing) * 2);\n }\n .contents {\n display: contents;\n }\n .flex {\n display: flex;\n }\n .hidden {\n display: none;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .inline-flex {\n display: inline-flex;\n }\n .table {\n display: table;\n }\n .h-1 {\n height: calc(var(--spacing) * 1);\n }\n .h-1\\.5 {\n height: calc(var(--spacing) * 1.5);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-2\\.5 {\n height: calc(var(--spacing) * 2.5);\n }\n .h-3 {\n height: calc(var(--spacing) * 3);\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-6 {\n height: calc(var(--spacing) * 6);\n }\n .h-10 {\n height: calc(var(--spacing) * 10);\n }\n .h-12 {\n height: calc(var(--spacing) * 12);\n }\n .h-14 {\n height: calc(var(--spacing) * 14);\n }\n .h-full {\n height: 100%;\n }\n .max-h-80 {\n max-height: calc(var(--spacing) * 80);\n }\n .max-h-\\[min\\(80vh\\,480px\\)\\] {\n max-height: min(80vh, 480px);\n }\n .min-h-0 {\n min-height: calc(var(--spacing) * 0);\n }\n .w-1 {\n width: calc(var(--spacing) * 1);\n }\n .w-1\\.5 {\n width: calc(var(--spacing) * 1.5);\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-2\\.5 {\n width: calc(var(--spacing) * 2.5);\n }\n .w-3 {\n width: calc(var(--spacing) * 3);\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-6 {\n width: calc(var(--spacing) * 6);\n }\n .w-12 {\n width: calc(var(--spacing) * 12);\n }\n .w-14 {\n width: calc(var(--spacing) * 14);\n }\n .w-80 {\n width: calc(var(--spacing) * 80);\n }\n .w-\\[2px\\] {\n width: 2px;\n }\n .w-\\[10vw\\] {\n width: 10vw;\n }\n .w-\\[15vw\\] {\n width: 15vw;\n }\n .w-fit {\n width: fit-content;\n }\n .w-full {\n width: 100%;\n }\n .max-w-\\[min\\(90vw\\,320px\\)\\] {\n max-width: min(90vw, 320px);\n }\n .max-w-md {\n max-width: var(--container-md);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-shrink {\n flex-shrink: 1;\n }\n .shrink-0 {\n flex-shrink: 0;\n }\n .border-collapse {\n border-collapse: collapse;\n }\n .-translate-x-1 {\n --tw-translate-x: calc(var(--spacing) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1 {\n --tw-translate-y: calc(var(--spacing) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .rotate-45 {\n rotate: 45deg;\n }\n .rotate-180 {\n rotate: 180deg;\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-default {\n cursor: default;\n }\n .cursor-not-allowed {\n cursor: not-allowed;\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .resize {\n resize: both;\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-wrap {\n flex-wrap: wrap;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-3 {\n gap: calc(var(--spacing) * 3);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .gap-7 {\n gap: calc(var(--spacing) * 7);\n }\n .space-y-0 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-3 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .overflow-y-auto {\n overflow-y: auto;\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-\\[5px\\] {\n border-radius: 5px;\n }\n .rounded-\\[7px\\] {\n border-radius: 7px;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .border-b {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 1px;\n }\n .border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .border-gray-600 {\n border-color: var(--color-gray-600);\n }\n .border-gray-700 {\n border-color: var(--color-gray-700);\n }\n .border-gray-700\\/60 {\n border-color: color-mix(in srgb, oklch(37.3% 0.034 259.733) 60%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-gray-700) 60%, transparent);\n }\n }\n .border-white {\n border-color: var(--color-white);\n }\n .border-white\\/10 {\n border-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .border-white\\/30 {\n border-color: color-mix(in srgb, #fff 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 30%, transparent);\n }\n }\n .border-white\\/40 {\n border-color: color-mix(in srgb, #fff 40%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 40%, transparent);\n }\n }\n .bg-\\[\\#3a4049\\] {\n background-color: #3a4049;\n }\n .bg-\\[\\#454545\\] {\n background-color: #454545;\n }\n .bg-\\[rgba\\(0\\,0\\,0\\,0\\.5\\)\\] {\n background-color: rgba(0,0,0,0.5);\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-black\\/60 {\n background-color: color-mix(in srgb, #000 60%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 60%, transparent);\n }\n }\n .bg-black\\/90 {\n background-color: color-mix(in srgb, #000 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 90%, transparent);\n }\n }\n .bg-blue-500 {\n background-color: var(--color-blue-500);\n }\n .bg-gray-500 {\n background-color: var(--color-gray-500);\n }\n .bg-gray-900 {\n background-color: var(--color-gray-900);\n }\n .bg-green-500 {\n background-color: var(--color-green-500);\n }\n .bg-purple-500 {\n background-color: var(--color-purple-500);\n }\n .bg-red-500 {\n background-color: var(--color-red-500);\n }\n .bg-red-500\\/15 {\n background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 15%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-red-500) 15%, transparent);\n }\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-white\\/10 {\n background-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .bg-white\\/20 {\n background-color: color-mix(in srgb, #fff 20%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 20%, transparent);\n }\n }\n .bg-white\\/80 {\n background-color: color-mix(in srgb, #fff 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 80%, transparent);\n }\n }\n .bg-linear-to-b {\n --tw-gradient-position: to bottom;\n @supports (background-image: linear-gradient(in lab, red, red)) {\n --tw-gradient-position: to bottom in oklab;\n }\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black {\n --tw-gradient-from: var(--color-black);\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .from-black\\/80 {\n --tw-gradient-from: color-mix(in srgb, #000 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 80%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .via-transparent {\n --tw-gradient-via: transparent;\n --tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);\n --tw-gradient-stops: var(--tw-gradient-via-stops);\n }\n .to-black {\n --tw-gradient-to: var(--color-black);\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-black\\/90 {\n --tw-gradient-to: color-mix(in srgb, #000 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-to: color-mix(in oklab, var(--color-black) 90%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .object-contain {\n object-fit: contain;\n }\n .p-0 {\n padding: calc(var(--spacing) * 0);\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .p-10 {\n padding: calc(var(--spacing) * 10);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .px-5 {\n padding-inline: calc(var(--spacing) * 5);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .px-10 {\n padding-inline: calc(var(--spacing) * 10);\n }\n .px-20 {\n padding-inline: calc(var(--spacing) * 20);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-1\\.5 {\n padding-block: calc(var(--spacing) * 1.5);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .py-3 {\n padding-block: calc(var(--spacing) * 3);\n }\n .py-4 {\n padding-block: calc(var(--spacing) * 4);\n }\n .pt-6 {\n padding-top: calc(var(--spacing) * 6);\n }\n .pr-1 {\n padding-right: calc(var(--spacing) * 1);\n }\n .pb-3 {\n padding-bottom: calc(var(--spacing) * 3);\n }\n .pb-4 {\n padding-bottom: calc(var(--spacing) * 4);\n }\n .pb-6 {\n padding-bottom: calc(var(--spacing) * 6);\n }\n .pb-10 {\n padding-bottom: calc(var(--spacing) * 10);\n }\n .pb-16 {\n padding-bottom: calc(var(--spacing) * 16);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-normal {\n --tw-font-weight: var(--font-weight-normal);\n font-weight: var(--font-weight-normal);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wider {\n --tw-tracking: var(--tracking-wider);\n letter-spacing: var(--tracking-wider);\n }\n .whitespace-nowrap {\n white-space: nowrap;\n }\n .text-gray-200 {\n color: var(--color-gray-200);\n }\n .text-gray-300 {\n color: var(--color-gray-300);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-900 {\n color: var(--color-gray-900);\n }\n .text-red-400 {\n color: var(--color-red-400);\n }\n .text-red-500 {\n color: var(--color-red-500);\n }\n .text-red-600 {\n color: var(--color-red-600);\n }\n .text-sky-300 {\n color: var(--color-sky-300);\n }\n .text-white {\n color: var(--color-white);\n }\n .normal-case {\n text-transform: none;\n }\n .underline {\n text-decoration-line: underline;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .opacity-50 {\n opacity: 50%;\n }\n .opacity-100 {\n opacity: 100%;\n }\n .shadow-2xl {\n --tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .shadow-md {\n --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .ring-1 {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .ring-red-500 {\n --tw-ring-color: var(--color-red-500);\n }\n .ring-red-500\\/25 {\n --tw-ring-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-ring-color: color-mix(in oklab, var(--color-red-500) 25%, transparent);\n }\n }\n .outline {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n .backdrop-blur-md {\n --tw-backdrop-blur: blur(var(--blur-md));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .backdrop-blur-sm {\n --tw-backdrop-blur: blur(var(--blur-sm));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .backdrop-filter {\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .transition {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-all {\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .duration-300 {\n --tw-duration: 300ms;\n transition-duration: 300ms;\n }\n .ease-in-out {\n --tw-ease: var(--ease-in-out);\n transition-timing-function: var(--ease-in-out);\n }\n .ease-out {\n --tw-ease: var(--ease-out);\n transition-timing-function: var(--ease-out);\n }\n .select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .hover\\:scale-105 {\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 105%;\n --tw-scale-y: 105%;\n --tw-scale-z: 105%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n }\n .hover\\:border-white\\/50 {\n &:hover {\n @media (hover: hover) {\n border-color: color-mix(in srgb, #fff 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 50%, transparent);\n }\n }\n }\n }\n .hover\\:bg-gray-300 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:bg-red-700 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-red-700);\n }\n }\n }\n .hover\\:bg-white\\/5 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 5%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 5%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/10 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/30 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 30%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/90 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 90%, transparent);\n }\n }\n }\n }\n .hover\\:text-gray-200 {\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-200);\n }\n }\n }\n .hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--color-white);\n }\n }\n }\n .hover\\:shadow-lg {\n &:hover {\n @media (hover: hover) {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-gray-400 {\n &:focus {\n --tw-ring-color: var(--color-gray-400);\n }\n }\n .focus\\:ring-offset-1 {\n &:focus {\n --tw-ring-offset-width: 1px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .active\\:scale-95 {\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .disabled\\:cursor-not-allowed {\n &:disabled {\n cursor: not-allowed;\n }\n }\n .disabled\\:bg-white\\/50 {\n &:disabled {\n background-color: color-mix(in srgb, #fff 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 50%, transparent);\n }\n }\n }\n .disabled\\:opacity-50 {\n &:disabled {\n opacity: 50%;\n }\n }\n .lg\\:h-18 {\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 18);\n }\n }\n .lg\\:w-18 {\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 18);\n }\n }\n .lg\\:pb-12 {\n @media (width >= 64rem) {\n padding-bottom: calc(var(--spacing) * 12);\n }\n }\n .lg\\:text-2xl {\n @media (width >= 64rem) {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n }\n .lg\\:text-3xl {\n @media (width >= 64rem) {\n font-size: var(--text-3xl);\n line-height: var(--tw-leading, var(--text-3xl--line-height));\n }\n }\n .lg\\:text-base {\n @media (width >= 64rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n}\n@keyframes live-dot-blink {\n 0%, 100% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6);\n }\n 50% {\n opacity: 0.35;\n transform: scale(0.85);\n box-shadow: 0 0 0 4px rgba(239, 68, 68, 0);\n }\n}\n.animate-live-blink {\n animation: live-dot-blink 1.2s ease-in-out infinite;\n}\n.noCursor {\n cursor: none !important;\n}\n.icon-class {\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n color: var(--color-gray-400);\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-200);\n }\n }\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 18);\n }\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 18);\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-gradient-position {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-via {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-to {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-via-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 0%;\n}\n@property --tw-gradient-via-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 50%;\n}\n@property --tw-gradient-to-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-tracking {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-outline-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-backdrop-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ease {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-scale-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 1;\n}\n@property --tw-scale-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 1;\n}\n@property --tw-scale-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 1;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-outline-style: solid;\n --tw-backdrop-blur: initial;\n --tw-backdrop-brightness: initial;\n --tw-backdrop-contrast: initial;\n --tw-backdrop-grayscale: initial;\n --tw-backdrop-hue-rotate: initial;\n --tw-backdrop-invert: initial;\n --tw-backdrop-opacity: initial;\n --tw-backdrop-saturate: initial;\n --tw-backdrop-sepia: initial;\n --tw-duration: initial;\n --tw-ease: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n";
39
+ var css_248z$4 = "/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-red-400: oklch(70.4% 0.191 22.216);\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-red-700: oklch(50.5% 0.213 27.518);\n --color-green-500: oklch(72.3% 0.219 149.579);\n --color-sky-300: oklch(82.8% 0.111 230.318);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-purple-500: oklch(62.7% 0.265 303.9);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-3xl: 1.875rem;\n --text-3xl--line-height: calc(2.25 / 1.875);\n --font-weight-normal: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wider: 0.05em;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\n --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --blur-sm: 8px;\n --blur-md: 12px;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=\"until-found\"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .-top-2 {\n top: calc(var(--spacing) * -2);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1 {\n top: calc(var(--spacing) * 1);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .top-full {\n top: 100%;\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-32 {\n right: calc(var(--spacing) * 32);\n }\n .right-full {\n right: 100%;\n }\n .bottom-36 {\n bottom: calc(var(--spacing) * 36);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1 {\n left: calc(var(--spacing) * 1);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-32 {\n left: calc(var(--spacing) * 32);\n }\n .left-full {\n left: 100%;\n }\n .z-40 {\n z-index: 40;\n }\n .z-50 {\n z-index: 50;\n }\n .z-\\[-1\\] {\n z-index: -1;\n }\n .mx-2 {\n margin-inline: calc(var(--spacing) * 2);\n }\n .mx-auto {\n margin-inline: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-2 {\n margin-top: calc(var(--spacing) * 2);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .-mr-1 {\n margin-right: calc(var(--spacing) * -1);\n }\n .mr-2 {\n margin-right: calc(var(--spacing) * 2);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .ml-1 {\n margin-left: calc(var(--spacing) * 1);\n }\n .ml-2 {\n margin-left: calc(var(--spacing) * 2);\n }\n .contents {\n display: contents;\n }\n .flex {\n display: flex;\n }\n .hidden {\n display: none;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .inline-flex {\n display: inline-flex;\n }\n .table {\n display: table;\n }\n .h-1 {\n height: calc(var(--spacing) * 1);\n }\n .h-1\\.5 {\n height: calc(var(--spacing) * 1.5);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-2\\.5 {\n height: calc(var(--spacing) * 2.5);\n }\n .h-3 {\n height: calc(var(--spacing) * 3);\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-6 {\n height: calc(var(--spacing) * 6);\n }\n .h-10 {\n height: calc(var(--spacing) * 10);\n }\n .h-12 {\n height: calc(var(--spacing) * 12);\n }\n .h-14 {\n height: calc(var(--spacing) * 14);\n }\n .h-full {\n height: 100%;\n }\n .max-h-80 {\n max-height: calc(var(--spacing) * 80);\n }\n .max-h-\\[min\\(80vh\\,480px\\)\\] {\n max-height: min(80vh, 480px);\n }\n .min-h-0 {\n min-height: calc(var(--spacing) * 0);\n }\n .w-1 {\n width: calc(var(--spacing) * 1);\n }\n .w-1\\.5 {\n width: calc(var(--spacing) * 1.5);\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-2\\.5 {\n width: calc(var(--spacing) * 2.5);\n }\n .w-3 {\n width: calc(var(--spacing) * 3);\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-6 {\n width: calc(var(--spacing) * 6);\n }\n .w-12 {\n width: calc(var(--spacing) * 12);\n }\n .w-14 {\n width: calc(var(--spacing) * 14);\n }\n .w-80 {\n width: calc(var(--spacing) * 80);\n }\n .w-\\[2px\\] {\n width: 2px;\n }\n .w-\\[10vw\\] {\n width: 10vw;\n }\n .w-\\[15vw\\] {\n width: 15vw;\n }\n .w-fit {\n width: fit-content;\n }\n .w-full {\n width: 100%;\n }\n .max-w-\\[min\\(90vw\\,320px\\)\\] {\n max-width: min(90vw, 320px);\n }\n .max-w-md {\n max-width: var(--container-md);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-shrink {\n flex-shrink: 1;\n }\n .shrink-0 {\n flex-shrink: 0;\n }\n .border-collapse {\n border-collapse: collapse;\n }\n .-translate-x-1 {\n --tw-translate-x: calc(var(--spacing) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1 {\n --tw-translate-y: calc(var(--spacing) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .rotate-45 {\n rotate: 45deg;\n }\n .rotate-180 {\n rotate: 180deg;\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-default {\n cursor: default;\n }\n .cursor-not-allowed {\n cursor: not-allowed;\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .resize {\n resize: both;\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-wrap {\n flex-wrap: wrap;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-3 {\n gap: calc(var(--spacing) * 3);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .gap-7 {\n gap: calc(var(--spacing) * 7);\n }\n .space-y-0 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-3 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .overflow-y-auto {\n overflow-y: auto;\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-\\[5px\\] {\n border-radius: 5px;\n }\n .rounded-\\[7px\\] {\n border-radius: 7px;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .border-b {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 1px;\n }\n .border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .border-gray-600 {\n border-color: var(--color-gray-600);\n }\n .border-gray-700 {\n border-color: var(--color-gray-700);\n }\n .border-gray-700\\/60 {\n border-color: color-mix(in srgb, oklch(37.3% 0.034 259.733) 60%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-gray-700) 60%, transparent);\n }\n }\n .border-white {\n border-color: var(--color-white);\n }\n .border-white\\/10 {\n border-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .border-white\\/30 {\n border-color: color-mix(in srgb, #fff 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 30%, transparent);\n }\n }\n .border-white\\/40 {\n border-color: color-mix(in srgb, #fff 40%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 40%, transparent);\n }\n }\n .bg-\\[\\#3a4049\\] {\n background-color: #3a4049;\n }\n .bg-\\[\\#454545\\] {\n background-color: #454545;\n }\n .bg-\\[rgba\\(0\\,0\\,0\\,0\\.5\\)\\] {\n background-color: rgba(0,0,0,0.5);\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-black\\/60 {\n background-color: color-mix(in srgb, #000 60%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 60%, transparent);\n }\n }\n .bg-black\\/90 {\n background-color: color-mix(in srgb, #000 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 90%, transparent);\n }\n }\n .bg-blue-500 {\n background-color: var(--color-blue-500);\n }\n .bg-gray-500 {\n background-color: var(--color-gray-500);\n }\n .bg-gray-900 {\n background-color: var(--color-gray-900);\n }\n .bg-green-500 {\n background-color: var(--color-green-500);\n }\n .bg-purple-500 {\n background-color: var(--color-purple-500);\n }\n .bg-red-500 {\n background-color: var(--color-red-500);\n }\n .bg-red-500\\/15 {\n background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 15%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-red-500) 15%, transparent);\n }\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-white\\/10 {\n background-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .bg-white\\/20 {\n background-color: color-mix(in srgb, #fff 20%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 20%, transparent);\n }\n }\n .bg-white\\/80 {\n background-color: color-mix(in srgb, #fff 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 80%, transparent);\n }\n }\n .bg-linear-to-b {\n --tw-gradient-position: to bottom;\n @supports (background-image: linear-gradient(in lab, red, red)) {\n --tw-gradient-position: to bottom in oklab;\n }\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black {\n --tw-gradient-from: var(--color-black);\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .from-black\\/80 {\n --tw-gradient-from: color-mix(in srgb, #000 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 80%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .via-transparent {\n --tw-gradient-via: transparent;\n --tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);\n --tw-gradient-stops: var(--tw-gradient-via-stops);\n }\n .to-black {\n --tw-gradient-to: var(--color-black);\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-black\\/90 {\n --tw-gradient-to: color-mix(in srgb, #000 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-to: color-mix(in oklab, var(--color-black) 90%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .object-contain {\n object-fit: contain;\n }\n .p-0 {\n padding: calc(var(--spacing) * 0);\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .p-10 {\n padding: calc(var(--spacing) * 10);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .px-5 {\n padding-inline: calc(var(--spacing) * 5);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .px-10 {\n padding-inline: calc(var(--spacing) * 10);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-1\\.5 {\n padding-block: calc(var(--spacing) * 1.5);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .py-3 {\n padding-block: calc(var(--spacing) * 3);\n }\n .py-4 {\n padding-block: calc(var(--spacing) * 4);\n }\n .pt-6 {\n padding-top: calc(var(--spacing) * 6);\n }\n .pr-1 {\n padding-right: calc(var(--spacing) * 1);\n }\n .pb-3 {\n padding-bottom: calc(var(--spacing) * 3);\n }\n .pb-4 {\n padding-bottom: calc(var(--spacing) * 4);\n }\n .pb-6 {\n padding-bottom: calc(var(--spacing) * 6);\n }\n .pb-10 {\n padding-bottom: calc(var(--spacing) * 10);\n }\n .pb-16 {\n padding-bottom: calc(var(--spacing) * 16);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-normal {\n --tw-font-weight: var(--font-weight-normal);\n font-weight: var(--font-weight-normal);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wider {\n --tw-tracking: var(--tracking-wider);\n letter-spacing: var(--tracking-wider);\n }\n .whitespace-nowrap {\n white-space: nowrap;\n }\n .text-gray-200 {\n color: var(--color-gray-200);\n }\n .text-gray-300 {\n color: var(--color-gray-300);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-900 {\n color: var(--color-gray-900);\n }\n .text-red-400 {\n color: var(--color-red-400);\n }\n .text-red-500 {\n color: var(--color-red-500);\n }\n .text-red-600 {\n color: var(--color-red-600);\n }\n .text-sky-300 {\n color: var(--color-sky-300);\n }\n .text-white {\n color: var(--color-white);\n }\n .normal-case {\n text-transform: none;\n }\n .underline {\n text-decoration-line: underline;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .opacity-100 {\n opacity: 100%;\n }\n .shadow-2xl {\n --tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .shadow-md {\n --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .ring-1 {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .ring-red-500 {\n --tw-ring-color: var(--color-red-500);\n }\n .ring-red-500\\/25 {\n --tw-ring-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-ring-color: color-mix(in oklab, var(--color-red-500) 25%, transparent);\n }\n }\n .outline {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n .backdrop-blur-md {\n --tw-backdrop-blur: blur(var(--blur-md));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .backdrop-blur-sm {\n --tw-backdrop-blur: blur(var(--blur-sm));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .backdrop-filter {\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .transition {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-all {\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .duration-300 {\n --tw-duration: 300ms;\n transition-duration: 300ms;\n }\n .ease-in-out {\n --tw-ease: var(--ease-in-out);\n transition-timing-function: var(--ease-in-out);\n }\n .ease-out {\n --tw-ease: var(--ease-out);\n transition-timing-function: var(--ease-out);\n }\n .select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .hover\\:scale-105 {\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 105%;\n --tw-scale-y: 105%;\n --tw-scale-z: 105%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n }\n .hover\\:border-white\\/50 {\n &:hover {\n @media (hover: hover) {\n border-color: color-mix(in srgb, #fff 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 50%, transparent);\n }\n }\n }\n }\n .hover\\:bg-gray-300 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:bg-red-700 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-red-700);\n }\n }\n }\n .hover\\:bg-white\\/5 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 5%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 5%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/10 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/30 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 30%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/90 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 90%, transparent);\n }\n }\n }\n }\n .hover\\:text-gray-200 {\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-200);\n }\n }\n }\n .hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--color-white);\n }\n }\n }\n .hover\\:shadow-lg {\n &:hover {\n @media (hover: hover) {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-gray-400 {\n &:focus {\n --tw-ring-color: var(--color-gray-400);\n }\n }\n .focus\\:ring-offset-1 {\n &:focus {\n --tw-ring-offset-width: 1px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .active\\:scale-95 {\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .disabled\\:cursor-not-allowed {\n &:disabled {\n cursor: not-allowed;\n }\n }\n .disabled\\:bg-white\\/50 {\n &:disabled {\n background-color: color-mix(in srgb, #fff 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 50%, transparent);\n }\n }\n }\n .disabled\\:opacity-50 {\n &:disabled {\n opacity: 50%;\n }\n }\n .lg\\:h-18 {\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 18);\n }\n }\n .lg\\:w-18 {\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 18);\n }\n }\n .lg\\:pb-12 {\n @media (width >= 64rem) {\n padding-bottom: calc(var(--spacing) * 12);\n }\n }\n .lg\\:text-2xl {\n @media (width >= 64rem) {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n }\n .lg\\:text-3xl {\n @media (width >= 64rem) {\n font-size: var(--text-3xl);\n line-height: var(--tw-leading, var(--text-3xl--line-height));\n }\n }\n .lg\\:text-base {\n @media (width >= 64rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n}\n@keyframes live-dot-blink {\n 0%, 100% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6);\n }\n 50% {\n opacity: 0.35;\n transform: scale(0.85);\n box-shadow: 0 0 0 4px rgba(239, 68, 68, 0);\n }\n}\n.animate-live-blink {\n animation: live-dot-blink 1.2s ease-in-out infinite;\n}\n.noCursor {\n cursor: none !important;\n}\n.icon-class {\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n color: var(--color-gray-400);\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-200);\n }\n }\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 18);\n }\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 18);\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-gradient-position {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-via {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-to {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-via-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 0%;\n}\n@property --tw-gradient-via-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 50%;\n}\n@property --tw-gradient-to-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-tracking {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-outline-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-backdrop-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ease {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-scale-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 1;\n}\n@property --tw-scale-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 1;\n}\n@property --tw-scale-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 1;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-outline-style: solid;\n --tw-backdrop-blur: initial;\n --tw-backdrop-brightness: initial;\n --tw-backdrop-contrast: initial;\n --tw-backdrop-grayscale: initial;\n --tw-backdrop-hue-rotate: initial;\n --tw-backdrop-invert: initial;\n --tw-backdrop-opacity: initial;\n --tw-backdrop-saturate: initial;\n --tw-backdrop-sepia: initial;\n --tw-duration: initial;\n --tw-ease: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n";
40
40
  styleInject(css_248z$4,{"insertAt":"top"});
41
41
 
42
42
  const createVideoRefsSlice = (set) => ({
@@ -726,7 +726,7 @@ const BottomControls = memo(({ config, isLive = false }) => {
726
726
  });
727
727
  BottomControls.displayName = "BottomControls";
728
728
 
729
- var css_248z$2 = ".icon-button {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.icon-button:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .icon-button {\n width: 32px;\n height: 32px;\n }\n}\n\n.fullscreen-icon {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.fullscreen-icon:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .fullscreen-icon {\n width: 32px;\n height: 32px;\n }\n}\n\n.pip-toggle {\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.pip-toggle:hover {\n color: #e5e7eb;\n}\n\n.pip-icon {\n width: 15px;\n height: 15px;\n}\n\n@media (min-width: 1024px) {\n .pip-icon {\n width: 28px;\n height: 28px;\n }\n}\n\n/* Ad Badge Header - Dark/Black Background */\n.ad-badge-header {\n background: rgba(45, 47, 49, 0.95);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n box-shadow: \n 0 4px 16px rgba(0, 0, 0, 0.4),\n 0 0 0 1px rgba(255, 255, 255, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n}\n\n/* Time display in badge - lighter gray */\n.ad-badge-header > span:last-child {\n color: rgba(209, 213, 219, 0.9);\n font-weight: 500;\n letter-spacing: 0.025em;\n}\n\n/* Pulse animation for the dot */\n@keyframes pulse-dot {\n 0%, 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(0.9);\n }\n}\n\n.ad-badge-header .animate-pulse {\n animation: pulse-dot 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .ad-badge-header {\n padding: 0.375rem 0.75rem;\n font-size: 0.625rem;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ad-badge-header .animate-pulse {\n animation: none;\n }\n}\n\n@media (prefers-contrast: high) {\n .ad-badge-header {\n background: #2d2f31;\n border: 2px solid #fff;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);\n }\n}";
729
+ var css_248z$2 = ".icon-button {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.icon-button:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .icon-button {\n width: 32px;\n height: 32px;\n }\n}\n\n.fullscreen-icon {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.fullscreen-icon:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .fullscreen-icon {\n width: 32px;\n height: 32px;\n }\n}\n\n/* Ad Badge Header - Dark/Black Background */\n.ad-badge-header {\n background: rgba(45, 47, 49, 0.95);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n box-shadow: \n 0 4px 16px rgba(0, 0, 0, 0.4),\n 0 0 0 1px rgba(255, 255, 255, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n}\n\n/* Time display in badge - lighter gray */\n.ad-badge-header > span:last-child {\n color: rgba(209, 213, 219, 0.9);\n font-weight: 500;\n letter-spacing: 0.025em;\n}\n\n/* Pulse animation for the dot */\n@keyframes pulse-dot {\n 0%, 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(0.9);\n }\n}\n\n.ad-badge-header .animate-pulse {\n animation: pulse-dot 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .ad-badge-header {\n padding: 0.375rem 0.75rem;\n font-size: 0.625rem;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ad-badge-header .animate-pulse {\n animation: none;\n }\n}\n\n@media (prefers-contrast: high) {\n .ad-badge-header {\n background: #2d2f31;\n border: 2px solid #fff;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);\n }\n}";
730
730
  styleInject(css_248z$2,{"insertAt":"top"});
731
731
 
732
732
  const FullScreenToggle = ({ isFullScreen, onClick, className = "fullscreen-icon", }) => {
@@ -735,13 +735,6 @@ const FullScreenToggle = ({ isFullScreen, onClick, className = "fullscreen-icon"
735
735
  React__default.createElement("path", { fill: "currentColor", d: "M4.746 8.056V6.294L18.73 20.278h-1.762a1.111 1.111 0 1 0 0 2.222h4.444a1.11 1.11 0 0 0 1.111-1.111v-4.445a1.111 1.111 0 0 0-2.222 0v1.762L6.317 4.722h1.762a1.111 1.111 0 1 0 0-2.222H3.635c-.614 0-1.112.497-1.112 1.111v4.445a1.111 1.111 0 1 0 2.223 0z" })))));
736
736
  };
737
737
 
738
- const PiPictureInPictureToggle = ({ onClick, className = "", }) => {
739
- return (React__default.createElement("div", { onClick: onClick, className: `pip-toggle` },
740
- React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", fill: "none", viewBox: "0 0 24 24", className: `pip-icon ${className}` },
741
- React__default.createElement("rect", { width: "9", height: "6", x: "11", y: "11.99", fill: "#fff", rx: "1" }),
742
- React__default.createElement("rect", { width: "22", height: "18", x: "1", y: "3", stroke: "#B3B3B3", strokeWidth: "2", rx: "3" }))));
743
- };
744
-
745
738
  const Popover = ({ button, children, closeOnButtonClick = false, className = "", align = "left", }) => {
746
739
  const [isOpen, setIsOpen] = useState(false);
747
740
  const popoverRef = useRef(null);
@@ -1037,10 +1030,9 @@ const ControlsHeader = ({ config }) => {
1037
1030
  const remaining = Math.max(0, adDuration - adCurrentTime);
1038
1031
  return formatTime(remaining);
1039
1032
  }, [adDuration, adCurrentTime, formatTime]);
1040
- const [isPipActive, setIsPipActive] = React.useState(false);
1041
1033
  const [isFullscreen, setIsFullscreen] = React.useState(false);
1042
1034
  const handleFullscreen = () => {
1043
- if (!screenfull.isEnabled || isPipActive)
1035
+ if (!screenfull.isEnabled)
1044
1036
  return;
1045
1037
  if (screenfull.isFullscreen) {
1046
1038
  screenfull.exit();
@@ -1071,30 +1063,6 @@ const ControlsHeader = ({ config }) => {
1071
1063
  }
1072
1064
  setMuted(nextMuted);
1073
1065
  };
1074
- const handlePipToggle = async () => {
1075
- if (!videoRef)
1076
- return;
1077
- try {
1078
- if (!document.pictureInPictureElement && !isPipActive) {
1079
- await videoRef.requestPictureInPicture();
1080
- setIsPipActive(true);
1081
- }
1082
- else if (document.pictureInPictureElement && isPipActive) {
1083
- await document.exitPictureInPicture();
1084
- setIsPipActive(false);
1085
- }
1086
- }
1087
- catch { }
1088
- };
1089
- React.useEffect(() => {
1090
- const handlePipChange = () => setIsPipActive(!!document.pictureInPictureElement);
1091
- document.addEventListener("enterpictureinpicture", handlePipChange);
1092
- document.addEventListener("leavepictureinpicture", handlePipChange);
1093
- return () => {
1094
- document.removeEventListener("enterpictureinpicture", handlePipChange);
1095
- document.removeEventListener("leavepictureinpicture", handlePipChange);
1096
- };
1097
- }, []);
1098
1066
  const handleClose = () => {
1099
1067
  resetStore();
1100
1068
  config?.onClose?.();
@@ -1105,7 +1073,7 @@ const ControlsHeader = ({ config }) => {
1105
1073
  adTimeRemaining && (React.createElement("span", { className: "text-gray-300 font-normal normal-case ml-1 text-xs" }, adTimeRemaining)))));
1106
1074
  const renderVideoHeader = () => (React.createElement("div", { className: "flex" },
1107
1075
  React.createElement("div", null,
1108
- React.createElement("h1", { className: "text-gray-200 text-lg lg:text-2xl font-semibold" }, episodeList.length > 0
1076
+ React.createElement("h1", { className: "text-gray-200 text-lg lg:text-2xl font-medium" }, episodeList.length > 0
1109
1077
  ? episodeList[currentEpisodeIndex]?.title
1110
1078
  : config?.title),
1111
1079
  config?.isTrailer && (React.createElement("p", { className: "text-gray-300 text-sm lg:text-base font-normal" }, "Trailer")))));
@@ -1116,16 +1084,9 @@ const ControlsHeader = ({ config }) => {
1116
1084
  React.createElement("div", { onClick: handleMute }, muted ? (React.createElement(Tooltip, { title: "Unmute" },
1117
1085
  React.createElement(IoVolumeMuteOutline, { className: iconClassName }))) : (React.createElement(Tooltip, { title: "Mute" },
1118
1086
  React.createElement(IoVolumeHighOutline, { className: iconClassName })))),
1119
- React.createElement(Tooltip, { title: isPipActive
1120
- ? "Disabled in PiP"
1121
- : isFullscreen
1122
- ? "Exit Fullscreen"
1123
- : "Fullscreen", className: `${iconClassName} ${isPipActive ? "opacity-50 cursor-not-allowed" : ""}` },
1124
- React.createElement("div", { onClick: handleFullscreen, className: isPipActive ? "pointer-events-none" : "" },
1087
+ React.createElement(Tooltip, { title: isFullscreen ? "Exit Fullscreen" : "Fullscreen", className: iconClassName },
1088
+ React.createElement("div", { onClick: handleFullscreen },
1125
1089
  React.createElement(FullScreenToggle, { isFullScreen: isFullscreen, className: iconClassName }))),
1126
- !isAdPlaying && (React.createElement(Tooltip, { className: "whitespace-nowrap", title: isPipActive ? "Exit PiP" : "Enter PiP" },
1127
- React.createElement("div", { onClick: handlePipToggle },
1128
- React.createElement(PiPictureInPictureToggle, { className: iconClassName })))),
1129
1090
  config?.onClose && (React.createElement(React.Fragment, null,
1130
1091
  React.createElement("div", { className: "w-[2px] h-10 bg-gray-500 hover:bg-gray-300 mx-2" }),
1131
1092
  React.createElement("div", { onClick: handleClose },
@@ -1278,8 +1239,8 @@ const MiddleControls = ({ config }) => {
1278
1239
  };
1279
1240
 
1280
1241
  const VideoPlayerControls = ({ config, isLive = false, }) => {
1281
- return (React.createElement("div", { className: "px-20" },
1282
- React.createElement("div", { className: "absolute top-0 left-0 h-full w-full bg-[rgba(0,0,0,0.5)] flex flex-col justify-between" },
1242
+ return (React.createElement("div", { className: "absolute inset-0" },
1243
+ React.createElement("div", { className: "absolute inset-0 bg-[rgba(0,0,0,0.5)] flex flex-col justify-between" },
1283
1244
  React.createElement(ControlsHeader, { config: config?.headerConfig?.config }),
1284
1245
  React.createElement(MiddleControls, { config: config?.middleConfig?.config }),
1285
1246
  React.createElement(BottomControls, { config: config?.bottomConfig?.config, isLive: isLive }))));
@@ -3625,7 +3586,7 @@ const VideoPlayer = React__default.memo(({ video, style, events, features }) =>
3625
3586
  return () => videoRef.removeEventListener("canplay", handleCanPlay);
3626
3587
  }, [videoRef, startFrom]);
3627
3588
  return (React__default.createElement("div", { ref: setVideoWrapperRef, className: `video-player ${height || "h-full"} ${width || "w-full"} mx-auto absolute` },
3628
- trackPoster && (React__default.createElement("div", { className: "pip-poster absolute inset-0 bg-center bg-cover hidden", style: { backgroundImage: `url(${trackPoster})` } })),
3589
+ trackPoster && (React__default.createElement("div", { className: "poster-bg absolute inset-0 bg-center bg-cover hidden", style: { backgroundImage: `url(${trackPoster})` } })),
3629
3590
  React__default.createElement("video", { playsInline: true, preload: hasPreRoll ? "metadata" : "auto", ref: registerVideoRef, onSeeked: onSeeked, poster: trackPoster, crossOrigin: "anonymous", controls: false, disableRemotePlayback: true, controlsList: "nodownload", onContextMenu: (e) => e.preventDefault(), onTimeUpdate: onTimeUpdate, onLoadedMetadata: onLoadedMetadata, onProgress: onProgress, onPlay: onPlay, onPause: onPause, onEnded: (e) => {
3630
3591
  onEndedHook(e);
3631
3592
  onEnded?.(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zezosoft/react-player",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "types": "dist/index.d.ts",
@@ -1,8 +0,0 @@
1
- import React from "react";
2
- import "../../VideoPlayer/components/styles/video-controls.css";
3
- interface PiPictureInPictureToggleProps {
4
- onClick?: () => void;
5
- className?: string;
6
- }
7
- declare const PiPictureInPictureToggle: React.FC<PiPictureInPictureToggleProps>;
8
- export default PiPictureInPictureToggle;