@xhub-short/ui 0.1.0-beta.8 → 1.0.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/CommentSheet.css-DuBy01rU.d.ts +219 -0
  2. package/dist/VideoSlotPlayIndicator-DPs8Xt5C.d.ts +51 -0
  3. package/dist/chunk-3OB3OVYR.js +349 -0
  4. package/dist/chunk-4RIMQOBR.js +58 -0
  5. package/dist/chunk-5MKYDI4X.js +1 -0
  6. package/dist/chunk-5Y43HNRG.js +296 -0
  7. package/dist/chunk-7WXAQHJI.js +350 -0
  8. package/dist/chunk-BADA7OLG.js +564 -0
  9. package/dist/chunk-BEJAJFV6.js +191 -0
  10. package/dist/chunk-BNI7CYRI.js +334 -0
  11. package/dist/{chunk-UPCVSGWH.js → chunk-CAWE42LH.js} +5 -2
  12. package/dist/chunk-DGKMO3AE.js +717 -0
  13. package/dist/chunk-DR7KR7OT.js +103 -0
  14. package/dist/chunk-GSNIZ6DF.js +605 -0
  15. package/dist/chunk-HXQPEZRG.js +105 -0
  16. package/dist/chunk-IC2KUU4V.js +1264 -0
  17. package/dist/chunk-IWSBYOSS.js +91 -0
  18. package/dist/chunk-MFJS65C5.js +368 -0
  19. package/dist/{chunk-CXPNPSF7.js → chunk-NJXIYSDZ.js} +12 -1
  20. package/dist/{chunk-NRQXKZO3.js → chunk-OM4L7RE5.js} +12 -2
  21. package/dist/chunk-QCRRF76W.js +75 -0
  22. package/dist/chunk-QUEJHA24.js +508 -0
  23. package/dist/chunk-UYBQTE4M.js +337 -0
  24. package/dist/chunk-VJ744W5N.js +603 -0
  25. package/dist/chunk-VXW7AOGM.js +285 -0
  26. package/dist/{chunk-OQ7P5XC7.js → chunk-YB7AXTX7.js} +1 -1
  27. package/dist/components/ActionBar/index.d.ts +7 -2
  28. package/dist/components/ActionBar/index.js +1 -1
  29. package/dist/components/AdvanceMenu/index.d.ts +80 -0
  30. package/dist/components/AdvanceMenu/index.js +1 -0
  31. package/dist/components/ArticleSlot/index.d.ts +213 -0
  32. package/dist/components/ArticleSlot/index.js +1 -0
  33. package/dist/components/AuthorInfo/index.js +1 -1
  34. package/dist/components/BottomSheet/index.d.ts +87 -0
  35. package/dist/components/BottomSheet/index.js +1 -0
  36. package/dist/components/CleanModeOverlay/index.d.ts +60 -0
  37. package/dist/components/CleanModeOverlay/index.js +1 -0
  38. package/dist/components/CommentSheet/index.d.ts +155 -3
  39. package/dist/components/CommentSheet/index.js +1 -1
  40. package/dist/components/DetailView/index.d.ts +314 -0
  41. package/dist/components/DetailView/index.js +1 -0
  42. package/dist/components/ErrorBoundary/index.js +1 -1
  43. package/dist/components/{VideoFeed → Feed}/index.d.ts +64 -45
  44. package/dist/components/Feed/index.js +1 -0
  45. package/dist/components/ImageCarousel/index.d.ts +50 -0
  46. package/dist/components/ImageCarousel/index.js +1 -0
  47. package/dist/components/Playlist/index.d.ts +117 -0
  48. package/dist/components/Playlist/index.js +1 -0
  49. package/dist/components/ProgressBar/index.js +1 -1
  50. package/dist/components/QualityPicker/index.d.ts +35 -0
  51. package/dist/components/QualityPicker/index.js +1 -0
  52. package/dist/components/ReportSheet/index.d.ts +74 -0
  53. package/dist/components/ReportSheet/index.js +1 -0
  54. package/dist/components/Skeleton/index.js +1 -1
  55. package/dist/components/SpeedPicker/index.d.ts +32 -0
  56. package/dist/components/SpeedPicker/index.js +1 -0
  57. package/dist/components/VideoInfo/index.d.ts +7 -3
  58. package/dist/components/VideoInfo/index.js +1 -1
  59. package/dist/components/VideoPlayer/index.js +1 -1
  60. package/dist/components/VideoSlot/index.d.ts +31 -68
  61. package/dist/components/VideoSlot/index.js +2 -1
  62. package/dist/components/VirtualSlider/index.js +1 -1
  63. package/dist/index.d.ts +74 -11
  64. package/dist/index.js +39 -15
  65. package/package.json +8 -4
  66. package/dist/CommentSheet.css-BD6XbpU2.d.ts +0 -207
  67. package/dist/chunk-EBAMBI3O.js +0 -571
  68. package/dist/chunk-K3CETRCY.js +0 -737
  69. package/dist/chunk-PGHLVKXS.js +0 -148
  70. package/dist/chunk-QF7O26KZ.js +0 -357
  71. package/dist/chunk-RKS7YA7Z.js +0 -562
  72. package/dist/chunk-T4RQWGRY.js +0 -1519
  73. package/dist/chunk-UXNIXHII.js +0 -2040
  74. package/dist/chunk-YWAPI7JO.js +0 -204
  75. package/dist/components/VideoFeed/index.js +0 -1
@@ -1,7 +1,8 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, ReactElement } from 'react';
3
3
  import { VideoSlotHeadlessProps, VideoItem, UIResourceState, UIPlayerState, UIPlayerControls } from '@xhub-short/contracts';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
+ export { V as VideoSlotPlayIndicator, c as VideoSlotPlayIndicatorInner, b as VideoSlotPlayIndicatorInnerProps, a as VideoSlotPlayIndicatorProps } from '../../VideoSlotPlayIndicator-DPs8Xt5C.js';
5
6
 
6
7
  interface VideoSlotHeadlessExtendedProps extends VideoSlotHeadlessProps {
7
8
  /** Children (overlay, poster, etc.) */
@@ -10,10 +11,22 @@ interface VideoSlotHeadlessExtendedProps extends VideoSlotHeadlessProps {
10
11
  onTap?: () => void;
11
12
  /** Handle double tap */
12
13
  onDoubleTap?: () => void;
14
+ /** Handle long press (hold > 500ms) */
15
+ onLongPress?: () => void;
16
+ /**
17
+ * Disable tap gesture handling.
18
+ * When true, single tap won't trigger play/pause toggle or PlayIndicator.
19
+ * Useful during zoom gesture to prevent phantom taps from touchend events.
20
+ */
21
+ disableTap?: boolean;
13
22
  /** Custom error UI */
14
23
  renderError?: (error: Error, retry: () => void) => ReactNode;
15
24
  /** Custom loading UI */
16
25
  renderLoading?: () => ReactNode;
26
+ /** Custom number of loop counts */
27
+ loopCount?: number;
28
+ /** Custom styles */
29
+ style?: React.CSSProperties;
17
30
  }
18
31
  /**
19
32
  * VideoSlotHeadless Component
@@ -46,7 +59,7 @@ interface VideoSlotHeadlessExtendedProps extends VideoSlotHeadlessProps {
46
59
  *
47
60
  * Wrapped with React.memo to prevent unnecessary re-renders.
48
61
  */
49
- declare function VideoSlotHeadlessBase({ video, resourceState, playerState, playerControls, className, children, onVisible: _onVisible, onHidden: _onHidden, onTap, onDoubleTap, renderError, renderLoading, restoreFrame, }: VideoSlotHeadlessExtendedProps): React.ReactElement;
62
+ declare function VideoSlotHeadlessBase({ video, resourceState, playerState, playerControls, className, children, onVisible: _onVisible, onHidden: _onHidden, onTap, onDoubleTap, onLongPress, disableTap, renderError, renderLoading, restoreFrame, style, }: VideoSlotHeadlessExtendedProps): React.ReactElement;
50
63
  /**
51
64
  * VideoSlotHeadless - Memoized for performance
52
65
  *
@@ -366,72 +379,22 @@ declare namespace VideoSlotLikeAnimation {
366
379
  var displayName: string;
367
380
  }
368
381
 
369
- /**
370
- * VideoSlotPlayIndicator - Shows play/pause icon when user taps video
371
- *
372
- * ONLY shows indicator when user explicitly taps to toggle play/pause.
373
- * Does NOT show on: swipe, auto-play, video loop, video change.
374
- *
375
- * Uses `lastUserToggleTime` from VideoSlotContext to detect user taps.
376
- *
377
- * ## Re-render Optimization
378
- *
379
- * Uses the "Context Selector" pattern to prevent re-renders:
380
- * - Outer component consumes context
381
- * - Inner component is memoized and receives data via props
382
- * - React.memo compares props → prevents re-render when context changes
383
- * but the selected values are the same
384
- *
385
- * @example
386
- * ```tsx
387
- * // Inside VideoSlot - auto-hide after tap
388
- * <VideoSlotPlayIndicator />
389
- *
390
- * // Persist play icon while paused (YouTube style)
391
- * <VideoSlotPlayIndicator persistWhenPaused />
392
- *
393
- * // With custom icons
394
- * <VideoSlotPlayIndicator
395
- * playIcon={<CustomPlayIcon />}
396
- * pauseIcon={<CustomPauseIcon />}
397
- * />
398
- * ```
399
- */
400
-
401
- interface VideoSlotPlayIndicatorProps {
402
- /** Custom play icon */
403
- playIcon?: ReactNode;
404
- /** Custom pause icon */
405
- pauseIcon?: ReactNode;
406
- /** Icon size in pixels */
407
- size?: number;
408
- /** Animation duration in ms */
409
- duration?: number;
410
- /**
411
- * Keep play icon visible while video is paused (YouTube style)
412
- * When false, icon auto-hides after duration
413
- */
414
- persistWhenPaused?: boolean;
415
- /** Additional CSS class */
382
+ interface ReportedVideoOverlayProps {
383
+ /** Handler when user wants to watch video anyway */
384
+ onWatchVideo: () => void;
385
+ /** Custom title text */
386
+ title?: string;
387
+ /** Custom message text */
388
+ message?: string;
389
+ /** Custom button text */
390
+ buttonText?: string;
391
+ /** Custom icon */
392
+ icon?: ReactNode;
393
+ /** Custom class name */
416
394
  className?: string;
417
- /** Test ID */
418
- testId?: string;
419
- }
420
- /**
421
- * VideoSlotPlayIndicator Component
422
- *
423
- * This outer component:
424
- * 1. Consumes context (will re-render when context changes)
425
- * 2. Selects only the needed values
426
- * 3. Passes them as props to memoized inner component
427
- *
428
- * The inner component will only re-render when the selected values change,
429
- * NOT when unrelated context values change (e.g., during seek operations).
430
- */
431
- declare function VideoSlotPlayIndicator(props: VideoSlotPlayIndicatorProps): React.ReactElement | null;
432
- declare namespace VideoSlotPlayIndicator {
433
- var displayName: string;
434
395
  }
396
+ declare function ReportedVideoOverlayComponent({ onWatchVideo, title, message, buttonText, icon, className, }: ReportedVideoOverlayProps): ReactElement;
397
+ declare const ReportedVideoOverlay: react.MemoExoticComponent<typeof ReportedVideoOverlayComponent>;
435
398
 
436
399
  interface VideoSlotContextValue {
437
400
  /** Video item data */
@@ -636,7 +599,7 @@ declare const Z_INDEX_CSS_VARS: {
636
599
  * - Avoids global selectors
637
600
  * - Follows BEM-like naming: sv-video-slot__[element]--[modifier]
638
601
  */
639
- declare const VIDEO_SLOT_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Z-INDEX LAYERING CONTRACT\n * \n * Override these variables to customize layer stacking:\n * --sv-z-poster: Poster/Thumbnail layer (default: 3)\n * --sv-z-slot-spinner: Loading spinner layer (default: 2)\n * --sv-z-indicator: Error/Play indicator layer (default: 4)\n * --sv-z-progress: Progress bar layer (default: 5)\n *\n * Layer Stack (bottom to top):\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 z-index: 5 - Progress Bar (topmost) \u2502\n * \u2502 z-index: 4 - Error UI / Play Indicator \u2502\n * \u2502 z-index: 3 - Poster / Thumbnail \u2502\n * \u2502 z-index: 2 - Loading Spinner \u2502\n * \u2502 z-index: 1 - Video Element \u2502\n * \u2502 z-index: 0 - Slot Container (base) \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * VideoSlot - Container for individual video in feed\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: var(--sv-bg-primary, #000);\n /* Touch optimization */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n /* GPU acceleration */\n will-change: contents;\n contain: layout style paint;\n}\n\n/* Active slot (currently visible) */\n.sv-video-slot--active {\n z-index: 1;\n}\n\n/* Loading state */\n.sv-video-slot--loading .sv-video-slot__video {\n opacity: 0;\n}\n\n.sv-video-slot--loading .sv-video-slot__poster {\n opacity: 1;\n}\n\n/* Playing state */\n.sv-video-slot--playing .sv-video-slot__video {\n opacity: 1;\n}\n\n.sv-video-slot--playing .sv-video-slot__poster {\n opacity: 0;\n}\n\n/* Paused state - keep poster hidden (show paused video frame, not poster) */\n.sv-video-slot--paused .sv-video-slot__video {\n opacity: 1;\n}\n\n.sv-video-slot--paused .sv-video-slot__poster {\n opacity: 0;\n}\n\n/* Hidden poster (explicit class applied by VideoSlotPoster component) */\n.sv-video-slot__poster--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Error state */\n.sv-video-slot--error {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Video Element\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__video-container {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sv-video-slot__video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n background-color: transparent;\n /* Smooth fade transition */\n transition: opacity var(--sv-transition-duration, 300ms) ease-out;\n}\n\n/* Video loaded but not playing yet */\n.sv-video-slot__video[data-loaded=\"true\"] {\n opacity: 1;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Poster / Thumbnail / First Frame\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__poster {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--sv-bg-primary, #000);\n /* Poster should be ABOVE spinner (z-index: 2) so thumbnail shows instead of spinner */\n z-index: var(--sv-z-poster, 3);\n /* Smooth fade transition */\n transition: opacity var(--sv-transition-duration, 300ms) ease-out;\n pointer-events: none;\n}\n\n.sv-video-slot__poster-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n/* First frame (client-captured) */\n.sv-video-slot__poster--first-frame .sv-video-slot__poster-image {\n image-rendering: auto;\n}\n\n/* Skeleton placeholder */\n.sv-video-slot__poster--skeleton {\n background: linear-gradient(\n 110deg,\n var(--sv-skeleton-bg, rgba(255, 255, 255, 0.05)) 0%,\n var(--sv-skeleton-shimmer, rgba(255, 255, 255, 0.1)) 50%,\n var(--sv-skeleton-bg, rgba(255, 255, 255, 0.05)) 100%\n );\n background-size: 200% 100%;\n animation: sv-slot-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes sv-slot-skeleton-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Overlay Container\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__overlay {\n position: absolute;\n inset: 0;\n z-index: var(--sv-z-overlay, 2);\n /* Gradient background for better text visibility */\n background: linear-gradient(\n to top,\n rgba(0, 0, 0, 0.6) 0%,\n rgba(0, 0, 0, 0.3) 20%,\n transparent 40%,\n transparent 60%,\n rgba(0, 0, 0, 0.2) 80%,\n rgba(0, 0, 0, 0.4) 100%\n );\n pointer-events: none;\n}\n\n/* \n * Overlay sections should NOT block clicks (pass-through to container for play/pause)\n * Only actual interactive elements (buttons, links) inside sections should receive clicks.\n * \n * DO NOT use: .sv-video-slot__overlay > * { pointer-events: auto; }\n * This would make entire sections block clicks even on \"empty\" areas.\n */\n.sv-video-slot__overlay-top,\n.sv-video-slot__overlay-bottom,\n.sv-video-slot__overlay-left,\n.sv-video-slot__overlay-right,\n.sv-video-slot__actions,\n.sv-video-slot__author {\n pointer-events: none;\n}\n\n/* Only interactive elements inside overlay sections should receive clicks */\n.sv-video-slot__overlay button,\n.sv-video-slot__overlay a,\n.sv-video-slot__overlay [role=\"button\"],\n.sv-video-slot__overlay input,\n.sv-video-slot__overlay label,\n.sv-video-slot__overlay .sv-progress-bar,\n.sv-video-slot__overlay .sv-author-info,\n.sv-video-slot__overlay .sv-video-info,\n.sv-video-slot__overlay .sv-action-bar {\n pointer-events: auto;\n}\n\n/* Overlay sections */\n.sv-video-slot__overlay-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n padding: var(--sv-spacing-md, 16px);\n padding-top: calc(var(--sv-safe-area-top, 0px) + var(--sv-spacing-md, 16px));\n}\n\n.sv-video-slot__overlay-bottom {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0px;\n padding: var(--sv-spacing-md, 16px);\n padding-bottom: calc(var(--sv-safe-area-bottom, 0px) + var(--sv-spacing-md, 16px));\n display: flex;\n flex-direction: column;\n gap: var(--sv-spacing-sm, 8px);\n}\n\n.sv-video-slot__overlay-left {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n padding: var(--sv-spacing-md, 16px);\n}\n\n.sv-video-slot__overlay-right {\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n padding: var(--sv-spacing-md, 16px);\n}\n\n/* Action bar (typically right side) */\n.sv-video-slot__actions {\n position: absolute;\n right: var(--sv-spacing-sm, 8px);\n bottom: calc(var(--sv-safe-area-bottom, 0px) + 80px);\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* Author info (above bottom section, left side) */\n.sv-video-slot__author {\n position: absolute;\n left: var(--sv-spacing-md, 16px);\n /* Position above .sv-video-slot__overlay-bottom (which has ~80px content) */\n bottom: calc(var(--sv-safe-area-bottom, 0px) + 100px);\n right: 80px; /* Leave space for actions */\n max-width: calc(100% - 100px); /* Don't overlap with actions */\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Error State\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__error {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background-color: var(--sv-bg-primary, #000);\n color: var(--sv-text-secondary, #999);\n text-align: center;\n padding: var(--sv-spacing-lg, 20px);\n gap: var(--sv-spacing-md, 16px);\n z-index: var(--sv-z-indicator, 3);\n}\n\n.sv-video-slot__error-icon {\n font-size: 48px;\n opacity: 0.6;\n}\n\n.sv-video-slot__error-message {\n font-size: var(--sv-font-size-md, 14px);\n max-width: 200px;\n}\n\n.sv-video-slot__error-retry {\n padding: var(--sv-spacing-sm, 8px) var(--sv-spacing-md, 16px);\n background-color: var(--sv-color-primary, #fe2c55);\n color: #fff;\n border: none;\n border-radius: var(--sv-radius-md, 8px);\n font-size: var(--sv-font-size-sm, 12px);\n font-weight: 600;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n\n.sv-video-slot__error-retry:hover {\n background-color: var(--sv-color-primary-hover, #e02850);\n}\n\n.sv-video-slot__error-retry:active {\n transform: scale(0.96);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Loading Spinner\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__spinner {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n /* Use slot-specific z-index (not global --sv-z-overlay which may conflict) */\n z-index: var(--sv-z-slot-spinner, 2);\n}\n\n.sv-video-slot__spinner-circle {\n width: 40px;\n height: 40px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: var(--sv-color-primary, #fe2c55);\n border-radius: 50%;\n animation: sv-slot-spin 0.8s linear infinite;\n}\n\n@keyframes sv-slot-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Play/Pause Visual Indicator\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__play-indicator {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 64px;\n height: 64px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n z-index: var(--sv-z-indicator, 3);\n opacity: 0;\n transition: opacity 200ms ease-out;\n pointer-events: none;\n}\n\n/* Show indicator */\n.sv-video-slot__play-indicator--visible {\n opacity: 0.65;\n}\n\n/* Persist mode: stay visible, no animation */\n.sv-video-slot__play-indicator--persist {\n opacity: 0.65;\n}\n\n/* Animating out: scale up + fade out */\n.sv-video-slot__play-indicator--animating-out {\n animation: sv-slot-indicator-out var(--sv-indicator-duration, 200ms) ease-out forwards;\n}\n\n@keyframes sv-slot-indicator-out {\n 0% {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translate(-50%, -50%) scale(1.5);\n }\n}\n\n.sv-video-slot__play-indicator-icon {\n color: #fff;\n font-size: 28px;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Progress Bar\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__progress {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 3px;\n background-color: rgba(255, 255, 255, 0.2);\n z-index: var(--sv-z-progress, 4);\n}\n\n.sv-video-slot__progress-bar {\n height: 100%;\n background-color: var(--sv-color-primary, #fe2c55);\n transition: width 100ms linear;\n}\n\n.sv-video-slot__progress-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background-color: rgba(255, 255, 255, 0.3);\n}\n";
602
+ declare const VIDEO_SLOT_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Z-INDEX LAYERING CONTRACT\n * \n * Override these variables to customize layer stacking:\n * --sv-z-poster: Poster/Thumbnail layer (default: 3)\n * --sv-z-slot-spinner: Loading spinner layer (default: 2)\n * --sv-z-indicator: Error/Play indicator layer (default: 4)\n * --sv-z-progress: Progress bar layer (default: 5)\n *\n * Layer Stack (bottom to top):\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 z-index: 5 - Progress Bar (topmost) \u2502\n * \u2502 z-index: 4 - Error UI / Play Indicator \u2502\n * \u2502 z-index: 3 - Poster / Thumbnail \u2502\n * \u2502 z-index: 2 - Loading Spinner \u2502\n * \u2502 z-index: 1 - Video Element \u2502\n * \u2502 z-index: 0 - Slot Container (base) \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * VideoSlot - Container for individual video in feed\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: var(--sv-bg-primary, #000);\n /* Touch optimization */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n /* GPU acceleration */\n will-change: contents;\n contain: layout style paint;\n}\n\n/* Active slot (currently visible) */\n.sv-video-slot--active {\n z-index: 1;\n}\n\n/* Loading state */\n.sv-video-slot--loading .sv-video-slot__video {\n opacity: 0;\n}\n\n.sv-video-slot--loading .sv-video-slot__poster {\n opacity: 1;\n}\n\n/* Playing state */\n.sv-video-slot--playing .sv-video-slot__video {\n opacity: 1;\n}\n\n.sv-video-slot--playing .sv-video-slot__poster {\n opacity: 0;\n}\n\n/* Paused state - keep poster hidden (show paused video frame, not poster) */\n.sv-video-slot--paused .sv-video-slot__video {\n opacity: 1;\n}\n\n.sv-video-slot--paused .sv-video-slot__poster {\n opacity: 0;\n}\n\n/* Hidden poster (explicit class applied by VideoSlotPoster component) */\n.sv-video-slot__poster--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Error state */\n.sv-video-slot--error {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Video Element\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__video-container {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sv-video-slot__video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n background-color: transparent;\n /* Smooth fade transition */\n transition: opacity var(--sv-transition-duration, 300ms) ease-out;\n}\n\n/* Video loaded but not playing yet */\n.sv-video-slot__video[data-loaded=\"true\"] {\n opacity: 1;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Poster / Thumbnail / First Frame\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__poster {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--sv-bg-primary, #000);\n /* Poster should be ABOVE spinner (z-index: 2) so thumbnail shows instead of spinner */\n z-index: var(--sv-z-poster, 3);\n /* Smooth fade transition */\n transition: opacity var(--sv-transition-duration, 300ms) ease-out;\n pointer-events: none;\n}\n\n.sv-video-slot__poster-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n/* First frame (client-captured) */\n.sv-video-slot__poster--first-frame .sv-video-slot__poster-image {\n image-rendering: auto;\n}\n\n/* Skeleton placeholder */\n.sv-video-slot__poster--skeleton {\n background: linear-gradient(\n 110deg,\n var(--sv-skeleton-bg, rgba(255, 255, 255, 0.05)) 0%,\n var(--sv-skeleton-shimmer, rgba(255, 255, 255, 0.1)) 50%,\n var(--sv-skeleton-bg, rgba(255, 255, 255, 0.05)) 100%\n );\n background-size: 200% 100%;\n animation: sv-slot-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes sv-slot-skeleton-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Overlay Container\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__overlay {\n position: absolute;\n inset: 0;\n z-index: var(--sv-z-overlay, 2);\n /* Gradient background for better text visibility */\n background: linear-gradient(\n to top,\n rgba(0, 0, 0, 0.6) 0%,\n rgba(0, 0, 0, 0.3) 20%,\n transparent 40%,\n transparent 60%,\n rgba(0, 0, 0, 0.2) 80%,\n rgba(0, 0, 0, 0.4) 100%\n );\n pointer-events: none;\n}\n\n/* \n * Overlay sections should NOT block clicks (pass-through to container for play/pause)\n * Only actual interactive elements (buttons, links) inside sections should receive clicks.\n * \n * DO NOT use: .sv-video-slot__overlay > * { pointer-events: auto; }\n * This would make entire sections block clicks even on \"empty\" areas.\n */\n.sv-video-slot__overlay-top,\n.sv-video-slot__overlay-bottom,\n.sv-video-slot__overlay-left,\n.sv-video-slot__overlay-right,\n.sv-video-slot__actions,\n.sv-video-slot__author {\n pointer-events: none;\n}\n\n/* Only interactive elements inside overlay sections should receive clicks */\n.sv-video-slot__overlay button,\n.sv-video-slot__overlay a,\n.sv-video-slot__overlay [role=\"button\"],\n.sv-video-slot__overlay input,\n.sv-video-slot__overlay label,\n.sv-video-slot__overlay .sv-progress-bar,\n.sv-video-slot__overlay .sv-author-info,\n.sv-video-slot__overlay .sv-video-info,\n.sv-video-slot__overlay .sv-action-bar {\n pointer-events: auto;\n}\n\n/* Overlay sections */\n.sv-video-slot__overlay-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n padding: var(--sv-spacing-md, 16px);\n padding-top: calc(var(--sv-safe-area-top, 0px) + var(--sv-spacing-md, 16px));\n}\n\n.sv-video-slot__overlay-bottom {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0px;\n padding: var(--sv-spacing-md, 16px);\n padding-bottom: calc(var(--sv-safe-area-bottom, 0px) + var(--sv-spacing-md, 16px));\n display: flex;\n flex-direction: column;\n gap: var(--sv-spacing-sm, 8px);\n}\n\n.sv-video-slot__overlay-left {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n padding: var(--sv-spacing-md, 16px);\n}\n\n.sv-video-slot__overlay-right {\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n padding: var(--sv-spacing-md, 16px);\n}\n\n/* Action bar (typically right side) */\n.sv-video-slot__actions {\n position: absolute;\n right: var(--sv-spacing-sm, 8px);\n bottom: calc(var(--sv-safe-area-bottom, 0px) + var(--sv-actions-bottom, 80px) + var(--sv-playlist-bar-offset, 0px));\n display: flex;\n flex-direction: column;\n align-items: center;\n transition: bottom 0.3s ease-in-out;\n}\n\n/* Author info (above bottom section, left side) */\n.sv-video-slot__author {\n position: absolute;\n left: var(--sv-spacing-md, 16px);\n /* Position above .sv-video-slot__overlay-bottom (which has ~80px content) */\n bottom: calc(var(--sv-safe-area-bottom, 0px) + var(--sv-author-bottom, 100px) + var(--sv-playlist-bar-offset, 0px));\n right: 80px; /* Leave space for actions */\n max-width: calc(100% - 100px); /* Don't overlap with actions */\n transition: bottom 0.3s ease-in-out;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Error State\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__error {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background-color: var(--sv-bg-primary, #000);\n color: var(--sv-text-secondary, #999);\n text-align: center;\n padding: var(--sv-spacing-lg, 20px);\n gap: var(--sv-spacing-md, 16px);\n z-index: var(--sv-z-indicator, 3);\n}\n\n.sv-video-slot__error-icon {\n font-size: 48px;\n opacity: 0.6;\n}\n\n.sv-video-slot__error-message {\n font-size: var(--sv-font-size-md, 14px);\n max-width: 200px;\n}\n\n.sv-video-slot__error-retry {\n padding: var(--sv-spacing-sm, 8px) var(--sv-spacing-md, 16px);\n background-color: var(--sv-color-primary, #fe2c55);\n color: #fff;\n border: none;\n border-radius: var(--sv-radius-md, 8px);\n font-size: var(--sv-font-size-sm, 12px);\n font-weight: 600;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n\n.sv-video-slot__error-retry:hover {\n background-color: var(--sv-color-primary-hover, #e02850);\n}\n\n.sv-video-slot__error-retry:active {\n transform: scale(0.96);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Loading Spinner\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__spinner {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n /* Use slot-specific z-index (not global --sv-z-overlay which may conflict) */\n z-index: var(--sv-z-slot-spinner, 2);\n}\n\n.sv-video-slot__spinner-circle {\n width: 40px;\n height: 40px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: var(--sv-color-primary, #fe2c55);\n border-radius: 50%;\n animation: sv-slot-spin 0.8s linear infinite;\n}\n\n@keyframes sv-slot-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Play/Pause Visual Indicator\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__play-indicator {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 64px;\n height: 64px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n z-index: var(--sv-z-indicator, 3);\n opacity: 0;\n transition: opacity 200ms ease-out;\n pointer-events: none;\n}\n\n/* Show indicator */\n.sv-video-slot__play-indicator--visible {\n opacity: 0.65;\n}\n\n/* Persist mode: stay visible, no animation */\n.sv-video-slot__play-indicator--persist {\n opacity: 0.65;\n}\n\n/* Animating out: scale up + fade out */\n.sv-video-slot__play-indicator--animating-out {\n animation: sv-slot-indicator-out var(--sv-indicator-duration, 200ms) ease-out forwards;\n}\n\n@keyframes sv-slot-indicator-out {\n 0% {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translate(-50%, -50%) scale(1.5);\n }\n}\n\n.sv-video-slot__play-indicator-icon {\n color: #fff;\n font-size: 28px;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * Progress Bar\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-video-slot__progress {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 3px;\n background-color: rgba(255, 255, 255, 0.2);\n z-index: var(--sv-z-progress, 4);\n}\n\n.sv-video-slot__progress-bar {\n height: 100%;\n background-color: var(--sv-color-primary, #fe2c55);\n transition: width 100ms linear;\n}\n\n.sv-video-slot__progress-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background-color: rgba(255, 255, 255, 0.3);\n}\n";
640
603
 
641
604
  /**
642
605
  * VideoSlotLikeAnimation CSS Styles
@@ -649,4 +612,4 @@ declare const VIDEO_SLOT_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\
649
612
  */
650
613
  declare const VIDEO_SLOT_LIKE_ANIMATION_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Container\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-like-animation-container {\n position: absolute;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n z-index: var(--sv-z-indicator, 3);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Single Heart\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-like-heart {\n position: absolute;\n left: var(--sv-heart-x, 50%);\n top: var(--sv-heart-y, 50%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n will-change: transform, opacity;\n}\n\n.sv-like-heart__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--sv-heart-size, 80px);\n height: var(--sv-heart-size, 80px);\n transform-origin: center;\n animation-duration: var(--sv-heart-duration, 1000ms);\n animation-fill-mode: forwards;\n animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Float Animation (TikTok style)\n - Hearts float upward while wiggling\n - Fades out near the top\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-like-heart--float .sv-like-heart__icon {\n animation-name: sv-heart-float;\n animation-timing-function: ease-out;\n}\n\n@keyframes sv-heart-float {\n 0% {\n opacity: 0;\n transform: scale(0) rotate(var(--sv-heart-rotation, 0deg));\n }\n 10% {\n opacity: 1;\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.2)) rotate(var(--sv-heart-rotation, 0deg));\n }\n 20% {\n transform: \n scale(var(--sv-heart-scale, 1)) \n rotate(var(--sv-heart-rotation, 0deg)) \n translateY(-20px) \n translateX(10px);\n }\n 40% {\n transform: \n scale(var(--sv-heart-scale, 1)) \n rotate(calc(var(--sv-heart-rotation, 0deg) - 10deg)) \n translateY(-60px) \n translateX(-15px);\n }\n 60% {\n opacity: 1;\n transform: \n scale(var(--sv-heart-scale, 1)) \n rotate(calc(var(--sv-heart-rotation, 0deg) + 15deg)) \n translateY(-100px) \n translateX(10px);\n }\n 80% {\n opacity: 0.6;\n transform: \n scale(calc(var(--sv-heart-scale, 1) * 0.9)) \n rotate(calc(var(--sv-heart-rotation, 0deg) - 5deg)) \n translateY(-140px) \n translateX(-5px);\n }\n 100% {\n opacity: 0;\n transform: \n scale(calc(var(--sv-heart-scale, 1) * 0.7)) \n rotate(var(--sv-heart-rotation, 0deg)) \n translateY(-180px) \n translateX(0);\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Burst Animation\n - Heart bursts outward with energy\n - Scales up quickly then fades\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-like-heart--burst .sv-like-heart__icon {\n animation-name: sv-heart-burst;\n animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);\n}\n\n@keyframes sv-heart-burst {\n 0% {\n opacity: 0;\n transform: scale(0) rotate(var(--sv-heart-rotation, 0deg));\n }\n 20% {\n opacity: 1;\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.5)) rotate(calc(var(--sv-heart-rotation, 0deg) + 15deg));\n }\n 40% {\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.2)) rotate(calc(var(--sv-heart-rotation, 0deg) - 10deg));\n }\n 60% {\n opacity: 1;\n transform: scale(var(--sv-heart-scale, 1)) rotate(var(--sv-heart-rotation, 0deg)) translateY(-30px);\n }\n 80% {\n opacity: 0.5;\n transform: scale(calc(var(--sv-heart-scale, 1) * 0.9)) rotate(var(--sv-heart-rotation, 0deg)) translateY(-60px);\n }\n 100% {\n opacity: 0;\n transform: scale(calc(var(--sv-heart-scale, 1) * 0.6)) rotate(var(--sv-heart-rotation, 0deg)) translateY(-80px);\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Scale Animation\n - Simple scale up and fade\n - Clean and minimal\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-like-heart--scale .sv-like-heart__icon {\n animation-name: sv-heart-scale;\n animation-timing-function: ease-out;\n}\n\n@keyframes sv-heart-scale {\n 0% {\n opacity: 0;\n transform: scale(0);\n }\n 20% {\n opacity: 1;\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.3));\n }\n 40% {\n transform: scale(var(--sv-heart-scale, 1));\n }\n 70% {\n opacity: 1;\n transform: scale(var(--sv-heart-scale, 1));\n }\n 100% {\n opacity: 0;\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.1));\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Bounce Animation\n - Heart bounces in place with energy\n - Playful and fun\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-like-heart--bounce .sv-like-heart__icon {\n animation-name: sv-heart-bounce;\n animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);\n}\n\n@keyframes sv-heart-bounce {\n 0% {\n opacity: 0;\n transform: scale(0) rotate(var(--sv-heart-rotation, 0deg)) translateY(0);\n }\n 15% {\n opacity: 1;\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.4)) rotate(calc(var(--sv-heart-rotation, 0deg) + 10deg)) translateY(-30px);\n }\n 30% {\n transform: scale(calc(var(--sv-heart-scale, 1) * 0.9)) rotate(calc(var(--sv-heart-rotation, 0deg) - 5deg)) translateY(10px);\n }\n 45% {\n transform: scale(calc(var(--sv-heart-scale, 1) * 1.15)) rotate(calc(var(--sv-heart-rotation, 0deg) + 5deg)) translateY(-15px);\n }\n 60% {\n opacity: 1;\n transform: scale(var(--sv-heart-scale, 1)) rotate(var(--sv-heart-rotation, 0deg)) translateY(0);\n }\n 80% {\n opacity: 0.7;\n transform: scale(var(--sv-heart-scale, 1)) rotate(var(--sv-heart-rotation, 0deg)) translateY(-10px);\n }\n 100% {\n opacity: 0;\n transform: scale(calc(var(--sv-heart-scale, 1) * 0.8)) rotate(var(--sv-heart-rotation, 0deg)) translateY(-20px);\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Accessibility: Reduce motion\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@media (prefers-reduced-motion: reduce) {\n .sv-like-heart__icon {\n animation-duration: 0.5s !important;\n }\n \n .sv-like-heart--float .sv-like-heart__icon,\n .sv-like-heart--burst .sv-like-heart__icon,\n .sv-like-heart--bounce .sv-like-heart__icon {\n animation-name: sv-heart-scale;\n }\n}\n";
651
614
 
652
- export { type HeartInstance, LOADING_ATTR, LOADING_DATASET_KEY, type LikeAnimationElement, type LikeAnimationStyle, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_CLASS, SLOT_ACTIVE_DATASET_KEY, SLOT_CLASS, SLOT_ERROR_CLASS, SLOT_LOADING_CLASS, SLOT_PAUSED_CLASS, SLOT_PLAYING_CLASS, VIDEO_ID_ATTR, VIDEO_ID_DATASET_KEY, VIDEO_SLOT_CSS, VIDEO_SLOT_LIKE_ANIMATION_CSS, VideoSlotContext, type VideoSlotContextValue, VideoSlotHeadless, type VideoSlotHeadlessExtendedProps, VideoSlotLikeAnimation, type VideoSlotLikeAnimationProps, type VideoSlotLikeAnimationRef, VideoSlotOverlay, type VideoSlotOverlayProps, type VideoSlotOverlayRegionProps, VideoSlotPlayIndicator, type VideoSlotPlayIndicatorProps, VideoSlotPoster, type VideoSlotPosterProps, VideoSlotSkeleton, Z_INDEX, Z_INDEX_CSS_VARS, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo };
615
+ export { type HeartInstance, LOADING_ATTR, LOADING_DATASET_KEY, type LikeAnimationElement, type LikeAnimationStyle, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, ReportedVideoOverlay, type ReportedVideoOverlayProps, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_CLASS, SLOT_ACTIVE_DATASET_KEY, SLOT_CLASS, SLOT_ERROR_CLASS, SLOT_LOADING_CLASS, SLOT_PAUSED_CLASS, SLOT_PLAYING_CLASS, VIDEO_ID_ATTR, VIDEO_ID_DATASET_KEY, VIDEO_SLOT_CSS, VIDEO_SLOT_LIKE_ANIMATION_CSS, VideoSlotContext, type VideoSlotContextValue, VideoSlotHeadless, type VideoSlotHeadlessExtendedProps, VideoSlotLikeAnimation, type VideoSlotLikeAnimationProps, type VideoSlotLikeAnimationRef, VideoSlotOverlay, type VideoSlotOverlayProps, type VideoSlotOverlayRegionProps, VideoSlotPoster, type VideoSlotPosterProps, VideoSlotSkeleton, Z_INDEX, Z_INDEX_CSS_VARS, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo };
@@ -1 +1,2 @@
1
- export { LOADING_ATTR, LOADING_DATASET_KEY, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_CLASS, SLOT_ACTIVE_DATASET_KEY, SLOT_CLASS, SLOT_ERROR_CLASS, SLOT_LOADING_CLASS, SLOT_PAUSED_CLASS, SLOT_PLAYING_CLASS, VIDEO_ID_ATTR, VIDEO_ID_DATASET_KEY, VIDEO_SLOT_CSS, VIDEO_SLOT_LIKE_ANIMATION_CSS, VideoSlotContext, VideoSlotHeadless, VideoSlotLikeAnimation, VideoSlotOverlay, VideoSlotPlayIndicator, VideoSlotPoster, VideoSlotSkeleton, Z_INDEX, Z_INDEX_CSS_VARS, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from '../../chunk-T4RQWGRY.js';
1
+ export { LOADING_ATTR, LOADING_DATASET_KEY, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, ReportedVideoOverlay, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_CLASS, SLOT_ACTIVE_DATASET_KEY, SLOT_CLASS, SLOT_ERROR_CLASS, SLOT_LOADING_CLASS, SLOT_PAUSED_CLASS, SLOT_PLAYING_CLASS, VIDEO_ID_ATTR, VIDEO_ID_DATASET_KEY, VIDEO_SLOT_CSS, VIDEO_SLOT_LIKE_ANIMATION_CSS, VideoSlotHeadless, VideoSlotLikeAnimation, VideoSlotOverlay, VideoSlotPoster, VideoSlotSkeleton, Z_INDEX, Z_INDEX_CSS_VARS } from '../../chunk-VJ744W5N.js';
2
+ export { VideoSlotContext, VideoSlotPlayIndicator, VideoSlotPlayIndicatorInner, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from '../../chunk-MFJS65C5.js';
@@ -1 +1 @@
1
- export { DEFAULT_BUFFER_SIZE, DEFAULT_EMPTY_TEXT, DEFAULT_END_REACHED_THRESHOLD, DEFAULT_END_TEXT, DEFAULT_LOADING_TEXT, SLIDER_CLASS, SLIDER_CONTAINER_CLASS, SLIDER_CONTAINER_SNAPPING_CLASS, SLIDER_CONTAINER_SWIPING_CLASS, SLIDER_SLOT_ACTIVE_CLASS, SLIDER_SLOT_ADJACENT_CLASS, SLIDER_SLOT_CLASS, SLIDER_SLOT_TRANSITIONING_CLASS, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, VIRTUAL_SLIDER_CSS, VirtualSlider, VirtualSliderContext, getSlotIndexFromPosition, useOptionalVirtualSliderContext, useSliderActiveIndex, useSliderIsSwiping, useSliderPosition, useVirtualSliderContext } from '../../chunk-OQ7P5XC7.js';
1
+ export { DEFAULT_BUFFER_SIZE, DEFAULT_EMPTY_TEXT, DEFAULT_END_REACHED_THRESHOLD, DEFAULT_END_TEXT, DEFAULT_LOADING_TEXT, SLIDER_CLASS, SLIDER_CONTAINER_CLASS, SLIDER_CONTAINER_SNAPPING_CLASS, SLIDER_CONTAINER_SWIPING_CLASS, SLIDER_SLOT_ACTIVE_CLASS, SLIDER_SLOT_ADJACENT_CLASS, SLIDER_SLOT_CLASS, SLIDER_SLOT_TRANSITIONING_CLASS, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, VIRTUAL_SLIDER_CSS, VirtualSlider, VirtualSliderContext, getSlotIndexFromPosition, useOptionalVirtualSliderContext, useSliderActiveIndex, useSliderIsSwiping, useSliderPosition, useVirtualSliderContext } from '../../chunk-YB7AXTX7.js';
package/dist/index.d.ts CHANGED
@@ -2,18 +2,28 @@ import { VideoItem, UIPlayerState, UIPlayerControls, UIInteractionState, UIInter
2
2
  import * as react from 'react';
3
3
  import { ReactNode, ReactElement } from 'react';
4
4
  export { clsx, clsx as cn } from 'clsx';
5
- export { ErrorBoundary, ErrorBoundaryProps, ErrorMode } from './components/ErrorBoundary/index.js';
6
- export { Skeleton, SkeletonAnimation, SkeletonAvatar, SkeletonProps, SkeletonText, SkeletonVideo } from './components/Skeleton/index.js';
5
+ export { ACTION_BAR_CSS, ActionBarBookmark, ActionBarComment, ActionBarHeadless, ActionBarHeadlessExtendedProps, ActionBarLike, ActionBarShare, ActionButton, ActionButtonExtendedProps, BookmarkButton, BookmarkButtonProps, CommentButton, CommentButtonProps, LikeButton, LikeButtonProps, ShareButton, ShareButtonProps } from './components/ActionBar/index.js';
6
+ export { ADVANCE_MENU_CSS, AdvanceMenuHeadless, AdvanceMenuHeadlessProps, AdvanceMenuItemProps, AdvanceMenuSectionTitleProps, AdvanceMenuSeparatorProps } from './components/AdvanceMenu/index.js';
7
+ export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, ArticleSlotActionsProps, ArticleSlotBottom, ArticleSlotBottomProps, ArticleSlotCaption, ArticleSlotCaptionProps, ArticleSlotContextValue, ArticleSlotHeadless, ArticleSlotHeadlessProps, ArticleSlotMusic, ArticleSlotMusicProps, ArticleSlotOverlay, ArticleSlotOverlayProps, ArticleSlotPlayIndicator, ArticleSlotPlayIndicatorProps, ArticleSlotReadMore, ArticleSlotReadMoreProps, ARTICLE_ACTIVE_ATTR as IMAGE_POST_ACTIVE_ATTR, ARTICLE_ID_ATTR as IMAGE_POST_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS as IMAGE_POST_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS as IMAGE_POST_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS as IMAGE_POST_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS as IMAGE_POST_SLOT_CSS, ArticleSlotActions as ImagePostSlotActions, ArticleSlotActionsProps as ImagePostSlotActionsProps, ArticleSlotBottom as ImagePostSlotBottom, ArticleSlotBottomProps as ImagePostSlotBottomProps, ArticleSlotCaption as ImagePostSlotCaption, ArticleSlotCaptionProps as ImagePostSlotCaptionProps, ArticleSlotContextValue as ImagePostSlotContextValue, ArticleSlotHeadless as ImagePostSlotHeadless, ArticleSlotHeadlessProps as ImagePostSlotHeadlessProps, ArticleSlotMusic as ImagePostSlotMusic, ArticleSlotMusicProps as ImagePostSlotMusicProps, ArticleSlotOverlay as ImagePostSlotOverlay, ArticleSlotOverlayProps as ImagePostSlotOverlayProps, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, ArticleSlotPlayIndicatorProps as ImagePostSlotPlayIndicatorProps, ArticleSlotReadMore as ImagePostSlotReadMore, ArticleSlotReadMoreProps as ImagePostSlotReadMoreProps, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext } from './components/ArticleSlot/index.js';
8
+ export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorAvatarProps, AuthorDescription, AuthorDescriptionProps, AuthorInfoContext, AuthorInfoContextValue, AuthorInfoHeadless, AuthorInfoHeadlessExtendedProps, AuthorInfoVariant, AuthorName, AuthorNameProps, AvatarSize, FollowButton, FollowButtonProps, FollowButtonSize, useAuthorInfoContext, useOptionalAuthorInfoContext } from './components/AuthorInfo/index.js';
9
+ export { BUFFERING_STATE_CLASS, ENDED_CLASS, ERROR_CLASS, ERROR_STATE_CLASS, LOADING_CLASS, LOADING_STATE_ATTR, LOADING_STATE_CLASS, PAUSED_CLASS, PLAYBACK_STATE_ATTR, PLAYER_CLASS, PLAYING_CLASS, POSTER_CLASS, READY_CLASS, UseAutoFirstFrameCaptureConfig, UseFirstFrameCaptureConfig, UseFirstFrameCaptureReturn, UseVideoElementConfig, UseVideoElementReturn, VIDEO_CLASS, VIDEO_PLAYER_CSS, Z_INDEX as VIDEO_PLAYER_Z_INDEX, Z_INDEX_CSS_VARS as VIDEO_PLAYER_Z_INDEX_CSS_VARS, VIDEO_TYPE_ATTR, VIDEO_WRAPPER_CLASS, VideoElementError, VideoErrorOrigin, VideoPlayerHeadless, VideoPlayerHeadlessExtendedProps, VideoSourceType, useAutoFirstFrameCapture, useFirstFrameCapture, useVideoElement } from './components/VideoPlayer/index.js';
7
10
  export { BookmarkFilledIcon, BookmarkIcon, CloseIcon, CommentIcon, HeartFilledIcon, HeartIcon, IconProps, MoreIcon, MusicIcon, PauseIcon, PlayIcon, PlusIcon, ShareIcon, UserCheckIcon, UserPlusIcon, VerifiedIcon, VolumeIcon, VolumeMutedIcon } from './components/icons/index.js';
11
+ export { CLEAN_MODE_OVERLAY_CSS, CleanModeOverlayHeadless, CleanModeOverlayHeadlessProps, injectCleanModeOverlayCSS } from './components/CleanModeOverlay/index.js';
12
+ export { C as COMMENT_SHEET_CSS, a as CommentInput, b as CommentInputProps, c as CommentItemComponent, d as CommentItemProps, e as CommentList, f as CommentListProps, g as CommentSheet, h as CommentSheetContext, i as CommentSheetContextValue, j as CommentSheetHeadless, k as CommentSheetHeadlessProps, l as CommentSheetI18n, R as ReplyTarget, S as SheetHeader, m as SheetHeaderProps, u as useCommentSheetContext, n as useOptionalCommentSheetContext } from './CommentSheet.css-DuBy01rU.js';
8
13
  export { DEFAULT_BUFFER_SIZE, DEFAULT_EMPTY_TEXT, DEFAULT_END_REACHED_THRESHOLD, DEFAULT_END_TEXT, DEFAULT_LOADING_TEXT, SLIDER_CLASS, SLIDER_CONTAINER_CLASS, SLIDER_CONTAINER_SNAPPING_CLASS, SLIDER_CONTAINER_SWIPING_CLASS, SLOT_ACTIVE_ATTR as SLIDER_SLOT_ACTIVE_ATTR, SLIDER_SLOT_ACTIVE_CLASS, SLOT_ACTIVE_DATASET_KEY as SLIDER_SLOT_ACTIVE_DATASET_KEY, SLIDER_SLOT_ADJACENT_CLASS, SLIDER_SLOT_CLASS, SLOT_INDEX_ATTR as SLIDER_SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY as SLIDER_SLOT_INDEX_DATASET_KEY, SLIDER_SLOT_TRANSITIONING_CLASS, SlotPosition as SliderSlotPosition, UseSliderPositionOptions, UseSliderPositionReturn, VIRTUAL_SLIDER_CSS, VirtualSlider, VirtualSliderContext, VirtualSliderContextValue, VirtualSliderProps, getSlotIndexFromPosition as getSliderIndexFromPosition, useOptionalVirtualSliderContext, useSliderActiveIndex, useSliderIsSwiping, useSliderPosition, useVirtualSliderContext } from './components/VirtualSlider/index.js';
9
- export { SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, SlotPosition, UseVideoFeedPositionOptions, UseVideoFeedPositionReturn, VIDEO_FEED_CLASS_PREFIX, VIDEO_FEED_CSS, VideoFeedContext, VideoFeedContextValue, VideoFeedHeadless, VideoFeedHeadlessProps, getSlotIndexFromPosition, useOptionalVideoFeedContext, useVideoFeedContext, useVideoFeedPosition } from './components/VideoFeed/index.js';
10
- export { HeartInstance, LOADING_ATTR, LOADING_DATASET_KEY, LikeAnimationStyle, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, SLOT_CLASS, SLOT_ERROR_CLASS, SLOT_LOADING_CLASS, SLOT_PAUSED_CLASS, SLOT_PLAYING_CLASS, VIDEO_ID_ATTR, VIDEO_ID_DATASET_KEY, VIDEO_SLOT_CSS, VIDEO_SLOT_LIKE_ANIMATION_CSS, VideoSlotContext, VideoSlotContextValue, VideoSlotHeadless, VideoSlotHeadlessExtendedProps, VideoSlotLikeAnimation, VideoSlotLikeAnimationProps, VideoSlotLikeAnimationRef, VideoSlotOverlay, VideoSlotOverlayProps, VideoSlotOverlayRegionProps, VideoSlotPlayIndicator, VideoSlotPlayIndicatorProps, VideoSlotPoster, VideoSlotPosterProps, VideoSlotSkeleton, Z_INDEX, Z_INDEX_CSS_VARS, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from './components/VideoSlot/index.js';
11
- export { BUFFERING_STATE_CLASS, ENDED_CLASS, ERROR_CLASS, ERROR_STATE_CLASS, LOADING_CLASS, LOADING_STATE_ATTR, LOADING_STATE_CLASS, PAUSED_CLASS, PLAYBACK_STATE_ATTR, PLAYER_CLASS, PLAYING_CLASS, POSTER_CLASS, READY_CLASS, UseAutoFirstFrameCaptureConfig, UseFirstFrameCaptureConfig, UseFirstFrameCaptureReturn, UseVideoElementConfig, UseVideoElementReturn, VIDEO_CLASS, VIDEO_PLAYER_CSS, Z_INDEX as VIDEO_PLAYER_Z_INDEX, Z_INDEX_CSS_VARS as VIDEO_PLAYER_Z_INDEX_CSS_VARS, VIDEO_TYPE_ATTR, VIDEO_WRAPPER_CLASS, VideoElementError, VideoErrorOrigin, VideoPlayerHeadless, VideoPlayerHeadlessExtendedProps, VideoSourceType, useAutoFirstFrameCapture, useFirstFrameCapture, useVideoElement } from './components/VideoPlayer/index.js';
14
+ export { DEFAULT_SPEEDS, SPEED_PICKER_CSS, SpeedPickerHeadless, SpeedPickerHeadlessProps } from './components/SpeedPicker/index.js';
15
+ export { DETAIL_VIEW_CSS, DetailViewAuthor, DetailViewAuthorProps, DetailViewCaption, DetailViewCaptionProps, DetailViewContextValue, DetailViewGallery, DetailViewGalleryProps, DetailViewHeadless, DetailViewHeadlessProps, DetailViewMusic, DetailViewMusicProps, DetailViewStats, DetailViewStatsProps, useDetailViewContext } from './components/DetailView/index.js';
16
+ export { ErrorBoundary, ErrorBoundaryProps, ErrorMode } from './components/ErrorBoundary/index.js';
17
+ export { FEED_CLASS_PREFIX, FEED_CSS, FeedContext, FeedContextValue, FeedHeadless, FeedHeadlessProps, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, SlotPosition, UseFeedPositionOptions, UseFeedPositionReturn, UseFeedPositionOptions as UseVideoFeedPositionOptions, UseFeedPositionReturn as UseVideoFeedPositionReturn, FEED_CLASS_PREFIX as VIDEO_FEED_CLASS_PREFIX, FEED_CSS as VIDEO_FEED_CSS, FeedContext as VideoFeedContext, FeedContextValue as VideoFeedContextValue, FeedHeadless as VideoFeedHeadless, FeedHeadlessProps as VideoFeedHeadlessProps, getSlotIndexFromPosition, useFeedContext, useFeedPosition, useOptionalFeedContext, useOptionalFeedContext as useOptionalVideoFeedContext, useFeedContext as useVideoFeedContext, useFeedPosition as useVideoFeedPosition } from './components/Feed/index.js';
18
+ export { HeartInstance, LOADING_ATTR, LOADING_DATASET_KEY, LikeAnimationStyle, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, ReportedVideoOverlay, ReportedVideoOverlayProps, SLOT_CLASS, SLOT_ERROR_CLASS, SLOT_LOADING_CLASS, SLOT_PAUSED_CLASS, SLOT_PLAYING_CLASS, VIDEO_ID_ATTR, VIDEO_ID_DATASET_KEY, VIDEO_SLOT_CSS, VIDEO_SLOT_LIKE_ANIMATION_CSS, VideoSlotContext, VideoSlotContextValue, VideoSlotHeadless, VideoSlotHeadlessExtendedProps, VideoSlotLikeAnimation, VideoSlotLikeAnimationProps, VideoSlotLikeAnimationRef, VideoSlotOverlay, VideoSlotOverlayProps, VideoSlotOverlayRegionProps, VideoSlotPoster, VideoSlotPosterProps, VideoSlotSkeleton, Z_INDEX, Z_INDEX_CSS_VARS, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from './components/VideoSlot/index.js';
19
+ export { IMAGE_CAROUSEL_CSS, ImageCarouselHeadless, ImageCarouselProps } from './components/ImageCarousel/index.js';
12
20
  export { PROGRESS_BAR_CSS, ProgressBarHeadless, ProgressBarHeadlessExtendedProps, calculateProgress, formatTime } from './components/ProgressBar/index.js';
13
- export { ACTION_BAR_CSS, ActionBarBookmark, ActionBarComment, ActionBarHeadless, ActionBarHeadlessExtendedProps, ActionBarLike, ActionBarShare, ActionButton, ActionButtonExtendedProps, BookmarkButton, BookmarkButtonProps, CommentButton, CommentButtonProps, LikeButton, LikeButtonProps, ShareButton, ShareButtonProps } from './components/ActionBar/index.js';
14
- export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorAvatarProps, AuthorDescription, AuthorDescriptionProps, AuthorInfoContext, AuthorInfoContextValue, AuthorInfoHeadless, AuthorInfoHeadlessExtendedProps, AuthorInfoVariant, AuthorName, AuthorNameProps, AvatarSize, FollowButton, FollowButtonProps, FollowButtonSize, useAuthorInfoContext, useOptionalAuthorInfoContext } from './components/AuthorInfo/index.js';
21
+ export { PlaylistBarHeadless, PlaylistBarHeadlessProps, PlaylistCollectionHeadless, PlaylistCollectionHeadlessProps, PlaylistCollectionItem, PlaylistSheetHeadless, PlaylistSheetHeadlessProps } from './components/Playlist/index.js';
22
+ export { QUALITY_PICKER_CSS, QualityPickerHeadless, QualityPickerHeadlessProps } from './components/QualityPicker/index.js';
23
+ export { REPORT_SHEET_CSS, ReportSheetHeadless, ReportSheetHeadlessProps, ReportSheetState, injectReportSheetCSS } from './components/ReportSheet/index.js';
24
+ export { Skeleton, SkeletonAnimation, SkeletonAvatar, SkeletonProps, SkeletonText, SkeletonVideo } from './components/Skeleton/index.js';
15
25
  export { VIDEO_INFO_CSS, VideoAuthorName, VideoAuthorNameProps, VideoCaption, VideoCaptionProps, VideoHashtags, VideoHashtagsProps, VideoInfoContext, VideoInfoContextValue, VideoInfoHeadless, VideoInfoHeadlessExtendedProps, VideoLocation, VideoLocationProps, VideoMusic, VideoMusicProps, useOptionalVideoInfoContext, useVideoInfoContext } from './components/VideoInfo/index.js';
16
- export { n as COMMENT_SHEET_CSS, f as CommentInput, g as CommentInputProps, h as CommentItemComponent, i as CommentItemProps, d as CommentList, e as CommentListProps, C as CommentSheet, j as CommentSheetContext, l as CommentSheetContextValue, a as CommentSheetHeadless, b as CommentSheetHeadlessProps, m as CommentSheetI18n, R as ReplyTarget, S as SheetHeader, c as SheetHeaderProps, u as useCommentSheetContext, k as useOptionalCommentSheetContext } from './CommentSheet.css-BD6XbpU2.js';
26
+ export { V as VideoSlotPlayIndicator, a as VideoSlotPlayIndicatorProps } from './VideoSlotPlayIndicator-DPs8Xt5C.js';
17
27
  import 'react/jsx-runtime';
18
28
 
19
29
  /**
@@ -86,8 +96,26 @@ declare function areStylesInjected(): boolean;
86
96
  * - Works with any bundler (Next.js, Vite, Webpack)
87
97
  *
88
98
  * Design Tokens from: User-provided tokens (Urbanist font, light/dark mode)
99
+ *
100
+ * ## CSS Layers
101
+ *
102
+ * SDK styles use `@layer sv` for low specificity. This allows host apps to
103
+ * override styles easily WITHOUT using `!important`.
104
+ *
105
+ * Host app can override by:
106
+ * 1. Using any CSS without @layer (higher priority)
107
+ * 2. Overriding CSS Variables (recommended for theming)
108
+ * 3. Using `@layer host { }` declared AFTER `sv` layer
109
+ *
110
+ * @example
111
+ * ```css
112
+ * // Host app styles - no !important needed
113
+ * .my-custom-action-bar {
114
+ * gap: 20px; // Overrides SDK's gap easily
115
+ * }
116
+ * ```
89
117
  */
90
- declare const CSS_CONTENT = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n XHub-short UI Styles - Auto-injected\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n FONT LOADING\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@import url('https://fonts.googleapis.com/css2?family=Urbanist:wght@400;500;600;700&display=swap');\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS VARIABLES - Light Mode (Default)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n:root {\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n COLOR TOKENS - Light Mode\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-color-primary: #164c8e;\n --sv-color-primary-alpha: #164c8e5b;\n --sv-color-secondary: #9fc5e9;\n --sv-color-tertiary: #e9f8ff;\n --sv-color-quaternary: #164c8e5b;\n\n --sv-color-contrast-positive: #121212;\n --sv-color-contrast-negative: #ffffff;\n\n --sv-color-accent: #a2a2a2;\n --sv-color-accent-2: #6b7271;\n --sv-color-accent-stroke: #e5e6e6;\n\n --sv-color-error: #ff434e;\n --sv-color-success: #1da031;\n --sv-color-warning: #daa000;\n --sv-color-info: #29c8f0;\n\n /* Semantic aliases */\n --sv-color-background: var(--sv-color-contrast-negative);\n --sv-color-text: var(--sv-color-contrast-positive);\n --sv-color-text-secondary: var(--sv-color-accent-2);\n --sv-color-text-muted: var(--sv-color-accent);\n --sv-color-border: var(--sv-color-accent-stroke);\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n TYPOGRAPHY TOKENS - Mobile (Default)\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-font-family: 'Urbanist', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;\n --sv-font-family-display: 'SF Pro Display', 'Urbanist', system-ui, sans-serif;\n\n --sv-font-size-xxs: 10px;\n --sv-font-size-xs: 12px;\n --sv-font-size-sm: 13px;\n --sv-font-size-md: 14px;\n --sv-font-size-lg: 16px;\n --sv-font-size-xl: 20px;\n\n --sv-font-weight-regular: 400;\n --sv-font-weight-medium: 500;\n --sv-font-weight-semibold: 600;\n --sv-font-weight-bold: 700;\n\n --sv-line-height-tight: 1.2;\n --sv-line-height-normal: 1.4;\n --sv-line-height-relaxed: 1.6;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n SPACING TOKENS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-spacing-xxs: 2px;\n --sv-spacing-xs: 4px;\n --sv-spacing-sm: 8px;\n --sv-spacing-md: 12px;\n --sv-spacing-lg: 16px;\n --sv-spacing-xl: 24px;\n --sv-spacing-xxl: 32px;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n BORDER RADIUS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-radius-sm: 4px;\n --sv-radius-md: 8px;\n --sv-radius-lg: 12px;\n --sv-radius-xl: 16px;\n --sv-radius-full: 9999px;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n TRANSITIONS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-transition-fast: 150ms ease;\n --sv-transition-normal: 250ms ease;\n --sv-transition-slow: 350ms ease;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Z-INDEX LAYERS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-z-base: 1;\n --sv-z-video: 1;\n --sv-z-overlay: 10;\n --sv-z-controls: 20;\n --sv-z-modal: 100;\n --sv-z-toast: 1000;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n SHADOWS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);\n --sv-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);\n --sv-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.15);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS VARIABLES - Dark Mode\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* System preference */\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {\n --sv-color-primary: #a6cec7;\n --sv-color-primary-alpha: #164c8e5b;\n --sv-color-secondary: #143a0c;\n --sv-color-tertiary: #252825;\n --sv-color-quaternary: #164c8e5b;\n\n --sv-color-contrast-positive: #ffffff;\n --sv-color-contrast-negative: #121212;\n\n --sv-color-accent: #6b7271;\n --sv-color-accent-2: #d2dddb;\n --sv-color-accent-stroke: #373737;\n\n --sv-color-error: #b62a32;\n --sv-color-success: #20a634;\n --sv-color-warning: #c29823;\n --sv-color-info: #1fa0c0;\n\n /* Semantic aliases update automatically */\n --sv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);\n --sv-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.3);\n --sv-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.4);\n }\n}\n\n/* Explicit dark mode (override) */\n[data-theme=\"dark\"],\n.dark {\n --sv-color-primary: #a6cec7;\n --sv-color-primary-alpha: #164c8e5b;\n --sv-color-secondary: #143a0c;\n --sv-color-tertiary: #252825;\n --sv-color-quaternary: #164c8e5b;\n\n --sv-color-contrast-positive: #ffffff;\n --sv-color-contrast-negative: #121212;\n\n --sv-color-accent: #6b7271;\n --sv-color-accent-2: #d2dddb;\n --sv-color-accent-stroke: #373737;\n\n --sv-color-error: #b62a32;\n --sv-color-success: #20a634;\n --sv-color-warning: #c29823;\n --sv-color-info: #1fa0c0;\n\n --sv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);\n --sv-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.3);\n --sv-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.4);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n TABLET BREAKPOINT - Typography scaling\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@media (min-width: 768px) {\n :root {\n --sv-font-size-xxs: 11px;\n --sv-font-size-xs: 13px;\n --sv-font-size-sm: 14px;\n --sv-font-size-md: 16px;\n --sv-font-size-lg: 18px;\n --sv-font-size-xl: 24px;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n BASE STYLES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-root {\n font-family: var(--sv-font-family);\n font-size: var(--sv-font-size-md);\n font-weight: var(--sv-font-weight-regular);\n line-height: var(--sv-line-height-normal);\n color: var(--sv-color-text);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n FEED CONTAINER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-feed {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: var(--sv-color-contrast-negative);\n touch-action: pan-y;\n -webkit-overflow-scrolling: touch;\n}\n\n.sv-feed::-webkit-scrollbar {\n display: none;\n}\n\n.sv-feed {\n -ms-overflow-style: none;\n scrollbar-width: none;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n VIDEO SLOT\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-slot {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sv-color-contrast-negative);\n will-change: transform;\n}\n\n.sv-slot--active {\n z-index: var(--sv-z-video);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n VIDEO PLAYER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-player {\n position: relative;\n width: 100%;\n height: 100%;\n background: var(--sv-color-contrast-negative);\n}\n\n.sv-player__video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n background: var(--sv-color-contrast-negative);\n}\n\n.sv-player__poster {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 1;\n transition: opacity var(--sv-transition-normal);\n}\n\n.sv-player__poster--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n.sv-player__overlay {\n position: absolute;\n inset: 0;\n background: linear-gradient(\n to bottom,\n transparent 0%,\n transparent 50%,\n rgba(0, 0, 0, 0.3) 100%\n );\n pointer-events: none;\n z-index: var(--sv-z-overlay);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n PROGRESS BAR\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-progress {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 3px;\n background: rgba(255, 255, 255, 0.2);\n z-index: var(--sv-z-controls);\n}\n\n.sv-progress__bar {\n height: 100%;\n background: var(--sv-color-contrast-positive);\n transition: width 100ms linear;\n will-change: width;\n}\n\n.sv-progress__bar--buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.3);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n INTERACTION BAR (Right side actions)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-actions {\n position: absolute;\n right: var(--sv-spacing-md);\n bottom: 120px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--sv-spacing-xl);\n z-index: var(--sv-z-controls);\n}\n\n.sv-action-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--sv-spacing-xs);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--sv-color-contrast-positive);\n transition: transform var(--sv-transition-fast);\n -webkit-tap-highlight-color: transparent;\n}\n\n.sv-action-btn:active {\n transform: scale(0.9);\n}\n\n.sv-action-btn__icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.3);\n border-radius: var(--sv-radius-full);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n\n.sv-action-btn__icon svg {\n width: 24px;\n height: 24px;\n fill: currentColor;\n}\n\n.sv-action-btn__count {\n font-size: var(--sv-font-size-xs);\n font-weight: var(--sv-font-weight-semibold);\n color: var(--sv-color-contrast-positive);\n}\n\n/* Like button states */\n.sv-action-btn--liked .sv-action-btn__icon {\n color: var(--sv-color-error);\n}\n\n.sv-action-btn--liked .sv-action-btn__icon svg {\n animation: sv-like-pop 0.3s ease;\n}\n\n@keyframes sv-like-pop {\n 0% { transform: scale(1); }\n 50% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n AUTHOR INFO (Bottom left)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-author {\n position: absolute;\n left: var(--sv-spacing-md);\n bottom: 80px;\n display: flex;\n flex-direction: column;\n gap: var(--sv-spacing-md);\n max-width: calc(100% - 80px);\n z-index: var(--sv-z-controls);\n}\n\n.sv-author__row {\n display: flex;\n align-items: center;\n gap: var(--sv-spacing-md);\n}\n\n.sv-author__avatar {\n width: 48px;\n height: 48px;\n border-radius: var(--sv-radius-full);\n border: 2px solid var(--sv-color-contrast-positive);\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.sv-author__info {\n display: flex;\n flex-direction: column;\n gap: var(--sv-spacing-xxs);\n min-width: 0;\n}\n\n.sv-author__name {\n font-size: var(--sv-font-size-lg);\n font-weight: var(--sv-font-weight-semibold);\n color: var(--sv-color-contrast-positive);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sv-author__handle {\n font-size: var(--sv-font-size-sm);\n color: rgba(255, 255, 255, 0.8);\n}\n\n.sv-author__description {\n font-size: var(--sv-font-size-sm);\n color: var(--sv-color-contrast-positive);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: var(--sv-line-height-relaxed);\n}\n\n/* Follow button */\n.sv-follow-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: var(--sv-spacing-xs) var(--sv-spacing-md);\n font-size: var(--sv-font-size-sm);\n font-weight: var(--sv-font-weight-semibold);\n font-family: var(--sv-font-family);\n color: var(--sv-color-contrast-negative);\n background: var(--sv-color-primary);\n border: none;\n border-radius: var(--sv-radius-sm);\n cursor: pointer;\n transition: all var(--sv-transition-fast);\n -webkit-tap-highlight-color: transparent;\n}\n\n.sv-follow-btn:active {\n transform: scale(0.95);\n}\n\n.sv-follow-btn--following {\n background: transparent;\n color: var(--sv-color-contrast-positive);\n border: 1px solid var(--sv-color-contrast-positive);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SPINNER / LOADING\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-spinner {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.sv-spinner__circle {\n width: 32px;\n height: 32px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: var(--sv-color-contrast-positive);\n border-radius: var(--sv-radius-full);\n animation: sv-spin 0.8s linear infinite;\n}\n\n.sv-spinner--sm .sv-spinner__circle {\n width: 20px;\n height: 20px;\n border-width: 2px;\n}\n\n.sv-spinner--lg .sv-spinner__circle {\n width: 48px;\n height: 48px;\n border-width: 4px;\n}\n\n@keyframes sv-spin {\n to { transform: rotate(360deg); }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n MUSIC INFO (Bottom - optional)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-music {\n position: absolute;\n left: var(--sv-spacing-md);\n bottom: var(--sv-spacing-lg);\n display: flex;\n align-items: center;\n gap: var(--sv-spacing-sm);\n max-width: calc(100% - 80px);\n z-index: var(--sv-z-controls);\n}\n\n.sv-music__icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n}\n\n.sv-music__text {\n font-size: var(--sv-font-size-sm);\n color: var(--sv-color-contrast-positive);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sv-music__marquee {\n animation: sv-marquee 10s linear infinite;\n}\n\n@keyframes sv-marquee {\n 0% { transform: translateX(0); }\n 100% { transform: translateX(-50%); }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n UTILITIES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.sv-tap-highlight-none {\n -webkit-tap-highlight-color: transparent;\n}\n\n/* Prevent text selection during gestures */\n.sv-no-select {\n -webkit-user-select: none;\n user-select: none;\n}\n\n/* Hardware acceleration hint */\n.sv-gpu {\n transform: translateZ(0);\n will-change: transform;\n}\n";
118
+ declare const CSS_CONTENT = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n XHub-short UI Styles - Auto-injected\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS LAYER DECLARATION\n \n Declare the 'sv' layer first. All SDK component styles go into this layer.\n Host app styles WITHOUT @layer automatically have HIGHER priority.\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@layer sv;\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n FONT LOADING (outside layer - needs to be global)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@import url('https://fonts.googleapis.com/css2?family=Urbanist:wght@400;500;600;700&display=swap');\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS VARIABLES - Light Mode (Default)\n Outside layer so host app can easily override variables\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n:root {\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n COLOR TOKENS - Light Mode\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-color-primary: #164c8e;\n --sv-color-primary-alpha: #164c8e5b;\n --sv-color-secondary: #9fc5e9;\n --sv-color-tertiary: #e9f8ff;\n --sv-color-quaternary: #164c8e5b;\n\n --sv-color-contrast-positive: #121212;\n --sv-color-contrast-negative: #ffffff;\n\n --sv-color-accent: #a2a2a2;\n --sv-color-accent-2: #6b7271;\n --sv-color-accent-stroke: #e5e6e6;\n\n --sv-color-error: #ff434e;\n --sv-color-success: #1da031;\n --sv-color-warning: #daa000;\n --sv-color-info: #29c8f0;\n\n /* Semantic aliases */\n --sv-color-background: var(--sv-color-contrast-negative);\n --sv-color-text: var(--sv-color-contrast-positive);\n --sv-color-text-secondary: var(--sv-color-accent-2);\n --sv-color-text-muted: var(--sv-color-accent);\n --sv-color-border: var(--sv-color-accent-stroke);\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n TYPOGRAPHY TOKENS - Mobile (Default)\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-font-family: 'Urbanist', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;\n --sv-font-family-display: 'SF Pro Display', 'Urbanist', system-ui, sans-serif;\n\n --sv-font-size-xxs: 10px;\n --sv-font-size-xs: 12px;\n --sv-font-size-sm: 13px;\n --sv-font-size-md: 14px;\n --sv-font-size-lg: 16px;\n --sv-font-size-xl: 20px;\n\n --sv-font-weight-regular: 400;\n --sv-font-weight-medium: 500;\n --sv-font-weight-semibold: 600;\n --sv-font-weight-bold: 700;\n\n --sv-line-height-tight: 1.2;\n --sv-line-height-normal: 1.4;\n --sv-line-height-relaxed: 1.6;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n SPACING TOKENS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-spacing-xxs: 2px;\n --sv-spacing-xs: 4px;\n --sv-spacing-sm: 8px;\n --sv-spacing-md: 12px;\n --sv-spacing-lg: 16px;\n --sv-spacing-xl: 24px;\n --sv-spacing-xxl: 32px;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n BORDER RADIUS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-radius-sm: 4px;\n --sv-radius-md: 8px;\n --sv-radius-lg: 12px;\n --sv-radius-xl: 16px;\n --sv-radius-full: 9999px;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n TRANSITIONS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-transition-fast: 150ms ease;\n --sv-transition-normal: 250ms ease;\n --sv-transition-slow: 350ms ease;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Z-INDEX LAYERS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-z-base: 1;\n --sv-z-video: 1;\n --sv-z-overlay: 10;\n --sv-z-controls: 20;\n --sv-z-modal: 100;\n --sv-z-toast: 1000;\n\n /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n SHADOWS\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n --sv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);\n --sv-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);\n --sv-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.15);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS VARIABLES - Dark Mode\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* System preference */\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {\n --sv-color-primary: #a6cec7;\n --sv-color-primary-alpha: #164c8e5b;\n --sv-color-secondary: #143a0c;\n --sv-color-tertiary: #252825;\n --sv-color-quaternary: #164c8e5b;\n\n --sv-color-contrast-positive: #ffffff;\n --sv-color-contrast-negative: #121212;\n\n --sv-color-accent: #6b7271;\n --sv-color-accent-2: #d2dddb;\n --sv-color-accent-stroke: #373737;\n\n --sv-color-error: #b62a32;\n --sv-color-success: #20a634;\n --sv-color-warning: #c29823;\n --sv-color-info: #1fa0c0;\n\n /* Semantic aliases update automatically */\n --sv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);\n --sv-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.3);\n --sv-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.4);\n }\n}\n\n/* Explicit dark mode (override) */\n[data-theme=\"dark\"],\n.dark {\n --sv-color-primary: #a6cec7;\n --sv-color-primary-alpha: #164c8e5b;\n --sv-color-secondary: #143a0c;\n --sv-color-tertiary: #252825;\n --sv-color-quaternary: #164c8e5b;\n\n --sv-color-contrast-positive: #ffffff;\n --sv-color-contrast-negative: #121212;\n\n --sv-color-accent: #6b7271;\n --sv-color-accent-2: #d2dddb;\n --sv-color-accent-stroke: #373737;\n\n --sv-color-error: #b62a32;\n --sv-color-success: #20a634;\n --sv-color-warning: #c29823;\n --sv-color-info: #1fa0c0;\n\n --sv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);\n --sv-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.3);\n --sv-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.4);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n TABLET BREAKPOINT - Typography scaling\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@media (min-width: 768px) {\n :root {\n --sv-font-size-xxs: 11px;\n --sv-font-size-xs: 13px;\n --sv-font-size-sm: 14px;\n --sv-font-size-md: 16px;\n --sv-font-size-lg: 18px;\n --sv-font-size-xl: 24px;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n BASE STYLES - Inside @layer sv for easy host app overrides\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@layer sv {\n\n.sv-root {\n font-family: var(--sv-font-family);\n font-size: var(--sv-font-size-md);\n font-weight: var(--sv-font-weight-regular);\n line-height: var(--sv-line-height-normal);\n color: var(--sv-color-text);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n FEED CONTAINER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-feed {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: var(--sv-color-contrast-negative);\n touch-action: pan-y;\n -webkit-overflow-scrolling: touch;\n}\n\n.sv-feed::-webkit-scrollbar {\n display: none;\n}\n\n.sv-feed {\n -ms-overflow-style: none;\n scrollbar-width: none;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n VIDEO SLOT\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-slot {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sv-color-contrast-negative);\n will-change: transform;\n}\n\n.sv-slot--active {\n z-index: var(--sv-z-video);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n VIDEO PLAYER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-player {\n position: relative;\n width: 100%;\n height: 100%;\n background: var(--sv-color-contrast-negative);\n}\n\n.sv-player__video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n background: var(--sv-color-contrast-negative);\n}\n\n.sv-player__poster {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 1;\n transition: opacity var(--sv-transition-normal);\n}\n\n.sv-player__poster--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n.sv-player__overlay {\n position: absolute;\n inset: 0;\n background: linear-gradient(\n to bottom,\n transparent 0%,\n transparent 50%,\n rgba(0, 0, 0, 0.3) 100%\n );\n pointer-events: none;\n z-index: var(--sv-z-overlay);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n PROGRESS BAR\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-progress {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 3px;\n background: rgba(255, 255, 255, 0.2);\n z-index: var(--sv-z-controls);\n}\n\n.sv-progress__bar {\n height: 100%;\n background: var(--sv-color-contrast-positive);\n transition: width 100ms linear;\n will-change: width;\n}\n\n.sv-progress__bar--buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.3);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n INTERACTION BAR (Right side actions)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-actions {\n position: absolute;\n right: var(--sv-spacing-md);\n bottom: 120px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--sv-spacing-xl);\n z-index: var(--sv-z-controls);\n}\n\n.sv-action-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--sv-spacing-xs);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--sv-color-contrast-positive);\n transition: transform var(--sv-transition-fast);\n -webkit-tap-highlight-color: transparent;\n}\n\n.sv-action-btn:active {\n transform: scale(0.9);\n}\n\n.sv-action-btn__icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.3);\n border-radius: var(--sv-radius-full);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n\n.sv-action-btn__icon svg {\n width: 24px;\n height: 24px;\n fill: currentColor;\n}\n\n.sv-action-btn__count {\n font-size: var(--sv-font-size-xs);\n font-weight: var(--sv-font-weight-semibold);\n color: var(--sv-color-contrast-positive);\n}\n\n/* Like button states */\n.sv-action-btn--liked .sv-action-btn__icon {\n color: var(--sv-color-error);\n}\n\n.sv-action-btn--liked .sv-action-btn__icon svg {\n animation: sv-like-pop 0.3s ease;\n}\n\n@keyframes sv-like-pop {\n 0% { transform: scale(1); }\n 50% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n AUTHOR INFO (Bottom left)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-author {\n position: absolute;\n left: var(--sv-spacing-md);\n bottom: 80px;\n display: flex;\n flex-direction: column;\n gap: var(--sv-spacing-md);\n max-width: calc(100% - 80px);\n z-index: var(--sv-z-controls);\n}\n\n.sv-author__row {\n display: flex;\n align-items: center;\n gap: var(--sv-spacing-md);\n}\n\n.sv-author__avatar {\n width: 48px;\n height: 48px;\n border-radius: var(--sv-radius-full);\n border: 2px solid var(--sv-color-contrast-positive);\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.sv-author__info {\n display: flex;\n flex-direction: column;\n gap: var(--sv-spacing-xxs);\n min-width: 0;\n}\n\n.sv-author__name {\n font-size: var(--sv-font-size-lg);\n font-weight: var(--sv-font-weight-semibold);\n color: var(--sv-color-contrast-positive);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sv-author__handle {\n font-size: var(--sv-font-size-sm);\n color: rgba(255, 255, 255, 0.8);\n}\n\n.sv-author__description {\n font-size: var(--sv-font-size-sm);\n color: var(--sv-color-contrast-positive);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: var(--sv-line-height-relaxed);\n}\n\n/* Follow button */\n.sv-follow-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: var(--sv-spacing-xs) var(--sv-spacing-md);\n font-size: var(--sv-font-size-sm);\n font-weight: var(--sv-font-weight-semibold);\n font-family: var(--sv-font-family);\n color: var(--sv-color-contrast-negative);\n background: var(--sv-color-primary);\n border: none;\n border-radius: var(--sv-radius-sm);\n cursor: pointer;\n transition: all var(--sv-transition-fast);\n -webkit-tap-highlight-color: transparent;\n}\n\n.sv-follow-btn:active {\n transform: scale(0.95);\n}\n\n.sv-follow-btn--following {\n background: transparent;\n color: var(--sv-color-contrast-positive);\n border: 1px solid var(--sv-color-contrast-positive);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SPINNER / LOADING\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-spinner {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.sv-spinner__circle {\n width: 32px;\n height: 32px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: var(--sv-color-contrast-positive);\n border-radius: var(--sv-radius-full);\n animation: sv-spin 0.8s linear infinite;\n}\n\n.sv-spinner--sm .sv-spinner__circle {\n width: 20px;\n height: 20px;\n border-width: 2px;\n}\n\n.sv-spinner--lg .sv-spinner__circle {\n width: 48px;\n height: 48px;\n border-width: 4px;\n}\n\n@keyframes sv-spin {\n to { transform: rotate(360deg); }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n MUSIC INFO (Bottom - optional)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-music {\n position: absolute;\n left: var(--sv-spacing-md);\n bottom: var(--sv-spacing-lg);\n display: flex;\n align-items: center;\n gap: var(--sv-spacing-sm);\n max-width: calc(100% - 80px);\n z-index: var(--sv-z-controls);\n}\n\n.sv-music__icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n}\n\n.sv-music__text {\n font-size: var(--sv-font-size-sm);\n color: var(--sv-color-contrast-positive);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sv-music__marquee {\n animation: sv-marquee 10s linear infinite;\n}\n\n@keyframes sv-marquee {\n 0% { transform: translateX(0); }\n 100% { transform: translateX(-50%); }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n UTILITIES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.sv-tap-highlight-none {\n -webkit-tap-highlight-color: transparent;\n}\n\n/* Prevent text selection during gestures */\n.sv-no-select {\n -webkit-user-select: none;\n user-select: none;\n}\n\n/* Hardware acceleration hint */\n.sv-gpu {\n transform: translateZ(0);\n will-change: transform;\n}\n\n} /* End @layer sv */\n";
91
119
 
92
120
  /**
93
121
  * Styles Module
@@ -356,8 +384,12 @@ interface UseDoubleTapConfig {
356
384
  onSingleTap?: () => void;
357
385
  /** Callback for double tap with position */
358
386
  onDoubleTap?: (position: TapPosition) => void;
387
+ /** Callback for long press (hold > longPressDelay without moving) */
388
+ onLongPress?: (position: TapPosition) => void;
359
389
  /** Delay in ms to detect double tap (default: 300) */
360
390
  doubleTapDelay?: number;
391
+ /** Delay in ms to detect long press (default: 500) */
392
+ longPressDelay?: number;
361
393
  /** Whether the hook is disabled */
362
394
  disabled?: boolean;
363
395
  /**
@@ -398,7 +430,7 @@ interface UseDoubleTapReturn {
398
430
  * Returns tap position as percentage (0-100) relative to container.
399
431
  * Falls back to center (50, 50) if container ref is null.
400
432
  */
401
- declare function useDoubleTap({ containerRef, onSingleTap, onDoubleTap, doubleTapDelay, disabled, movementThreshold, }: UseDoubleTapConfig): UseDoubleTapReturn;
433
+ declare function useDoubleTap({ containerRef, onSingleTap, onDoubleTap, onLongPress, doubleTapDelay, longPressDelay, disabled, movementThreshold, }: UseDoubleTapConfig): UseDoubleTapReturn;
402
434
 
403
435
  /**
404
436
  * CustomLayout - Fully Composable Layout
@@ -694,6 +726,21 @@ declare const Layouts: {
694
726
  * - Persistent by default: CSS stays in DOM after injection (no cleanup overhead)
695
727
  * - SSR-safe: Checks for document existence
696
728
  * - Hydration-aware: Checks for existing styles from SSR
729
+ * - **CSS Layers**: All component CSS is wrapped in `@layer sv` for easy host overrides
730
+ *
731
+ * ## CSS Layers for Host App Overrides
732
+ *
733
+ * All SDK component styles are injected inside `@layer sv`. This means:
734
+ * - Host app CSS without @layer has HIGHER priority
735
+ * - No need for `!important` to override SDK styles
736
+ *
737
+ * @example
738
+ * ```css
739
+ * // Host app can easily override without !important
740
+ * .my-custom-button {
741
+ * background: blue; // Overrides SDK styles easily
742
+ * }
743
+ * ```
697
744
  *
698
745
  * ## Why No Auto-Cleanup?
699
746
  *
@@ -723,6 +770,21 @@ declare const Layouts: {
723
770
  * }
724
771
  * ```
725
772
  */
773
+ /**
774
+ * Options for CSS injection
775
+ */
776
+ interface InjectCSSOptions {
777
+ /**
778
+ * Whether to wrap CSS in @layer sv.
779
+ *
780
+ * - `true` (default): CSS wrapped in @layer sv, host app can override easily
781
+ * - `false`: CSS injected without layer, useful for critical components
782
+ * that need to resist global resets like `* { margin: 0; padding: 0; }`
783
+ *
784
+ * @default true
785
+ */
786
+ layered?: boolean;
787
+ }
726
788
  /**
727
789
  * Inject CSS for a specific component.
728
790
  *
@@ -731,9 +793,10 @@ declare const Layouts: {
731
793
  *
732
794
  * @param componentId - Unique identifier for the component (e.g., 'video-player')
733
795
  * @param css - CSS string to inject
796
+ * @param options - Injection options
734
797
  * @returns Empty cleanup function (CSS persists intentionally)
735
798
  */
736
- declare function injectComponentCSS(componentId: string, css: string): () => void;
799
+ declare function injectComponentCSS(componentId: string, css: string, options?: InjectCSSOptions): () => void;
737
800
  /**
738
801
  * Remove CSS for a specific component.
739
802
  * Mainly used for testing cleanup.