@xhub-short/ui 1.0.0-beta.21 → 1.0.0-beta.23

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.
@@ -111,7 +111,7 @@ function AuthorDescription({
111
111
  }
112
112
 
113
113
  // src/components/AuthorInfo/AuthorInfo.css.ts
114
- var AUTHOR_INFO_CSS = `.sv-author-info{display:flex;align-items:center;gap:var(--sv-author-gap,12px);width:100%}.sv-author-info--vertical{flex-direction:column;align-items:flex-start}.sv-author-info--horizontal{flex-direction:row;align-items:center}.sv-author-info--compact{gap:var(--sv-author-gap-compact,8px)}.sv-author-info__avatar{position:relative;flex-shrink:0;width:var(--sv-author-avatar-size,48px);height:var(--sv-author-avatar-size,48px);border-radius:50%;overflow:hidden;background:var(--sv-author-avatar-bg,rgba(255,255,255,.1));cursor:pointer;transition:transform .15s ease}.sv-author-info__avatar:hover{transform:scale(1.05)}.sv-author-info__avatar:active{transform:scale(.98)}.sv-author-info__avatar-img{width:100%;height:100%;object-fit:cover;border-radius:50%}.sv-author-info__avatar-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--sv-author-avatar-placeholder-bg,linear-gradient(135deg,#667eea 0%,#764ba2 100%));color:var(--sv-author-avatar-placeholder-color,#fff);font-size:calc(var(--sv-author-avatar-size,48px)* .4);font-weight:600;text-transform:uppercase}.sv-author-info__avatar-placeholder svg{width:60%;height:60%;opacity:.9}.sv-author-info__avatar--small{width:var(--sv-author-avatar-size-small,32px);height:var(--sv-author-avatar-size-small,32px)}.sv-author-info__avatar--large{width:var(--sv-author-avatar-size-large,64px);height:var(--sv-author-avatar-size-large,64px)}.sv-author-info__verified-badge{position:absolute;bottom:-2px;right:-2px;width:calc(var(--sv-author-avatar-size,48px)* .35);height:calc(var(--sv-author-avatar-size,48px)* .35);min-width:14px;min-height:14px;border-radius:50%;background:var(--sv-verified-badge-bg,#1DA1F2);display:flex;align-items:center;justify-content:center;border:2px solid var(--sv-verified-badge-border,#000)}.sv-author-info__verified-badge svg{width:60%;height:60%;color:var(--sv-verified-badge-color,#fff)}.sv-author-info__content{display:flex;flex-direction:column;gap:var(--sv-author-content-gap,2px);flex:1;min-width:0}.sv-author-info__name{display:flex;align-items:center;gap:var(--sv-author-name-gap,4px);font-size:var(--sv-author-name-size,16px);font-weight:var(--sv-author-name-weight,600);color:var(--sv-author-name-color,#fff);cursor:pointer;transition:opacity .15s ease}.sv-author-info__name:hover{opacity:.8}.sv-author-info__name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sv-author-info__name--with-at::before{content:'@';opacity:.8}.sv-author-info__name-verified{flex-shrink:0;width:var(--sv-author-name-verified-size,14px);height:var(--sv-author-name-verified-size,14px);color:var(--sv-verified-badge-bg,#1DA1F2)}.sv-author-info__description{font-size:var(--sv-author-desc-size,13px);color:var(--sv-author-desc-color,rgba(255,255,255,.7));line-height:var(--sv-author-desc-line-height,1.4);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:var(--sv-author-desc-lines,2);-webkit-box-orient:vertical}.sv-author-info__description--single-line{-webkit-line-clamp:1;white-space:nowrap;display:block}.sv-author-info__follow-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sv-follow-btn-gap,6px);padding:var(--sv-follow-btn-padding,8px 16px);min-width:var(--sv-follow-btn-min-width,88px);border:0;border-radius:var(--sv-follow-btn-radius,4px);font-size:var(--sv-follow-btn-size,14px);font-weight:var(--sv-follow-btn-weight,600);cursor:pointer;transition:all .2s ease;outline:none;user-select:none;-webkit-tap-highlight-color:transparent}.sv-author-info__follow-btn--default{background:var(--sv-follow-btn-bg,#fe2c55);color:var(--sv-follow-btn-color,#fff)}.sv-author-info__follow-btn--default:hover:not(:disabled){background:var(--sv-follow-btn-bg-hover,#f46);transform:scale(1.02)}.sv-author-info__follow-btn--default:active:not(:disabled){transform:scale(.98)}.sv-author-info__follow-btn--following{background:var(--sv-follow-btn-following-bg,transparent);color:var(--sv-follow-btn-following-color,rgba(255,255,255,.9));border:1px solid var(--sv-follow-btn-following-border,rgba(255,255,255,.3))}.sv-author-info__follow-btn--following:hover:not(:disabled){background:var(--sv-follow-btn-following-bg-hover,rgba(255,255,255,.1));border-color:var(--sv-follow-btn-following-border-hover,rgba(255,255,255,.5))}.sv-author-info__follow-btn--pending{opacity:.6;pointer-events:none;cursor:wait}.sv-author-info__follow-btn:disabled{opacity:.5;cursor:not-allowed}.sv-author-info__follow-btn-icon{width:var(--sv-follow-btn-icon-size,16px);height:var(--sv-follow-btn-icon-size,16px);flex-shrink:0}.sv-author-info__follow-btn-spinner{width:var(--sv-follow-btn-icon-size,16px);height:var(--sv-follow-btn-icon-size,16px);border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:sv-author-info-spin .6s linear infinite}@keyframes sv-author-info-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.sv-author-info__follow-btn--small{padding:var(--sv-follow-btn-padding-small,6px 12px);font-size:var(--sv-follow-btn-size-small,12px);min-width:var(--sv-follow-btn-min-width-small,72px)}.sv-author-info__follow-btn--large{padding:var(--sv-follow-btn-padding-large,10px 20px);font-size:var(--sv-follow-btn-size-large,16px);min-width:var(--sv-follow-btn-min-width-large,100px)}.sv-author-info__follow-btn--icon-only{min-width:unset;padding:var(--sv-follow-btn-icon-padding,8px);border-radius:50%}.sv-author-info--inline{justify-content:space-between}.sv-author-info--inline .sv-author-info__content{flex:1}.sv-author-info--stacked{flex-direction:column;align-items:center;text-align:center}.sv-author-info--stacked .sv-author-info__content{align-items:center}.sv-author-info--overlay{text-shadow:var(--sv-author-overlay-shadow,0 1px 2px rgba(0,0,0,.5))}.sv-author-info--overlay .sv-author-info__avatar{border:2px solid var(--sv-author-overlay-avatar-border,rgba(255,255,255,.5))}.sv-author-info--avatar-badge{position:relative;display:flex;flex-direction:column;align-items:center;width:auto;gap:0}.sv-author-info--avatar-badge .sv-author-info__avatar{width:var(--sv-avatar-badge-size,48px);height:var(--sv-avatar-badge-size,48px);border:2px solid var(--sv-avatar-badge-border,#fff)}.sv-author-info--avatar-badge .sv-author-info__follow-btn{position:absolute;bottom:var(--sv-avatar-badge-btn-bottom,-10px);left:50%;transform:translateX(-50%);min-width:unset;width:var(--sv-avatar-badge-btn-size,24px);height:var(--sv-avatar-badge-btn-size,24px);padding:0;border-radius:50%;background:var(--sv-color-primary,#fe2c55);border:2px solid var(--sv-bg-primary,#000);z-index:1}.sv-author-info--avatar-badge .sv-author-info__follow-btn:hover:not(:disabled){transform:translateX(-50%)scale(1.1)}.sv-author-info--avatar-badge .sv-author-info__follow-btn:active:not(:disabled){transform:translateX(-50%)scale(.95)}.sv-author-info--avatar-badge .sv-author-info__follow-btn-icon{width:var(--sv-avatar-badge-icon-size,14px);height:var(--sv-avatar-badge-icon-size,14px)}.sv-author-info--avatar-badge .sv-author-info__follow-btn--following{display:none}.sv-author-info--avatar-badge .sv-author-info__content{display:none}.sv-author-info--avatar-badge{margin-bottom:var(--sv-avatar-badge-margin,16px)}`;
114
+ var AUTHOR_INFO_CSS = `.sv-author-info{display:flex;align-items:center;gap:var(--sv-author-gap,12px);width:100%}.sv-author-info--vertical{flex-direction:column;align-items:flex-start}.sv-author-info--horizontal{flex-direction:row;align-items:center}.sv-author-info--compact{gap:var(--sv-author-gap-compact,8px)}.sv-author-info__avatar{position:relative;flex-shrink:0;width:var(--sv-author-avatar-size,48px);height:var(--sv-author-avatar-size,48px);border-radius:50%;overflow:hidden;background:var(--sv-author-avatar-bg,rgba(255,255,255,.1));cursor:pointer;transition:transform .15s ease}.sv-author-info__avatar:hover{transform:scale(1.05)}.sv-author-info__avatar:active{transform:scale(.98)}.sv-author-info__avatar-img{width:100%;height:100%;object-fit:cover;border-radius:50%}.sv-author-info__avatar-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--sv-author-avatar-placeholder-bg,linear-gradient(135deg,#667eea 0%,#764ba2 100%));color:var(--sv-author-avatar-placeholder-color,#fff);font-size:calc(var(--sv-author-avatar-size,48px)* .4);font-weight:600;text-transform:uppercase}.sv-author-info__avatar-placeholder svg{width:60%;height:60%;opacity:.9}.sv-author-info__avatar--small{width:var(--sv-author-avatar-size-small,32px);height:var(--sv-author-avatar-size-small,32px)}.sv-author-info__avatar--large{width:var(--sv-author-avatar-size-large,64px);height:var(--sv-author-avatar-size-large,64px)}.sv-author-info__verified-badge{position:absolute;bottom:-2px;right:-2px;width:calc(var(--sv-author-avatar-size,48px)* .35);height:calc(var(--sv-author-avatar-size,48px)* .35);min-width:14px;min-height:14px;border-radius:50%;background:var(--sv-verified-badge-bg,#1DA1F2);display:flex;align-items:center;justify-content:center;border:2px solid var(--sv-verified-badge-border,#000)}.sv-author-info__verified-badge svg{width:60%;height:60%;color:var(--sv-verified-badge-color,#fff)}.sv-author-info__content{display:flex;flex-direction:column;gap:var(--sv-author-content-gap,2px);flex:1;min-width:0}.sv-author-info__name{display:flex;align-items:center;gap:var(--sv-author-name-gap,4px);font-size:var(--sv-author-name-size,16px);font-weight:var(--sv-author-name-weight,600);color:var(--sv-author-name-color,#fff);cursor:pointer;transition:opacity .15s ease}.sv-author-info__name:hover{opacity:.8}.sv-author-info__name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sv-author-info__name--with-at::before{content:'@';opacity:.8}.sv-author-info__name-verified{flex-shrink:0;width:var(--sv-author-name-verified-size,14px);height:var(--sv-author-name-verified-size,14px);color:var(--sv-verified-badge-bg,#1DA1F2)}.sv-author-info__description{font-size:var(--sv-author-desc-size,13px);color:var(--sv-author-desc-color,rgba(255,255,255,.7));line-height:var(--sv-author-desc-line-height,1.4);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:var(--sv-author-desc-lines,2);-webkit-box-orient:vertical}.sv-author-info__description--single-line{-webkit-line-clamp:1;white-space:nowrap;display:block}.sv-author-info__follow-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sv-follow-btn-gap,6px);padding:var(--sv-follow-btn-padding,8px 16px);min-width:var(--sv-follow-btn-min-width,88px);border:0;border-radius:var(--sv-follow-btn-radius,4px);font-size:var(--sv-follow-btn-size,14px);font-weight:var(--sv-follow-btn-weight,600);cursor:pointer;transition:all .2s ease;outline:none;user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent}.sv-author-info__follow-btn--default{background:var(--sv-follow-btn-bg,#fe2c55);color:var(--sv-follow-btn-color,#fff)}.sv-author-info__follow-btn--default:hover:not(:disabled){background:var(--sv-follow-btn-bg-hover,#f46);transform:scale(1.02)}.sv-author-info__follow-btn--default:active:not(:disabled){transform:scale(.98)}.sv-author-info__follow-btn--following{background:var(--sv-follow-btn-following-bg,transparent);color:var(--sv-follow-btn-following-color,rgba(255,255,255,.9));border:1px solid var(--sv-follow-btn-following-border,rgba(255,255,255,.3))}.sv-author-info__follow-btn--following:hover:not(:disabled){background:var(--sv-follow-btn-following-bg-hover,rgba(255,255,255,.1));border-color:var(--sv-follow-btn-following-border-hover,rgba(255,255,255,.5))}.sv-author-info__follow-btn--pending{opacity:.6;pointer-events:none;cursor:wait}.sv-author-info__follow-btn:disabled{opacity:.5;cursor:not-allowed}.sv-author-info__follow-btn-icon{width:var(--sv-follow-btn-icon-size,16px);height:var(--sv-follow-btn-icon-size,16px);flex-shrink:0}.sv-author-info__follow-btn-spinner{width:var(--sv-follow-btn-icon-size,16px);height:var(--sv-follow-btn-icon-size,16px);border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:sv-author-info-spin .6s linear infinite}@keyframes sv-author-info-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.sv-author-info__follow-btn--small{padding:var(--sv-follow-btn-padding-small,6px 12px);font-size:var(--sv-follow-btn-size-small,12px);min-width:var(--sv-follow-btn-min-width-small,72px)}.sv-author-info__follow-btn--large{padding:var(--sv-follow-btn-padding-large,10px 20px);font-size:var(--sv-follow-btn-size-large,16px);min-width:var(--sv-follow-btn-min-width-large,100px)}.sv-author-info__follow-btn--icon-only{min-width:unset;padding:var(--sv-follow-btn-icon-padding,8px);border-radius:50%}.sv-author-info--inline{justify-content:space-between}.sv-author-info--inline .sv-author-info__content{flex:1}.sv-author-info--stacked{flex-direction:column;align-items:center;text-align:center}.sv-author-info--stacked .sv-author-info__content{align-items:center}.sv-author-info--overlay{text-shadow:var(--sv-author-overlay-shadow,0 1px 2px rgba(0,0,0,.5))}.sv-author-info--overlay .sv-author-info__avatar{border:2px solid var(--sv-author-overlay-avatar-border,rgba(255,255,255,.5))}.sv-author-info--avatar-badge{position:relative;display:flex;flex-direction:column;align-items:center;width:auto;gap:0}.sv-author-info--avatar-badge .sv-author-info__avatar{width:var(--sv-avatar-badge-size,48px);height:var(--sv-avatar-badge-size,48px);border:2px solid var(--sv-avatar-badge-border,#fff)}.sv-author-info--avatar-badge .sv-author-info__follow-btn{position:absolute;bottom:var(--sv-avatar-badge-btn-bottom,-10px);left:50%;transform:translateX(-50%);min-width:unset;width:var(--sv-avatar-badge-btn-size,24px);height:var(--sv-avatar-badge-btn-size,24px);padding:0;border-radius:50%;background:var(--sv-color-primary,#fe2c55);border:2px solid var(--sv-bg-primary,#000);z-index:1}.sv-author-info--avatar-badge .sv-author-info__follow-btn:hover:not(:disabled){transform:translateX(-50%)scale(1.1)}.sv-author-info--avatar-badge .sv-author-info__follow-btn:active:not(:disabled){transform:translateX(-50%)scale(.95)}.sv-author-info--avatar-badge .sv-author-info__follow-btn-icon{width:var(--sv-avatar-badge-icon-size,14px);height:var(--sv-avatar-badge-icon-size,14px)}.sv-author-info--avatar-badge .sv-author-info__follow-btn--following{display:none}.sv-author-info--avatar-badge .sv-author-info__content{display:none}.sv-author-info--avatar-badge{margin-bottom:var(--sv-avatar-badge-margin,16px)}`;
115
115
  function DefaultVerifiedIcon() {
116
116
  return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" }) });
117
117
  }
@@ -176,6 +176,136 @@ function useDoubleTap({
176
176
  lastPosition: lastPositionRef
177
177
  };
178
178
  }
179
+ var DEFAULT_HOLD_DELAY = 2e3;
180
+ var DEFAULT_BOOST_SPEED = 2;
181
+ var DEFAULT_PULL_DOWN_THRESHOLD = 50;
182
+ var DEFAULT_MOVEMENT_THRESHOLD2 = 15;
183
+ function useLongPressSpeed({
184
+ onSpeedBoost,
185
+ onSpeedReset,
186
+ onSpeedLock,
187
+ boostSpeed = DEFAULT_BOOST_SPEED,
188
+ holdDelay = DEFAULT_HOLD_DELAY,
189
+ pullDownThreshold = DEFAULT_PULL_DOWN_THRESHOLD,
190
+ disabled = false,
191
+ movementThreshold = DEFAULT_MOVEMENT_THRESHOLD2
192
+ }) {
193
+ const [isSpeedBoosted, setIsSpeedBoosted] = useState(false);
194
+ const [isSpeedLocked, setIsSpeedLocked] = useState(false);
195
+ const holdTimerRef = useRef(null);
196
+ const isBoostedRef = useRef(false);
197
+ const isLockedRef = useRef(false);
198
+ const pointerStartRef = useRef(null);
199
+ const boostStartYRef = useRef(null);
200
+ const preboostMovementRef = useRef(0);
201
+ const isTrackingRef = useRef(false);
202
+ const cancelTimer = useCallback(() => {
203
+ if (holdTimerRef.current) {
204
+ clearTimeout(holdTimerRef.current);
205
+ holdTimerRef.current = null;
206
+ }
207
+ }, []);
208
+ useEffect(() => {
209
+ return () => {
210
+ cancelTimer();
211
+ };
212
+ }, [cancelTimer]);
213
+ useEffect(() => {
214
+ if (disabled) {
215
+ cancelTimer();
216
+ if (isBoostedRef.current) {
217
+ isBoostedRef.current = false;
218
+ setIsSpeedBoosted(false);
219
+ }
220
+ }
221
+ }, [disabled, cancelTimer]);
222
+ const handlePointerDown = useCallback(
223
+ (e) => {
224
+ if (e.button !== 0) return;
225
+ if (disabled) return;
226
+ if (isLockedRef.current) return;
227
+ pointerStartRef.current = { x: e.clientX, y: e.clientY };
228
+ preboostMovementRef.current = 0;
229
+ isTrackingRef.current = true;
230
+ cancelTimer();
231
+ holdTimerRef.current = setTimeout(() => {
232
+ holdTimerRef.current = null;
233
+ isBoostedRef.current = true;
234
+ setIsSpeedBoosted(true);
235
+ boostStartYRef.current = pointerStartRef.current?.y ?? e.clientY;
236
+ onSpeedBoost?.(boostSpeed);
237
+ }, holdDelay);
238
+ },
239
+ [disabled, boostSpeed, holdDelay, cancelTimer, onSpeedBoost]
240
+ );
241
+ const handlePointerMove = useCallback(
242
+ (e) => {
243
+ if (!isTrackingRef.current) return;
244
+ if (!pointerStartRef.current) return;
245
+ if (!isBoostedRef.current) {
246
+ preboostMovementRef.current += Math.abs(e.movementX) + Math.abs(e.movementY);
247
+ if (preboostMovementRef.current > movementThreshold * 2) {
248
+ cancelTimer();
249
+ isTrackingRef.current = false;
250
+ }
251
+ } else {
252
+ if (boostStartYRef.current !== null && !isLockedRef.current) {
253
+ const deltaY = e.clientY - boostStartYRef.current;
254
+ if (deltaY > pullDownThreshold) {
255
+ isLockedRef.current = true;
256
+ setIsSpeedLocked(true);
257
+ onSpeedLock?.(boostSpeed);
258
+ }
259
+ }
260
+ }
261
+ },
262
+ [movementThreshold, pullDownThreshold, boostSpeed, cancelTimer, onSpeedLock]
263
+ );
264
+ const handlePointerUp = useCallback(
265
+ (_e) => {
266
+ cancelTimer();
267
+ isTrackingRef.current = false;
268
+ pointerStartRef.current = null;
269
+ boostStartYRef.current = null;
270
+ if (isBoostedRef.current && !isLockedRef.current) {
271
+ isBoostedRef.current = false;
272
+ setIsSpeedBoosted(false);
273
+ onSpeedReset?.();
274
+ } else if (isBoostedRef.current && isLockedRef.current) {
275
+ isBoostedRef.current = false;
276
+ setIsSpeedBoosted(false);
277
+ }
278
+ },
279
+ [cancelTimer, onSpeedReset]
280
+ );
281
+ const handlePointerCancel = useCallback(
282
+ (_e) => {
283
+ cancelTimer();
284
+ isTrackingRef.current = false;
285
+ pointerStartRef.current = null;
286
+ boostStartYRef.current = null;
287
+ if (isBoostedRef.current && !isLockedRef.current) {
288
+ isBoostedRef.current = false;
289
+ setIsSpeedBoosted(false);
290
+ onSpeedReset?.();
291
+ } else if (isBoostedRef.current) {
292
+ isBoostedRef.current = false;
293
+ setIsSpeedBoosted(false);
294
+ }
295
+ },
296
+ [cancelTimer, onSpeedReset]
297
+ );
298
+ return {
299
+ handlers: {
300
+ onPointerDown: handlePointerDown,
301
+ onPointerMove: handlePointerMove,
302
+ onPointerUp: handlePointerUp,
303
+ onPointerCancel: handlePointerCancel
304
+ },
305
+ isSpeedBoosted,
306
+ isSpeedLocked
307
+ };
308
+ }
179
309
  function invariantContextError(hookName, componentName) {
180
310
  const baseMessage = `${hookName} must be used within a VideoSlot component.`;
181
311
  if (process.env.NODE_ENV !== "production") {
@@ -365,4 +495,4 @@ function VideoSlotPlayIndicator(props) {
365
495
  }
366
496
  VideoSlotPlayIndicator.displayName = "VideoSlotPlayIndicator";
367
497
 
368
- export { VideoSlotContext, VideoSlotPlayIndicator, VideoSlotPlayIndicatorInner, useDoubleTap, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo };
498
+ export { VideoSlotContext, VideoSlotPlayIndicator, VideoSlotPlayIndicatorInner, useDoubleTap, useLongPressSpeed, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo };
@@ -181,7 +181,7 @@ function VideoHashtags({
181
181
  }
182
182
 
183
183
  // src/components/VideoInfo/VideoInfo.css.ts
184
- var VIDEO_INFO_CSS = `.sv-video-info{display:flex;flex-direction:column;gap:var(--sv-video-info-gap,6px);color:var(--sv-video-info-color,#fff);font-family:var(--sv-font-family,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif);text-shadow:var(--sv-video-info-text-shadow,0 1px 2px rgba(0,0,0,.5));max-width:100%;overflow:hidden;transition:opacity .3s cubic-bezier(.4,0,.2,1)}.sv-video-info--hidden{opacity:0;pointer-events:none}.sv-video-info--overlay{pointer-events:none}.sv-video-info--overlay>*{pointer-events:auto}.sv-video-info__author{display:flex;align-items:center;gap:var(--sv-video-info-author-gap,6px);cursor:pointer;transition:opacity .15s ease}.sv-video-info__author:hover{opacity:.85}.sv-video-info__author:active{opacity:.7}.sv-video-info__author-name{font-size:var(--sv-video-info-author-font-size,16px);font-weight:var(--sv-video-info-author-font-weight,700);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px}.sv-video-info__author-prefix{opacity:.95}.sv-video-info__verified-badge{display:inline-flex;align-items:center;justify-content:center;width:var(--sv-video-info-verified-size,14px);height:var(--sv-video-info-verified-size,14px);background:var(--sv-video-info-verified-bg,#20d5ec);border-radius:50%;flex-shrink:0}.sv-video-info__verified-badge svg,.sv-video-info__verified-badge span{font-size:10px;color:#fff;font-weight:bold}.sv-video-info__caption{font-size:var(--sv-video-info-caption-font-size,14px);line-height:var(--sv-video-info-caption-line-height,1.4);color:var(--sv-video-info-caption-color,#fff);display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.sv-video-info__caption--lines-1{-webkit-line-clamp:1}.sv-video-info__caption--lines-2{-webkit-line-clamp:2}.sv-video-info__caption--lines-3{-webkit-line-clamp:3}.sv-video-info__caption--expanded{-webkit-line-clamp:unset}.sv-video-info__caption--clickable{cursor:pointer;transition:opacity .15s ease}.sv-video-info__caption--clickable:hover{opacity:.85}.sv-video-info__caption--clickable:active{opacity:.7}.sv-video-info__caption-more{background:0 0;border:0;color:var(--sv-video-info-caption-more-color,rgba(255,255,255,.7));font-size:var(--sv-video-info-caption-font-size,14px);padding:0;margin-left:4px;cursor:pointer}.sv-video-info__caption-more:hover{color:var(--sv-video-info-caption-color,#fff)}.sv-video-info__hashtags{display:inline-flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:var(--sv-video-info-hashtag-gap,6px);font-size:var(--sv-video-info-hashtag-font-size,14px)}.sv-video-info__hashtags--inline{gap:var(--sv-video-info-hashtag-gap-inline,4px)}.sv-video-info__hashtag{display:inline-flex;color:var(--sv-video-info-hashtag-color,#fff);font-weight:var(--sv-video-info-hashtag-font-weight,500);background:0 0;border:0;padding:0;cursor:pointer;transition:opacity .15s ease;white-space:nowrap}.sv-video-info__hashtag:hover{opacity:.8;text-decoration:underline}.sv-video-info__hashtag--not-clickable{cursor:default}.sv-video-info__hashtag--not-clickable:hover{opacity:1;text-decoration:none}.sv-video-info__caption .sv-video-info__hashtag{display:inline}.sv-video-info__location{display:flex;align-items:center;gap:var(--sv-video-info-location-gap,4px);font-size:var(--sv-video-info-location-font-size,13px);color:var(--sv-video-info-location-color,rgba(255,255,255,.9));cursor:pointer;transition:opacity .15s ease}.sv-video-info__location:hover{opacity:.8}.sv-video-info__location-icon{font-size:14px;flex-shrink:0}.sv-video-info__location-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sv-video-info__music{display:flex;align-items:center;gap:var(--sv-video-info-music-gap,8px);font-size:var(--sv-video-info-music-font-size,13px);color:var(--sv-video-info-music-color,#fff);cursor:pointer;transition:opacity .15s ease;overflow:hidden}.sv-video-info__music:hover{opacity:.8}.sv-video-info__music-icon{font-size:14px;flex-shrink:0}.sv-video-info__music-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sv-video-info__music-text--marquee{animation:sv-video-info-marquee 8s linear infinite}@keyframes sv-video-info-marquee{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}`;
184
+ var VIDEO_INFO_CSS = `.sv-video-info{display:flex;flex-direction:column;gap:var(--sv-video-info-gap,6px);color:var(--sv-video-info-color,#fff);font-family:var(--sv-font-family,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif);text-shadow:var(--sv-video-info-text-shadow,0 1px 2px rgba(0,0,0,.5));max-width:100%;overflow:hidden;transition:opacity .3s cubic-bezier(.4,0,.2,1);user-select:none;-webkit-user-select:none}.sv-video-info--hidden{opacity:0;pointer-events:none}.sv-video-info--overlay{pointer-events:none}.sv-video-info--overlay>*{pointer-events:auto}.sv-video-info__author{display:flex;align-items:center;gap:var(--sv-video-info-author-gap,6px);cursor:pointer;transition:opacity .15s ease}.sv-video-info__author:hover{opacity:.85}.sv-video-info__author:active{opacity:.7}.sv-video-info__author-name{font-size:var(--sv-video-info-author-font-size,16px);font-weight:var(--sv-video-info-author-font-weight,700);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px}.sv-video-info__author-prefix{opacity:.95}.sv-video-info__verified-badge{display:inline-flex;align-items:center;justify-content:center;width:var(--sv-video-info-verified-size,14px);height:var(--sv-video-info-verified-size,14px);background:var(--sv-video-info-verified-bg,#20d5ec);border-radius:50%;flex-shrink:0}.sv-video-info__verified-badge svg,.sv-video-info__verified-badge span{font-size:10px;color:#fff;font-weight:bold}.sv-video-info__caption{font-size:var(--sv-video-info-caption-font-size,14px);line-height:var(--sv-video-info-caption-line-height,1.4);color:var(--sv-video-info-caption-color,#fff);display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.sv-video-info__caption--lines-1{-webkit-line-clamp:1}.sv-video-info__caption--lines-2{-webkit-line-clamp:2}.sv-video-info__caption--lines-3{-webkit-line-clamp:3}.sv-video-info__caption--expanded{-webkit-line-clamp:unset}.sv-video-info__caption--clickable{cursor:pointer;transition:opacity .15s ease}.sv-video-info__caption--clickable:hover{opacity:.85}.sv-video-info__caption--clickable:active{opacity:.7}.sv-video-info__caption-more{background:0 0;border:0;color:var(--sv-video-info-caption-more-color,rgba(255,255,255,.7));font-size:var(--sv-video-info-caption-font-size,14px);padding:0;margin-left:4px;cursor:pointer}.sv-video-info__caption-more:hover{color:var(--sv-video-info-caption-color,#fff)}.sv-video-info__hashtags{display:inline-flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:var(--sv-video-info-hashtag-gap,6px);font-size:var(--sv-video-info-hashtag-font-size,14px)}.sv-video-info__hashtags--inline{gap:var(--sv-video-info-hashtag-gap-inline,4px)}.sv-video-info__hashtag{display:inline-flex;color:var(--sv-video-info-hashtag-color,#fff);font-weight:var(--sv-video-info-hashtag-font-weight,500);background:0 0;border:0;padding:0;cursor:pointer;transition:opacity .15s ease;white-space:nowrap}.sv-video-info__hashtag:hover{opacity:.8;text-decoration:underline}.sv-video-info__hashtag--not-clickable{cursor:default}.sv-video-info__hashtag--not-clickable:hover{opacity:1;text-decoration:none}.sv-video-info__caption .sv-video-info__hashtag{display:inline}.sv-video-info__location{display:flex;align-items:center;gap:var(--sv-video-info-location-gap,4px);font-size:var(--sv-video-info-location-font-size,13px);color:var(--sv-video-info-location-color,rgba(255,255,255,.9));cursor:pointer;transition:opacity .15s ease}.sv-video-info__location:hover{opacity:.8}.sv-video-info__location-icon{font-size:14px;flex-shrink:0}.sv-video-info__location-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sv-video-info__music{display:flex;align-items:center;gap:var(--sv-video-info-music-gap,8px);font-size:var(--sv-video-info-music-font-size,13px);color:var(--sv-video-info-music-color,#fff);cursor:pointer;transition:opacity .15s ease;overflow:hidden}.sv-video-info__music:hover{opacity:.8}.sv-video-info__music-icon{font-size:14px;flex-shrink:0}.sv-video-info__music-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sv-video-info__music-text--marquee{animation:sv-video-info-marquee 8s linear infinite}@keyframes sv-video-info-marquee{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}`;
185
185
  function DefaultLocationIcon() {
186
186
  return /* @__PURE__ */ jsx("span", { className: "sv-video-info__location-icon", children: "\u{1F4CD}" });
187
187
  }
@@ -58,6 +58,7 @@ var ACTION_BAR_CSS = (
58
58
  touch-action: manipulation;
59
59
  -webkit-tap-highlight-color: transparent;
60
60
  user-select: none;
61
+ -webkit-user-select: none;
61
62
 
62
63
  /* Transition */
63
64
  transition: transform 0.15s ease, opacity 0.15s ease;
@@ -1,4 +1,4 @@
1
- import { useDoubleTap, VideoSlotPlayIndicatorInner } from './chunk-VS54DRIS.js';
1
+ import { useDoubleTap, VideoSlotPlayIndicatorInner } from './chunk-3LINB7GV.js';
2
2
  import { ImageCarouselHeadless } from './chunk-GSNIZ6DF.js';
3
3
  import { clsx2 } from './chunk-EDWS2IPH.js';
4
4
  import { injectComponentCSS } from './chunk-CAWE42LH.js';
@@ -1,13 +1,72 @@
1
- import { useDoubleTap, VideoSlotContext, useVideoSlotContext } from './chunk-VS54DRIS.js';
1
+ import { useDoubleTap, useLongPressSpeed, VideoSlotContext, useVideoSlotContext } from './chunk-3LINB7GV.js';
2
2
  import { HeartFilledIcon } from './chunk-ANCP53F3.js';
3
3
  import { clsx2 } from './chunk-EDWS2IPH.js';
4
4
  import { injectComponentCSS } from './chunk-CAWE42LH.js';
5
- import { memo, useMemo, useState, useCallback, useEffect, useInsertionEffect, useRef } from 'react';
5
+ import { memo, useMemo, useState, useCallback, useEffect, useRef, useInsertionEffect } from 'react';
6
6
  import { jsx, jsxs } from 'react/jsx-runtime';
7
7
 
8
8
  // src/components/VideoSlot/VideoSlot.css.ts
9
9
  var VIDEO_SLOT_CSS = `.sv-video-slot{position:relative;width:100%;height:100%;overflow:hidden;background-color:var(--sv-bg-primary,#000);touch-action:none;user-select:none;-webkit-user-select:none;will-change:contents;contain:layout style paint}.sv-video-slot--active{z-index:1}.sv-video-slot--loading .sv-video-slot__video{opacity:0}.sv-video-slot--loading .sv-video-slot__poster{opacity:1}.sv-video-slot--playing .sv-video-slot__video{opacity:1}.sv-video-slot--playing .sv-video-slot__poster{opacity:0}.sv-video-slot--paused .sv-video-slot__video{opacity:1}.sv-video-slot--paused .sv-video-slot__poster{opacity:0}.sv-video-slot__poster--hidden{opacity:0;pointer-events:none}.sv-video-slot--error{display:flex;align-items:center;justify-content:center}.sv-video-slot__video-container{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.sv-video-slot__video{width:100%;height:100%;object-fit:cover;background-color:transparent;transition:opacity var(--sv-transition-duration,300ms)ease-out}.sv-video-slot__video[data-loaded="true"]{opacity:1}.sv-video-slot__poster{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background-color:var(--sv-bg-primary,#000);z-index:var(--sv-z-poster,3);transition:opacity var(--sv-transition-duration,300ms)ease-out;pointer-events:none}.sv-video-slot__poster-image{width:100%;height:100%;object-fit:cover}.sv-video-slot__poster--first-frame .sv-video-slot__poster-image{image-rendering:auto}.sv-video-slot__poster--skeleton{background:linear-gradient(110deg,var(--sv-skeleton-bg,rgba(255,255,255,.05))0%,var(--sv-skeleton-shimmer,rgba(255,255,255,.1))50%,var(--sv-skeleton-bg,rgba(255,255,255,.05))100%);background-size:200% 100%;animation:sv-slot-skeleton-shimmer 1.5s ease-in-out infinite}@keyframes sv-slot-skeleton-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}.sv-video-slot__overlay{position:absolute;inset:0;z-index:var(--sv-z-overlay,2);background:linear-gradient(to top,rgba(0,0,0,.6)0%,rgba(0,0,0,.3)20%,transparent 40%,transparent 60%,rgba(0,0,0,.2)80%,rgba(0,0,0,.4)100%);pointer-events:none}.sv-video-slot__overlay-top,.sv-video-slot__overlay-bottom,.sv-video-slot__overlay-left,.sv-video-slot__overlay-right,.sv-video-slot__actions,.sv-video-slot__author{pointer-events:none}.sv-video-slot__overlay button,.sv-video-slot__overlay a,.sv-video-slot__overlay [role="button"],.sv-video-slot__overlay input,.sv-video-slot__overlay label,.sv-video-slot__overlay .sv-progress-bar,.sv-video-slot__overlay .sv-author-info,.sv-video-slot__overlay .sv-video-info,.sv-video-slot__overlay .sv-action-bar{pointer-events:auto}.sv-video-slot__overlay-top{position:absolute;top:0;left:0;right:0;padding:var(--sv-spacing-md,16px);padding-top:calc(var(--sv-safe-area-top,0)+var(--sv-spacing-md,16px))}.sv-video-slot__overlay-bottom{position:absolute;bottom:0;left:0;right:0;padding:var(--sv-spacing-md,16px);padding-bottom:calc(var(--sv-safe-area-bottom,0)+var(--sv-spacing-md,16px));display:flex;flex-direction:column;gap:var(--sv-spacing-sm,8px)}.sv-video-slot__overlay-left{position:absolute;top:50%;left:0;transform:translateY(-50%);padding:var(--sv-spacing-md,16px)}.sv-video-slot__overlay-right{position:absolute;top:50%;right:0;transform:translateY(-50%);padding:var(--sv-spacing-md,16px)}.sv-video-slot__actions{position:absolute;right:var(--sv-spacing-sm,8px);bottom:calc(var(--sv-safe-area-bottom,0)+var(--sv-actions-bottom,80px)+var(--sv-playlist-bar-offset,0));display:flex;flex-direction:column;align-items:center;transition:bottom .3s ease-in-out}.sv-video-slot__author{position:absolute;left:var(--sv-spacing-md,16px);bottom:calc(var(--sv-safe-area-bottom,0)+var(--sv-author-bottom,100px)+var(--sv-playlist-bar-offset,0));right:80px;max-width:calc(100% - 100px);transition:bottom .3s ease-in-out}.sv-video-slot__error{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:var(--sv-bg-primary,#000);color:var(--sv-text-secondary,#999);text-align:center;padding:var(--sv-spacing-lg,20px);gap:var(--sv-spacing-md,16px);z-index:var(--sv-z-indicator,3)}.sv-video-slot__error-icon{font-size:48px;opacity:.6}.sv-video-slot__error-message{font-size:var(--sv-font-size-md,14px);max-width:200px}.sv-video-slot__error-retry{padding:var(--sv-spacing-sm,8px)var(--sv-spacing-md,16px);background-color:var(--sv-color-primary,#fe2c55);color:#fff;border:0;border-radius:var(--sv-radius-md,8px);font-size:var(--sv-font-size-sm,12px);font-weight:600;cursor:pointer;transition:background-color 150ms ease}.sv-video-slot__error-retry:hover{background-color:var(--sv-color-primary-hover,#e02850)}.sv-video-slot__error-retry:active{transform:scale(.96)}.sv-video-slot__spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:var(--sv-z-slot-spinner,2)}.sv-video-slot__spinner-circle{width:40px;height:40px;border:3px solid rgba(255,255,255,.2);border-top-color:var(--sv-color-primary,#fe2c55);border-radius:50%;animation:sv-slot-spin .8s linear infinite}@keyframes sv-slot-spin{to{transform:rotate(360deg)}}.sv-video-slot__play-indicator{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:64px;height:64px;display:flex;align-items:center;justify-content:center;border-radius:50%;z-index:var(--sv-z-indicator,3);opacity:0;transition:opacity 200ms ease-out;pointer-events:none}.sv-video-slot__play-indicator--visible{opacity:.65}.sv-video-slot__play-indicator--persist{opacity:.65}.sv-video-slot__play-indicator--animating-out{animation:sv-slot-indicator-out var(--sv-indicator-duration,200ms)ease-out forwards}@keyframes sv-slot-indicator-out{0%{opacity:1;transform:translate(-50%,-50%)scale(1)}100%{opacity:0;transform:translate(-50%,-50%)scale(1.5)}}.sv-video-slot__play-indicator-icon{color:#fff;font-size:28px;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.sv-video-slot__progress{position:absolute;bottom:0;left:0;right:0;height:3px;background-color:rgba(255,255,255,.2);z-index:var(--sv-z-progress,4)}.sv-video-slot__progress-bar{height:100%;background-color:var(--sv-color-primary,#fe2c55);transition:width 100ms linear}.sv-video-slot__progress-buffered{position:absolute;top:0;left:0;height:100%;background-color:rgba(255,255,255,.3)}`;
10
10
 
11
+ // src/components/VideoSlot/SpeedBoostIndicator.css.ts
12
+ var SPEED_BOOST_INDICATOR_CSS = `.sv-speed-boost{position:absolute;top:calc(var(--sv-safe-area-top,0)+60px);left:50%;transform:translateX(-50%);z-index:20;display:flex;align-items:center;gap:6px;padding:6px 14px;border-radius:20px;background:rgba(0,0,0,.65);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);color:#fff;font-size:13px;font-weight:600;letter-spacing:.02em;white-space:nowrap;pointer-events:none;user-select:none;-webkit-user-select:none;animation:sv-speed-boost-in 200ms ease-out both}.sv-speed-boost--locked{background:rgba(0,0,0,.75);border:1px solid rgba(255,255,255,.15)}.sv-speed-boost--exit{animation:sv-speed-boost-out 200ms ease-in forwards}.sv-speed-boost__icon{display:flex;align-items:center;font-size:14px;animation:sv-speed-boost-pulse 600ms ease-in-out infinite alternate}.sv-speed-boost--locked .sv-speed-boost__icon{animation:none}.sv-speed-boost__lock{display:flex;align-items:center;font-size:11px;margin-left:2px}.sv-speed-boost__hint{font-size:11px;font-weight:normal;opacity:.7;margin-left:4px}@keyframes sv-speed-boost-in{0%{opacity:0;transform:translateX(-50%)scale(.8)translateY(-8px)}100%{opacity:1;transform:translateX(-50%)scale(1)translateY(0)}}@keyframes sv-speed-boost-out{0%{opacity:1;transform:translateX(-50%)scale(1)translateY(0)}100%{opacity:0;transform:translateX(-50%)scale(.9)translateY(-4px)}}@keyframes sv-speed-boost-pulse{0%{opacity:.7}100%{opacity:1}}`;
13
+ function SpeedBoostIndicatorBase({
14
+ isVisible,
15
+ isLocked,
16
+ speed = 2,
17
+ showHint = true
18
+ }) {
19
+ useEffect(() => {
20
+ return injectComponentCSS("speed-boost-indicator", SPEED_BOOST_INDICATOR_CSS);
21
+ }, []);
22
+ const [shouldRender, setShouldRender] = useState(false);
23
+ const [isExiting, setIsExiting] = useState(false);
24
+ const exitTimerRef = useRef(null);
25
+ useEffect(() => {
26
+ if (isVisible) {
27
+ setIsExiting(false);
28
+ setShouldRender(true);
29
+ if (exitTimerRef.current) {
30
+ clearTimeout(exitTimerRef.current);
31
+ exitTimerRef.current = null;
32
+ }
33
+ } else if (shouldRender && !isLocked) {
34
+ setIsExiting(true);
35
+ exitTimerRef.current = setTimeout(() => {
36
+ setShouldRender(false);
37
+ setIsExiting(false);
38
+ exitTimerRef.current = null;
39
+ }, 200);
40
+ } else if (!isVisible && !isLocked) {
41
+ setShouldRender(false);
42
+ setIsExiting(false);
43
+ }
44
+ return () => {
45
+ if (exitTimerRef.current) {
46
+ clearTimeout(exitTimerRef.current);
47
+ }
48
+ };
49
+ }, [isVisible, isLocked, shouldRender]);
50
+ const isVisibleOrLocked = shouldRender || isLocked;
51
+ if (!isVisibleOrLocked) return null;
52
+ const classNames = [
53
+ "sv-speed-boost",
54
+ isLocked && "sv-speed-boost--locked",
55
+ isExiting && !isLocked && "sv-speed-boost--exit"
56
+ ].filter(Boolean).join(" ");
57
+ return /* @__PURE__ */ jsxs("div", { className: classNames, "aria-live": "polite", role: "status", children: [
58
+ /* @__PURE__ */ jsx("span", { className: "sv-speed-boost__icon", "aria-hidden": "true", children: "\u25B6\u25B6" }),
59
+ /* @__PURE__ */ jsxs("span", { children: [
60
+ speed,
61
+ "x"
62
+ ] }),
63
+ isLocked && /* @__PURE__ */ jsx("span", { className: "sv-speed-boost__lock", "aria-label": "Speed locked", children: "locked" }),
64
+ showHint && isVisible && !isLocked && /* @__PURE__ */ jsx("span", { className: "sv-speed-boost__hint", children: "\u2193 pull down to lock" })
65
+ ] });
66
+ }
67
+ var SpeedBoostIndicator = memo(SpeedBoostIndicatorBase);
68
+ SpeedBoostIndicator.displayName = "SpeedBoostIndicator";
69
+
11
70
  // src/components/VideoSlot/constants.ts
12
71
  var VIDEO_ID_ATTR = "data-video-id";
13
72
  var VIDEO_ID_DATASET_KEY = "videoId";
@@ -64,7 +123,14 @@ function VideoSlotHeadlessBase({
64
123
  renderError,
65
124
  renderLoading,
66
125
  restoreFrame,
67
- style
126
+ onSpeedBoost,
127
+ onSpeedReset,
128
+ onSpeedLock,
129
+ style,
130
+ disableSpeedBoost,
131
+ speedBoostSpeed,
132
+ speedBoostHoldDelay,
133
+ speedBoostPullDownThreshold
68
134
  }) {
69
135
  useInsertionEffect(() => {
70
136
  return injectComponentCSS("video-slot", VIDEO_SLOT_CSS);
@@ -136,6 +202,36 @@ function VideoSlotHeadlessBase({
136
202
  onDoubleTap: handleDoubleTap,
137
203
  onLongPress: onLongPress ? handleLongPress : void 0
138
204
  });
205
+ const { handlers: speedHandlers, isSpeedBoosted, isSpeedLocked } = useLongPressSpeed({
206
+ onSpeedBoost,
207
+ onSpeedReset,
208
+ onSpeedLock,
209
+ boostSpeed: speedBoostSpeed,
210
+ holdDelay: speedBoostHoldDelay,
211
+ pullDownThreshold: speedBoostPullDownThreshold,
212
+ disabled: disableSpeedBoost || !onSpeedBoost
213
+ });
214
+ const mergedHandlers = useMemo(() => {
215
+ if (disableSpeedBoost || !onSpeedBoost) {
216
+ return tapHandlers;
217
+ }
218
+ return {
219
+ onPointerDown: (e) => {
220
+ tapHandlers.onPointerDown(e);
221
+ speedHandlers.onPointerDown(e);
222
+ },
223
+ onPointerMove: (e) => {
224
+ tapHandlers.onPointerMove(e);
225
+ speedHandlers.onPointerMove(e);
226
+ },
227
+ onPointerUp: (e) => {
228
+ tapHandlers.onPointerUp(e);
229
+ speedHandlers.onPointerUp(e);
230
+ },
231
+ onClick: tapHandlers.onClick,
232
+ onPointerCancel: speedHandlers.onPointerCancel
233
+ };
234
+ }, [tapHandlers, speedHandlers, disableSpeedBoost, onSpeedBoost]);
139
235
  const handleRetry = useCallback(() => {
140
236
  playerControls.play();
141
237
  }, [playerControls]);
@@ -181,14 +277,14 @@ function VideoSlotHeadlessBase({
181
277
  {
182
278
  ref: containerRef,
183
279
  className: clsx2(...stateClasses, className),
184
- ...tapHandlers,
280
+ ...mergedHandlers,
185
281
  ...{
186
282
  [VIDEO_ID_ATTR]: video.id,
187
283
  [SLOT_ACTIVE_ATTR]: resourceState.isActive ? "true" : "false",
188
284
  [PLAYER_STATE_ATTR]: playerStateString,
189
285
  [LOADING_ATTR]: playerState.isLoading ? "true" : "false"
190
286
  },
191
- style,
287
+ style: { WebkitUserSelect: "none", ...style },
192
288
  children: [
193
289
  restoreFrame && !playerState.isPlaying && !playerState.error && /* @__PURE__ */ jsx(
194
290
  "div",
@@ -208,6 +304,13 @@ function VideoSlotHeadlessBase({
208
304
  "aria-hidden": "true"
209
305
  }
210
306
  ),
307
+ onSpeedBoost && /* @__PURE__ */ jsx(
308
+ SpeedBoostIndicator,
309
+ {
310
+ isVisible: isSpeedBoosted,
311
+ isLocked: isSpeedLocked
312
+ }
313
+ ),
211
314
  playerState.error && (renderError ? renderError(playerState.error, handleRetry) : /* @__PURE__ */ jsx(DefaultErrorUI, { error: playerState.error, onRetry: handleRetry })),
212
315
  playerState.isLoading && !playerState.error && !restoreFrame && (renderLoading ? renderLoading() : /* @__PURE__ */ jsx(DefaultLoadingUI, {})),
213
316
  children
@@ -244,6 +244,6 @@ declare const ActionBarHeadless: typeof ActionBarHeadlessRoot & {
244
244
  * - --sv-action-count-color: Count text color (default: white)
245
245
  * - --sv-action-bar-gap: Gap between action buttons (default: 16px)
246
246
  */
247
- declare const ACTION_BAR_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 * ACTION BAR - Container for action buttons\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-action-bar {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--sv-action-bar-gap, 12px);\n padding: var(--sv-action-bar-padding, 8px 0);\n \n /* Auto-hide transition */\n transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Hidden state for auto-hide */\n.sv-action-bar--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Horizontal variant */\n.sv-action-bar--horizontal {\n flex-direction: row;\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 * ACTION BUTTON - Individual action button (Like, Comment, Share, etc.)\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-action-button {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--sv-action-button-gap, 4px);\n \n /* Reset button styles */\n appearance: none;\n background: transparent;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n \n /* Interaction */\n outline: none;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n user-select: none;\n \n /* Transition */\n transition: transform 0.15s ease, opacity 0.15s ease;\n}\n\n/* Hover state */\n.sv-action-button:hover {\n transform: scale(1.05);\n}\n\n/* Active (pressed) state */\n.sv-action-button:active {\n transform: scale(0.95);\n}\n\n/* Focus visible state (keyboard navigation) */\n.sv-action-button:focus-visible {\n outline: 2px solid var(--sv-focus-ring-color, rgba(255, 255, 255, 0.6));\n outline-offset: 2px;\n border-radius: 8px;\n}\n\n/* Disabled state */\n.sv-action-button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Pending state - No visual change, debounce handles rapid clicks */\n/* Button remains fully interactive for smooth UX like TikTok/Instagram */\n.sv-action-button--pending {\n /* No opacity change - keep button fully visible */\n /* No pointer-events:none - allow continuous clicks */\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 * ACTION BUTTON ICON\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-action-button__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n \n width: var(--sv-action-button-size, 48px);\n height: var(--sv-action-button-size, 48px);\n \n /* Background circle */\n border-radius: 50%;\n \n /* Icon color */\n color: var(--sv-action-button-color, white);\n \n /* Icon size - applied to SVG children */\n font-size: var(--sv-action-button-icon-size, 24px);\n \n /* Smooth transitions */\n transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;\n}\n\n/* SVG icon sizing */\n.sv-action-button__icon svg {\n width: var(--sv-action-button-icon-size, 24px);\n height: var(--sv-action-button-icon-size, 24px);\n fill: currentColor;\n}\n\n\n/* Active state - icon filled */\n.sv-action-button--active .sv-action-button__icon {\n color: var(--sv-action-button-active-color, #fe2c55);\n}\n\n/* Like animation (pop effect) */\n.sv-action-button--like-animate .sv-action-button__icon {\n animation: sv-like-pop 0.3s ease;\n}\n\n@keyframes sv-like-pop {\n 0% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2);\n }\n 50% {\n transform: scale(0.95);\n }\n 100% {\n transform: scale(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 * ACTION BUTTON COUNT\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-action-button__count {\n font-size: var(--sv-action-count-font-size, 12px);\n font-weight: 600;\n color: var(--sv-action-count-color, white);\n \n /* Prevent layout shift on number change */\n min-width: 2ch;\n text-align: center;\n \n /* Text shadow for readability on video */\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n \n /* Line height */\n line-height: 1.2;\n \n /* Transition for count updates */\n transition: transform 0.15s ease;\n}\n\n/* Count update animation */\n.sv-action-button--count-update .sv-action-button__count {\n animation: sv-count-bounce 0.3s ease;\n}\n\n@keyframes sv-count-bounce {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.15);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n/* Hide count when zero */\n.sv-action-button__count--hidden {\n visibility: hidden;\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 * VARIANTS\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/* Minimal variant - no background */\n.sv-action-button--minimal .sv-action-button__icon {\n background: transparent;\n}\n\n.sv-action-button--minimal:hover .sv-action-button__icon {\n background: rgba(255, 255, 255, 0.1);\n}\n\n/* Compact variant - smaller size */\n.sv-action-button--compact {\n gap: 2px;\n}\n\n.sv-action-button--compact .sv-action-button__icon {\n width: var(--sv-action-button-size-compact, 40px);\n height: var(--sv-action-button-size-compact, 40px);\n}\n\n.sv-action-button--compact .sv-action-button__count {\n font-size: var(--sv-action-count-font-size-compact, 11px);\n}\n\n/* Large variant */\n.sv-action-button--large .sv-action-button__icon {\n width: var(--sv-action-button-size-large, 56px);\n height: var(--sv-action-button-size-large, 56px);\n}\n\n.sv-action-button--large .sv-action-button__icon svg {\n width: var(--sv-action-button-icon-size-large, 28px);\n height: var(--sv-action-button-icon-size-large, 28px);\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 * SPECIFIC BUTTON TYPES\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/* Like button - red when active */\n.sv-action-button--like.sv-action-button--active .sv-action-button__icon {\n color: var(--sv-like-color, #fe2c55);\n}\n\n/* Bookmark button - yellow when active */\n.sv-action-button--bookmark.sv-action-button--active .sv-action-button__icon {\n color: var(--sv-bookmark-color, #ffc107);\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 * RESPONSIVE\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/* Small screens - slightly smaller buttons */\n@media (max-width: 375px) {\n .sv-action-button__icon {\n width: 44px;\n height: 44px;\n }\n \n .sv-action-button__icon svg {\n width: 22px;\n height: 22px;\n }\n \n .sv-action-button__count {\n font-size: 11px;\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\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/* Reduced motion preference */\n@media (prefers-reduced-motion: reduce) {\n .sv-action-button,\n .sv-action-button__icon,\n .sv-action-button__count {\n transition: none;\n animation: none;\n }\n}\n";
247
+ declare const ACTION_BAR_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 * ACTION BAR - Container for action buttons\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-action-bar {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--sv-action-bar-gap, 12px);\n padding: var(--sv-action-bar-padding, 8px 0);\n \n /* Auto-hide transition */\n transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Hidden state for auto-hide */\n.sv-action-bar--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Horizontal variant */\n.sv-action-bar--horizontal {\n flex-direction: row;\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 * ACTION BUTTON - Individual action button (Like, Comment, Share, etc.)\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-action-button {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--sv-action-button-gap, 4px);\n \n /* Reset button styles */\n appearance: none;\n background: transparent;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n \n /* Interaction */\n outline: none;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n user-select: none;\n -webkit-user-select: none;\n \n /* Transition */\n transition: transform 0.15s ease, opacity 0.15s ease;\n}\n\n/* Hover state */\n.sv-action-button:hover {\n transform: scale(1.05);\n}\n\n/* Active (pressed) state */\n.sv-action-button:active {\n transform: scale(0.95);\n}\n\n/* Focus visible state (keyboard navigation) */\n.sv-action-button:focus-visible {\n outline: 2px solid var(--sv-focus-ring-color, rgba(255, 255, 255, 0.6));\n outline-offset: 2px;\n border-radius: 8px;\n}\n\n/* Disabled state */\n.sv-action-button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Pending state - No visual change, debounce handles rapid clicks */\n/* Button remains fully interactive for smooth UX like TikTok/Instagram */\n.sv-action-button--pending {\n /* No opacity change - keep button fully visible */\n /* No pointer-events:none - allow continuous clicks */\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 * ACTION BUTTON ICON\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-action-button__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n \n width: var(--sv-action-button-size, 48px);\n height: var(--sv-action-button-size, 48px);\n \n /* Background circle */\n border-radius: 50%;\n \n /* Icon color */\n color: var(--sv-action-button-color, white);\n \n /* Icon size - applied to SVG children */\n font-size: var(--sv-action-button-icon-size, 24px);\n \n /* Smooth transitions */\n transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;\n}\n\n/* SVG icon sizing */\n.sv-action-button__icon svg {\n width: var(--sv-action-button-icon-size, 24px);\n height: var(--sv-action-button-icon-size, 24px);\n fill: currentColor;\n}\n\n\n/* Active state - icon filled */\n.sv-action-button--active .sv-action-button__icon {\n color: var(--sv-action-button-active-color, #fe2c55);\n}\n\n/* Like animation (pop effect) */\n.sv-action-button--like-animate .sv-action-button__icon {\n animation: sv-like-pop 0.3s ease;\n}\n\n@keyframes sv-like-pop {\n 0% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2);\n }\n 50% {\n transform: scale(0.95);\n }\n 100% {\n transform: scale(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 * ACTION BUTTON COUNT\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-action-button__count {\n font-size: var(--sv-action-count-font-size, 12px);\n font-weight: 600;\n color: var(--sv-action-count-color, white);\n \n /* Prevent layout shift on number change */\n min-width: 2ch;\n text-align: center;\n \n /* Text shadow for readability on video */\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n \n /* Line height */\n line-height: 1.2;\n \n /* Transition for count updates */\n transition: transform 0.15s ease;\n}\n\n/* Count update animation */\n.sv-action-button--count-update .sv-action-button__count {\n animation: sv-count-bounce 0.3s ease;\n}\n\n@keyframes sv-count-bounce {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.15);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n/* Hide count when zero */\n.sv-action-button__count--hidden {\n visibility: hidden;\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 * VARIANTS\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/* Minimal variant - no background */\n.sv-action-button--minimal .sv-action-button__icon {\n background: transparent;\n}\n\n.sv-action-button--minimal:hover .sv-action-button__icon {\n background: rgba(255, 255, 255, 0.1);\n}\n\n/* Compact variant - smaller size */\n.sv-action-button--compact {\n gap: 2px;\n}\n\n.sv-action-button--compact .sv-action-button__icon {\n width: var(--sv-action-button-size-compact, 40px);\n height: var(--sv-action-button-size-compact, 40px);\n}\n\n.sv-action-button--compact .sv-action-button__count {\n font-size: var(--sv-action-count-font-size-compact, 11px);\n}\n\n/* Large variant */\n.sv-action-button--large .sv-action-button__icon {\n width: var(--sv-action-button-size-large, 56px);\n height: var(--sv-action-button-size-large, 56px);\n}\n\n.sv-action-button--large .sv-action-button__icon svg {\n width: var(--sv-action-button-icon-size-large, 28px);\n height: var(--sv-action-button-icon-size-large, 28px);\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 * SPECIFIC BUTTON TYPES\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/* Like button - red when active */\n.sv-action-button--like.sv-action-button--active .sv-action-button__icon {\n color: var(--sv-like-color, #fe2c55);\n}\n\n/* Bookmark button - yellow when active */\n.sv-action-button--bookmark.sv-action-button--active .sv-action-button__icon {\n color: var(--sv-bookmark-color, #ffc107);\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 * RESPONSIVE\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/* Small screens - slightly smaller buttons */\n@media (max-width: 375px) {\n .sv-action-button__icon {\n width: 44px;\n height: 44px;\n }\n \n .sv-action-button__icon svg {\n width: 22px;\n height: 22px;\n }\n \n .sv-action-button__count {\n font-size: 11px;\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\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/* Reduced motion preference */\n@media (prefers-reduced-motion: reduce) {\n .sv-action-button,\n .sv-action-button__icon,\n .sv-action-button__count {\n transition: none;\n animation: none;\n }\n}\n";
248
248
 
249
249
  export { ACTION_BAR_CSS, CompoundBookmark as ActionBarBookmark, CompoundComment as ActionBarComment, ActionBarHeadless, type ActionBarHeadlessExtendedProps, CompoundLike as ActionBarLike, CompoundShare as ActionBarShare, ActionButton, type ActionButtonExtendedProps, BookmarkButton, type BookmarkButtonProps, CommentButton, type CommentButtonProps, LikeButton, type LikeButtonProps, ShareButton, type ShareButtonProps };
@@ -1 +1 @@
1
- export { ACTION_BAR_CSS, CompoundBookmark as ActionBarBookmark, CompoundComment as ActionBarComment, ActionBarHeadless, CompoundLike as ActionBarLike, CompoundShare as ActionBarShare, ActionButton, BookmarkButton, CommentButton, LikeButton, ShareButton } from '../../chunk-NJXIYSDZ.js';
1
+ export { ACTION_BAR_CSS, CompoundBookmark as ActionBarBookmark, CompoundComment as ActionBarComment, ActionBarHeadless, CompoundLike as ActionBarLike, CompoundShare as ActionBarShare, ActionButton, BookmarkButton, CommentButton, LikeButton, ShareButton } from '../../chunk-C27FC7E2.js';
@@ -1 +1 @@
1
- export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, ArticleSlotBottom, ArticleSlotCaption, ArticleSlotHeadless, ArticleSlotMusic, ArticleSlotOverlay, ArticleSlotPlayIndicator, ArticleSlotReadMore, 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, ArticleSlotBottom as ImagePostSlotBottom, ArticleSlotCaption as ImagePostSlotCaption, ArticleSlotHeadless as ImagePostSlotHeadless, ArticleSlotMusic as ImagePostSlotMusic, ArticleSlotOverlay as ImagePostSlotOverlay, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, ArticleSlotReadMore as ImagePostSlotReadMore, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext } from '../../chunk-TX3D3C2M.js';
1
+ export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, ArticleSlotBottom, ArticleSlotCaption, ArticleSlotHeadless, ArticleSlotMusic, ArticleSlotOverlay, ArticleSlotPlayIndicator, ArticleSlotReadMore, 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, ArticleSlotBottom as ImagePostSlotBottom, ArticleSlotCaption as ImagePostSlotCaption, ArticleSlotHeadless as ImagePostSlotHeadless, ArticleSlotMusic as ImagePostSlotMusic, ArticleSlotOverlay as ImagePostSlotOverlay, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, ArticleSlotReadMore as ImagePostSlotReadMore, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext } from '../../chunk-OTCSGHTG.js';
@@ -273,6 +273,6 @@ declare function useOptionalAuthorInfoContext(): AuthorInfoContextValue | null;
273
273
  * - --sv-author-desc-color: Description text color
274
274
  * - --sv-follow-btn-*: Follow button styling
275
275
  */
276
- declare const AUTHOR_INFO_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 AUTHOR INFO - 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-author-info {\n display: flex;\n align-items: center;\n gap: var(--sv-author-gap, 12px);\n width: 100%;\n}\n\n.sv-author-info--vertical {\n flex-direction: column;\n align-items: flex-start;\n}\n\n.sv-author-info--horizontal {\n flex-direction: row;\n align-items: center;\n}\n\n.sv-author-info--compact {\n gap: var(--sv-author-gap-compact, 8px);\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 AVATAR\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-info__avatar {\n position: relative;\n flex-shrink: 0;\n width: var(--sv-author-avatar-size, 48px);\n height: var(--sv-author-avatar-size, 48px);\n border-radius: 50%;\n overflow: hidden;\n background: var(--sv-author-avatar-bg, rgba(255, 255, 255, 0.1));\n cursor: pointer;\n transition: transform 0.15s ease;\n}\n\n.sv-author-info__avatar:hover {\n transform: scale(1.05);\n}\n\n.sv-author-info__avatar:active {\n transform: scale(0.98);\n}\n\n.sv-author-info__avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 50%;\n}\n\n.sv-author-info__avatar-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sv-author-avatar-placeholder-bg, linear-gradient(135deg, #667eea 0%, #764ba2 100%));\n color: var(--sv-author-avatar-placeholder-color, #fff);\n font-size: calc(var(--sv-author-avatar-size, 48px) * 0.4);\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.sv-author-info__avatar-placeholder svg {\n width: 60%;\n height: 60%;\n opacity: 0.9;\n}\n\n/* Avatar sizes */\n.sv-author-info__avatar--small {\n width: var(--sv-author-avatar-size-small, 32px);\n height: var(--sv-author-avatar-size-small, 32px);\n}\n\n.sv-author-info__avatar--large {\n width: var(--sv-author-avatar-size-large, 64px);\n height: var(--sv-author-avatar-size-large, 64px);\n}\n\n/* Verified badge */\n.sv-author-info__verified-badge {\n position: absolute;\n bottom: -2px;\n right: -2px;\n width: calc(var(--sv-author-avatar-size, 48px) * 0.35);\n height: calc(var(--sv-author-avatar-size, 48px) * 0.35);\n min-width: 14px;\n min-height: 14px;\n border-radius: 50%;\n background: var(--sv-verified-badge-bg, #1DA1F2);\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--sv-verified-badge-border, #000);\n}\n\n.sv-author-info__verified-badge svg {\n width: 60%;\n height: 60%;\n color: var(--sv-verified-badge-color, #fff);\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 INFO (Name + Description 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-author-info__content {\n display: flex;\n flex-direction: column;\n gap: var(--sv-author-content-gap, 2px);\n flex: 1;\n min-width: 0; /* Allow text truncation */\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 NAME\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-info__name {\n display: flex;\n align-items: center;\n gap: var(--sv-author-name-gap, 4px);\n font-size: var(--sv-author-name-size, 16px);\n font-weight: var(--sv-author-name-weight, 600);\n color: var(--sv-author-name-color, #fff);\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-author-info__name:hover {\n opacity: 0.8;\n}\n\n.sv-author-info__name-text {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sv-author-info__name--with-at::before {\n content: '@';\n opacity: 0.8;\n}\n\n.sv-author-info__name-verified {\n flex-shrink: 0;\n width: var(--sv-author-name-verified-size, 14px);\n height: var(--sv-author-name-verified-size, 14px);\n color: var(--sv-verified-badge-bg, #1DA1F2);\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 DESCRIPTION / BIO\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-info__description {\n font-size: var(--sv-author-desc-size, 13px);\n color: var(--sv-author-desc-color, rgba(255, 255, 255, 0.7));\n line-height: var(--sv-author-desc-line-height, 1.4);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: var(--sv-author-desc-lines, 2);\n -webkit-box-orient: vertical;\n}\n\n.sv-author-info__description--single-line {\n -webkit-line-clamp: 1;\n white-space: nowrap;\n display: block;\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 FOLLOW BUTTON\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-info__follow-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--sv-follow-btn-gap, 6px);\n padding: var(--sv-follow-btn-padding, 8px 16px);\n min-width: var(--sv-follow-btn-min-width, 88px);\n border: none;\n border-radius: var(--sv-follow-btn-radius, 4px);\n font-size: var(--sv-follow-btn-size, 14px);\n font-weight: var(--sv-follow-btn-weight, 600);\n cursor: pointer;\n transition: all 0.2s ease;\n outline: none;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n/* Not following state (primary CTA) */\n.sv-author-info__follow-btn--default {\n background: var(--sv-follow-btn-bg, #fe2c55);\n color: var(--sv-follow-btn-color, #fff);\n}\n\n.sv-author-info__follow-btn--default:hover:not(:disabled) {\n background: var(--sv-follow-btn-bg-hover, #ff4466);\n transform: scale(1.02);\n}\n\n.sv-author-info__follow-btn--default:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n/* Following state (outline) */\n.sv-author-info__follow-btn--following {\n background: var(--sv-follow-btn-following-bg, transparent);\n color: var(--sv-follow-btn-following-color, rgba(255, 255, 255, 0.9));\n border: 1px solid var(--sv-follow-btn-following-border, rgba(255, 255, 255, 0.3));\n}\n\n.sv-author-info__follow-btn--following:hover:not(:disabled) {\n background: var(--sv-follow-btn-following-bg-hover, rgba(255, 255, 255, 0.1));\n border-color: var(--sv-follow-btn-following-border-hover, rgba(255, 255, 255, 0.5));\n}\n\n/* Pending state */\n.sv-author-info__follow-btn--pending {\n opacity: 0.6;\n pointer-events: none;\n cursor: wait;\n}\n\n.sv-author-info__follow-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Icon in button */\n.sv-author-info__follow-btn-icon {\n width: var(--sv-follow-btn-icon-size, 16px);\n height: var(--sv-follow-btn-icon-size, 16px);\n flex-shrink: 0;\n}\n\n/* Loading spinner */\n.sv-author-info__follow-btn-spinner {\n width: var(--sv-follow-btn-icon-size, 16px);\n height: var(--sv-follow-btn-icon-size, 16px);\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: sv-author-info-spin 0.6s linear infinite;\n}\n\n@keyframes sv-author-info-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Button sizes */\n.sv-author-info__follow-btn--small {\n padding: var(--sv-follow-btn-padding-small, 6px 12px);\n font-size: var(--sv-follow-btn-size-small, 12px);\n min-width: var(--sv-follow-btn-min-width-small, 72px);\n}\n\n.sv-author-info__follow-btn--large {\n padding: var(--sv-follow-btn-padding-large, 10px 20px);\n font-size: var(--sv-follow-btn-size-large, 16px);\n min-width: var(--sv-follow-btn-min-width-large, 100px);\n}\n\n/* Icon-only button */\n.sv-author-info__follow-btn--icon-only {\n min-width: unset;\n padding: var(--sv-follow-btn-icon-padding, 8px);\n border-radius: 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 LAYOUT VARIANTS\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/* Inline variant (avatar + name inline, follow button on right) */\n.sv-author-info--inline {\n justify-content: space-between;\n}\n\n.sv-author-info--inline .sv-author-info__content {\n flex: 1;\n}\n\n/* Stacked variant (avatar above name) */\n.sv-author-info--stacked {\n flex-direction: column;\n align-items: center;\n text-align: center;\n}\n\n.sv-author-info--stacked .sv-author-info__content {\n align-items: 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 OVERLAY MODE (for use on video)\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-info--overlay {\n /* Text shadow for readability on video */\n text-shadow: var(--sv-author-overlay-shadow, 0 1px 2px rgba(0, 0, 0, 0.5));\n}\n\n.sv-author-info--overlay .sv-author-info__avatar {\n border: 2px solid var(--sv-author-overlay-avatar-border, rgba(255, 255, 255, 0.5));\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 AVATAR-BADGE VARIANT (TikTok-style avatar with follow badge)\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-info--avatar-badge {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: auto;\n gap: 0;\n}\n\n/* Avatar in badge variant */\n.sv-author-info--avatar-badge .sv-author-info__avatar {\n width: var(--sv-avatar-badge-size, 48px);\n height: var(--sv-avatar-badge-size, 48px);\n border: 2px solid var(--sv-avatar-badge-border, #fff);\n}\n\n/* Follow button as overlay badge */\n.sv-author-info--avatar-badge .sv-author-info__follow-btn {\n position: absolute;\n bottom: var(--sv-avatar-badge-btn-bottom, -10px);\n left: 50%;\n transform: translateX(-50%);\n min-width: unset;\n width: var(--sv-avatar-badge-btn-size, 24px);\n height: var(--sv-avatar-badge-btn-size, 24px);\n padding: 0;\n border-radius: 50%;\n background: var(--sv-color-primary, #fe2c55);\n border: 2px solid var(--sv-bg-primary, #000);\n z-index: 1;\n}\n\n.sv-author-info--avatar-badge .sv-author-info__follow-btn:hover:not(:disabled) {\n transform: translateX(-50%) scale(1.1);\n}\n\n.sv-author-info--avatar-badge .sv-author-info__follow-btn:active:not(:disabled) {\n transform: translateX(-50%) scale(0.95);\n}\n\n/* Icon size in badge button */\n.sv-author-info--avatar-badge .sv-author-info__follow-btn-icon {\n width: var(--sv-avatar-badge-icon-size, 14px);\n height: var(--sv-avatar-badge-icon-size, 14px);\n}\n\n/* Hide button when following (TikTok behavior) */\n.sv-author-info--avatar-badge .sv-author-info__follow-btn--following {\n display: none;\n}\n\n/* Hide content section in badge variant */\n.sv-author-info--avatar-badge .sv-author-info__content {\n display: none;\n}\n\n/* Add margin bottom for action bar spacing */\n.sv-author-info--avatar-badge {\n margin-bottom: var(--sv-avatar-badge-margin, 16px);\n}\n";
276
+ declare const AUTHOR_INFO_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 AUTHOR INFO - 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-author-info {\n display: flex;\n align-items: center;\n gap: var(--sv-author-gap, 12px);\n width: 100%;\n}\n\n.sv-author-info--vertical {\n flex-direction: column;\n align-items: flex-start;\n}\n\n.sv-author-info--horizontal {\n flex-direction: row;\n align-items: center;\n}\n\n.sv-author-info--compact {\n gap: var(--sv-author-gap-compact, 8px);\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 AVATAR\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-info__avatar {\n position: relative;\n flex-shrink: 0;\n width: var(--sv-author-avatar-size, 48px);\n height: var(--sv-author-avatar-size, 48px);\n border-radius: 50%;\n overflow: hidden;\n background: var(--sv-author-avatar-bg, rgba(255, 255, 255, 0.1));\n cursor: pointer;\n transition: transform 0.15s ease;\n}\n\n.sv-author-info__avatar:hover {\n transform: scale(1.05);\n}\n\n.sv-author-info__avatar:active {\n transform: scale(0.98);\n}\n\n.sv-author-info__avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 50%;\n}\n\n.sv-author-info__avatar-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sv-author-avatar-placeholder-bg, linear-gradient(135deg, #667eea 0%, #764ba2 100%));\n color: var(--sv-author-avatar-placeholder-color, #fff);\n font-size: calc(var(--sv-author-avatar-size, 48px) * 0.4);\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.sv-author-info__avatar-placeholder svg {\n width: 60%;\n height: 60%;\n opacity: 0.9;\n}\n\n/* Avatar sizes */\n.sv-author-info__avatar--small {\n width: var(--sv-author-avatar-size-small, 32px);\n height: var(--sv-author-avatar-size-small, 32px);\n}\n\n.sv-author-info__avatar--large {\n width: var(--sv-author-avatar-size-large, 64px);\n height: var(--sv-author-avatar-size-large, 64px);\n}\n\n/* Verified badge */\n.sv-author-info__verified-badge {\n position: absolute;\n bottom: -2px;\n right: -2px;\n width: calc(var(--sv-author-avatar-size, 48px) * 0.35);\n height: calc(var(--sv-author-avatar-size, 48px) * 0.35);\n min-width: 14px;\n min-height: 14px;\n border-radius: 50%;\n background: var(--sv-verified-badge-bg, #1DA1F2);\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--sv-verified-badge-border, #000);\n}\n\n.sv-author-info__verified-badge svg {\n width: 60%;\n height: 60%;\n color: var(--sv-verified-badge-color, #fff);\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 INFO (Name + Description 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-author-info__content {\n display: flex;\n flex-direction: column;\n gap: var(--sv-author-content-gap, 2px);\n flex: 1;\n min-width: 0; /* Allow text truncation */\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 NAME\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-info__name {\n display: flex;\n align-items: center;\n gap: var(--sv-author-name-gap, 4px);\n font-size: var(--sv-author-name-size, 16px);\n font-weight: var(--sv-author-name-weight, 600);\n color: var(--sv-author-name-color, #fff);\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-author-info__name:hover {\n opacity: 0.8;\n}\n\n.sv-author-info__name-text {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sv-author-info__name--with-at::before {\n content: '@';\n opacity: 0.8;\n}\n\n.sv-author-info__name-verified {\n flex-shrink: 0;\n width: var(--sv-author-name-verified-size, 14px);\n height: var(--sv-author-name-verified-size, 14px);\n color: var(--sv-verified-badge-bg, #1DA1F2);\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 DESCRIPTION / BIO\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-info__description {\n font-size: var(--sv-author-desc-size, 13px);\n color: var(--sv-author-desc-color, rgba(255, 255, 255, 0.7));\n line-height: var(--sv-author-desc-line-height, 1.4);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: var(--sv-author-desc-lines, 2);\n -webkit-box-orient: vertical;\n}\n\n.sv-author-info__description--single-line {\n -webkit-line-clamp: 1;\n white-space: nowrap;\n display: block;\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 FOLLOW BUTTON\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-info__follow-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--sv-follow-btn-gap, 6px);\n padding: var(--sv-follow-btn-padding, 8px 16px);\n min-width: var(--sv-follow-btn-min-width, 88px);\n border: none;\n border-radius: var(--sv-follow-btn-radius, 4px);\n font-size: var(--sv-follow-btn-size, 14px);\n font-weight: var(--sv-follow-btn-weight, 600);\n cursor: pointer;\n transition: all 0.2s ease;\n outline: none;\n user-select: none;\n -webkit-user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n/* Not following state (primary CTA) */\n.sv-author-info__follow-btn--default {\n background: var(--sv-follow-btn-bg, #fe2c55);\n color: var(--sv-follow-btn-color, #fff);\n}\n\n.sv-author-info__follow-btn--default:hover:not(:disabled) {\n background: var(--sv-follow-btn-bg-hover, #ff4466);\n transform: scale(1.02);\n}\n\n.sv-author-info__follow-btn--default:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n/* Following state (outline) */\n.sv-author-info__follow-btn--following {\n background: var(--sv-follow-btn-following-bg, transparent);\n color: var(--sv-follow-btn-following-color, rgba(255, 255, 255, 0.9));\n border: 1px solid var(--sv-follow-btn-following-border, rgba(255, 255, 255, 0.3));\n}\n\n.sv-author-info__follow-btn--following:hover:not(:disabled) {\n background: var(--sv-follow-btn-following-bg-hover, rgba(255, 255, 255, 0.1));\n border-color: var(--sv-follow-btn-following-border-hover, rgba(255, 255, 255, 0.5));\n}\n\n/* Pending state */\n.sv-author-info__follow-btn--pending {\n opacity: 0.6;\n pointer-events: none;\n cursor: wait;\n}\n\n.sv-author-info__follow-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Icon in button */\n.sv-author-info__follow-btn-icon {\n width: var(--sv-follow-btn-icon-size, 16px);\n height: var(--sv-follow-btn-icon-size, 16px);\n flex-shrink: 0;\n}\n\n/* Loading spinner */\n.sv-author-info__follow-btn-spinner {\n width: var(--sv-follow-btn-icon-size, 16px);\n height: var(--sv-follow-btn-icon-size, 16px);\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: sv-author-info-spin 0.6s linear infinite;\n}\n\n@keyframes sv-author-info-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Button sizes */\n.sv-author-info__follow-btn--small {\n padding: var(--sv-follow-btn-padding-small, 6px 12px);\n font-size: var(--sv-follow-btn-size-small, 12px);\n min-width: var(--sv-follow-btn-min-width-small, 72px);\n}\n\n.sv-author-info__follow-btn--large {\n padding: var(--sv-follow-btn-padding-large, 10px 20px);\n font-size: var(--sv-follow-btn-size-large, 16px);\n min-width: var(--sv-follow-btn-min-width-large, 100px);\n}\n\n/* Icon-only button */\n.sv-author-info__follow-btn--icon-only {\n min-width: unset;\n padding: var(--sv-follow-btn-icon-padding, 8px);\n border-radius: 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 LAYOUT VARIANTS\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/* Inline variant (avatar + name inline, follow button on right) */\n.sv-author-info--inline {\n justify-content: space-between;\n}\n\n.sv-author-info--inline .sv-author-info__content {\n flex: 1;\n}\n\n/* Stacked variant (avatar above name) */\n.sv-author-info--stacked {\n flex-direction: column;\n align-items: center;\n text-align: center;\n}\n\n.sv-author-info--stacked .sv-author-info__content {\n align-items: 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 OVERLAY MODE (for use on video)\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-info--overlay {\n /* Text shadow for readability on video */\n text-shadow: var(--sv-author-overlay-shadow, 0 1px 2px rgba(0, 0, 0, 0.5));\n}\n\n.sv-author-info--overlay .sv-author-info__avatar {\n border: 2px solid var(--sv-author-overlay-avatar-border, rgba(255, 255, 255, 0.5));\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 AVATAR-BADGE VARIANT (TikTok-style avatar with follow badge)\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-info--avatar-badge {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: auto;\n gap: 0;\n}\n\n/* Avatar in badge variant */\n.sv-author-info--avatar-badge .sv-author-info__avatar {\n width: var(--sv-avatar-badge-size, 48px);\n height: var(--sv-avatar-badge-size, 48px);\n border: 2px solid var(--sv-avatar-badge-border, #fff);\n}\n\n/* Follow button as overlay badge */\n.sv-author-info--avatar-badge .sv-author-info__follow-btn {\n position: absolute;\n bottom: var(--sv-avatar-badge-btn-bottom, -10px);\n left: 50%;\n transform: translateX(-50%);\n min-width: unset;\n width: var(--sv-avatar-badge-btn-size, 24px);\n height: var(--sv-avatar-badge-btn-size, 24px);\n padding: 0;\n border-radius: 50%;\n background: var(--sv-color-primary, #fe2c55);\n border: 2px solid var(--sv-bg-primary, #000);\n z-index: 1;\n}\n\n.sv-author-info--avatar-badge .sv-author-info__follow-btn:hover:not(:disabled) {\n transform: translateX(-50%) scale(1.1);\n}\n\n.sv-author-info--avatar-badge .sv-author-info__follow-btn:active:not(:disabled) {\n transform: translateX(-50%) scale(0.95);\n}\n\n/* Icon size in badge button */\n.sv-author-info--avatar-badge .sv-author-info__follow-btn-icon {\n width: var(--sv-avatar-badge-icon-size, 14px);\n height: var(--sv-avatar-badge-icon-size, 14px);\n}\n\n/* Hide button when following (TikTok behavior) */\n.sv-author-info--avatar-badge .sv-author-info__follow-btn--following {\n display: none;\n}\n\n/* Hide content section in badge variant */\n.sv-author-info--avatar-badge .sv-author-info__content {\n display: none;\n}\n\n/* Add margin bottom for action bar spacing */\n.sv-author-info--avatar-badge {\n margin-bottom: var(--sv-avatar-badge-margin, 16px);\n}\n";
277
277
 
278
278
  export { AUTHOR_INFO_CSS, AuthorAvatar, type AuthorAvatarProps, AuthorDescription, type AuthorDescriptionProps, AuthorInfoContext, type AuthorInfoContextValue, AuthorInfoHeadless, type AuthorInfoHeadlessExtendedProps, type AuthorInfoVariant, AuthorName, type AuthorNameProps, type AvatarSize, FollowButton, type FollowButtonProps, type FollowButtonSize, useAuthorInfoContext, useOptionalAuthorInfoContext };
@@ -1 +1 @@
1
- export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext } from '../../chunk-3OB3OVYR.js';
1
+ export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext } from '../../chunk-26KDWJRI.js';
@@ -159,6 +159,6 @@ declare function useOptionalVideoInfoContext(): VideoInfoContextValue | undefine
159
159
  * - Location (optional)
160
160
  * - Music info (optional)
161
161
  */
162
- declare const VIDEO_INFO_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 * VideoInfo 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-info {\n display: flex;\n flex-direction: column;\n gap: var(--sv-video-info-gap, 6px);\n color: var(--sv-video-info-color, #fff);\n font-family: var(--sv-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n text-shadow: var(--sv-video-info-text-shadow, 0 1px 2px rgba(0, 0, 0, 0.5));\n max-width: 100%;\n overflow: hidden;\n \n /* Auto-hide transition */\n transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Hidden state for auto-hide */\n.sv-video-info--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Overlay variant (on top of video) */\n.sv-video-info--overlay {\n pointer-events: none;\n}\n\n.sv-video-info--overlay > * {\n pointer-events: auto;\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 Name\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-info__author {\n display: flex;\n align-items: center;\n gap: var(--sv-video-info-author-gap, 6px);\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-video-info__author:hover {\n opacity: 0.85;\n}\n\n.sv-video-info__author:active {\n opacity: 0.7;\n}\n\n.sv-video-info__author-name {\n font-size: var(--sv-video-info-author-font-size, 16px);\n font-weight: var(--sv-video-info-author-font-weight, 700);\n line-height: 1.3;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.sv-video-info__author-prefix {\n opacity: 0.95;\n}\n\n.sv-video-info__verified-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--sv-video-info-verified-size, 14px);\n height: var(--sv-video-info-verified-size, 14px);\n background: var(--sv-video-info-verified-bg, #20d5ec);\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.sv-video-info__verified-badge svg,\n.sv-video-info__verified-badge span {\n font-size: 10px;\n color: #fff;\n font-weight: 700;\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 * Caption\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-info__caption {\n font-size: var(--sv-video-info-caption-font-size, 14px);\n line-height: var(--sv-video-info-caption-line-height, 1.4);\n color: var(--sv-video-info-caption-color, #fff);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n}\n\n.sv-video-info__caption--lines-1 {\n -webkit-line-clamp: 1;\n}\n\n.sv-video-info__caption--lines-2 {\n -webkit-line-clamp: 2;\n}\n\n.sv-video-info__caption--lines-3 {\n -webkit-line-clamp: 3;\n}\n\n.sv-video-info__caption--expanded {\n -webkit-line-clamp: unset;\n}\n\n/* Clickable caption (for opening detail view) */\n.sv-video-info__caption--clickable {\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-video-info__caption--clickable:hover {\n opacity: 0.85;\n}\n\n.sv-video-info__caption--clickable:active {\n opacity: 0.7;\n}\n\n/* \"more\" button for expandable caption */\n.sv-video-info__caption-more {\n background: none;\n border: none;\n color: var(--sv-video-info-caption-more-color, rgba(255, 255, 255, 0.7));\n font-size: var(--sv-video-info-caption-font-size, 14px);\n padding: 0;\n margin-left: 4px;\n cursor: pointer;\n}\n\n.sv-video-info__caption-more:hover {\n color: var(--sv-video-info-caption-color, #fff);\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 * Hashtags\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-info__hashtags {\n display: inline-flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--sv-video-info-hashtag-gap, 6px);\n font-size: var(--sv-video-info-hashtag-font-size, 14px);\n}\n\n/* Inline variant - more compact */\n.sv-video-info__hashtags--inline {\n gap: var(--sv-video-info-hashtag-gap-inline, 4px);\n}\n\n.sv-video-info__hashtag {\n display: inline-flex;\n color: var(--sv-video-info-hashtag-color, #fff);\n font-weight: var(--sv-video-info-hashtag-font-weight, 500);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n transition: opacity 0.15s ease;\n white-space: nowrap;\n}\n\n.sv-video-info__hashtag:hover {\n opacity: 0.8;\n text-decoration: underline;\n}\n\n.sv-video-info__hashtag--not-clickable {\n cursor: default;\n}\n\n.sv-video-info__hashtag--not-clickable:hover {\n opacity: 1;\n text-decoration: none;\n}\n\n/* Inline hashtags (inside caption) */\n.sv-video-info__caption .sv-video-info__hashtag {\n display: inline;\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 * Location\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-info__location {\n display: flex;\n align-items: center;\n gap: var(--sv-video-info-location-gap, 4px);\n font-size: var(--sv-video-info-location-font-size, 13px);\n color: var(--sv-video-info-location-color, rgba(255, 255, 255, 0.9));\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-video-info__location:hover {\n opacity: 0.8;\n}\n\n.sv-video-info__location-icon {\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.sv-video-info__location-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\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\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-info__music {\n display: flex;\n align-items: center;\n gap: var(--sv-video-info-music-gap, 8px);\n font-size: var(--sv-video-info-music-font-size, 13px);\n color: var(--sv-video-info-music-color, #fff);\n cursor: pointer;\n transition: opacity 0.15s ease;\n overflow: hidden;\n}\n\n.sv-video-info__music:hover {\n opacity: 0.8;\n}\n\n.sv-video-info__music-icon {\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.sv-video-info__music-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n /* Marquee animation for long text */\n}\n\n/* Marquee animation for music text */\n.sv-video-info__music-text--marquee {\n animation: sv-video-info-marquee 8s linear infinite;\n}\n\n@keyframes sv-video-info-marquee {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(-50%);\n }\n}\n";
162
+ declare const VIDEO_INFO_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 * VideoInfo 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-info {\n display: flex;\n flex-direction: column;\n gap: var(--sv-video-info-gap, 6px);\n color: var(--sv-video-info-color, #fff);\n font-family: var(--sv-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n text-shadow: var(--sv-video-info-text-shadow, 0 1px 2px rgba(0, 0, 0, 0.5));\n max-width: 100%;\n overflow: hidden;\n \n /* Auto-hide transition */\n transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n /* Prevent text selection in webview */\n user-select: none;\n -webkit-user-select: none;\n}\n\n/* Hidden state for auto-hide */\n.sv-video-info--hidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Overlay variant (on top of video) */\n.sv-video-info--overlay {\n pointer-events: none;\n}\n\n.sv-video-info--overlay > * {\n pointer-events: auto;\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 Name\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-info__author {\n display: flex;\n align-items: center;\n gap: var(--sv-video-info-author-gap, 6px);\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-video-info__author:hover {\n opacity: 0.85;\n}\n\n.sv-video-info__author:active {\n opacity: 0.7;\n}\n\n.sv-video-info__author-name {\n font-size: var(--sv-video-info-author-font-size, 16px);\n font-weight: var(--sv-video-info-author-font-weight, 700);\n line-height: 1.3;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.sv-video-info__author-prefix {\n opacity: 0.95;\n}\n\n.sv-video-info__verified-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--sv-video-info-verified-size, 14px);\n height: var(--sv-video-info-verified-size, 14px);\n background: var(--sv-video-info-verified-bg, #20d5ec);\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.sv-video-info__verified-badge svg,\n.sv-video-info__verified-badge span {\n font-size: 10px;\n color: #fff;\n font-weight: 700;\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 * Caption\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-info__caption {\n font-size: var(--sv-video-info-caption-font-size, 14px);\n line-height: var(--sv-video-info-caption-line-height, 1.4);\n color: var(--sv-video-info-caption-color, #fff);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n}\n\n.sv-video-info__caption--lines-1 {\n -webkit-line-clamp: 1;\n}\n\n.sv-video-info__caption--lines-2 {\n -webkit-line-clamp: 2;\n}\n\n.sv-video-info__caption--lines-3 {\n -webkit-line-clamp: 3;\n}\n\n.sv-video-info__caption--expanded {\n -webkit-line-clamp: unset;\n}\n\n/* Clickable caption (for opening detail view) */\n.sv-video-info__caption--clickable {\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-video-info__caption--clickable:hover {\n opacity: 0.85;\n}\n\n.sv-video-info__caption--clickable:active {\n opacity: 0.7;\n}\n\n/* \"more\" button for expandable caption */\n.sv-video-info__caption-more {\n background: none;\n border: none;\n color: var(--sv-video-info-caption-more-color, rgba(255, 255, 255, 0.7));\n font-size: var(--sv-video-info-caption-font-size, 14px);\n padding: 0;\n margin-left: 4px;\n cursor: pointer;\n}\n\n.sv-video-info__caption-more:hover {\n color: var(--sv-video-info-caption-color, #fff);\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 * Hashtags\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-info__hashtags {\n display: inline-flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--sv-video-info-hashtag-gap, 6px);\n font-size: var(--sv-video-info-hashtag-font-size, 14px);\n}\n\n/* Inline variant - more compact */\n.sv-video-info__hashtags--inline {\n gap: var(--sv-video-info-hashtag-gap-inline, 4px);\n}\n\n.sv-video-info__hashtag {\n display: inline-flex;\n color: var(--sv-video-info-hashtag-color, #fff);\n font-weight: var(--sv-video-info-hashtag-font-weight, 500);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n transition: opacity 0.15s ease;\n white-space: nowrap;\n}\n\n.sv-video-info__hashtag:hover {\n opacity: 0.8;\n text-decoration: underline;\n}\n\n.sv-video-info__hashtag--not-clickable {\n cursor: default;\n}\n\n.sv-video-info__hashtag--not-clickable:hover {\n opacity: 1;\n text-decoration: none;\n}\n\n/* Inline hashtags (inside caption) */\n.sv-video-info__caption .sv-video-info__hashtag {\n display: inline;\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 * Location\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-info__location {\n display: flex;\n align-items: center;\n gap: var(--sv-video-info-location-gap, 4px);\n font-size: var(--sv-video-info-location-font-size, 13px);\n color: var(--sv-video-info-location-color, rgba(255, 255, 255, 0.9));\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-video-info__location:hover {\n opacity: 0.8;\n}\n\n.sv-video-info__location-icon {\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.sv-video-info__location-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\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\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-info__music {\n display: flex;\n align-items: center;\n gap: var(--sv-video-info-music-gap, 8px);\n font-size: var(--sv-video-info-music-font-size, 13px);\n color: var(--sv-video-info-music-color, #fff);\n cursor: pointer;\n transition: opacity 0.15s ease;\n overflow: hidden;\n}\n\n.sv-video-info__music:hover {\n opacity: 0.8;\n}\n\n.sv-video-info__music-icon {\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.sv-video-info__music-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n /* Marquee animation for long text */\n}\n\n/* Marquee animation for music text */\n.sv-video-info__music-text--marquee {\n animation: sv-video-info-marquee 8s linear infinite;\n}\n\n@keyframes sv-video-info-marquee {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(-50%);\n }\n}\n";
163
163
 
164
164
  export { VIDEO_INFO_CSS, VideoAuthorName, type VideoAuthorNameProps, VideoCaption, type VideoCaptionProps, VideoHashtags, type VideoHashtagsProps, VideoInfoContext, type VideoInfoContextValue, VideoInfoHeadless, type VideoInfoHeadlessExtendedProps, VideoLocation, type VideoLocationProps, VideoMusic, type VideoMusicProps, useOptionalVideoInfoContext, useVideoInfoContext };
@@ -1 +1 @@
1
- export { VIDEO_INFO_CSS, VideoAuthorName, VideoCaption, VideoHashtags, VideoInfoContext, VideoInfoHeadless, VideoLocation, VideoMusic, useOptionalVideoInfoContext, useVideoInfoContext } from '../../chunk-7WXAQHJI.js';
1
+ export { VIDEO_INFO_CSS, VideoAuthorName, VideoCaption, VideoHashtags, VideoInfoContext, VideoInfoHeadless, VideoLocation, VideoMusic, useOptionalVideoInfoContext, useVideoInfoContext } from '../../chunk-4WTGO44D.js';
@@ -27,6 +27,18 @@ interface VideoSlotHeadlessExtendedProps extends VideoSlotHeadlessProps {
27
27
  loopCount?: number;
28
28
  /** Custom styles */
29
29
  style?: React.CSSProperties;
30
+ /**
31
+ * Disable long-press speed boost gesture.
32
+ * When true, holding won't trigger 2x speed.
33
+ * @default false
34
+ */
35
+ disableSpeedBoost?: boolean;
36
+ /** Speed multiplier for speed boost (default: 2) */
37
+ speedBoostSpeed?: number;
38
+ /** Hold delay in ms before speed boost activates (default: 2000) */
39
+ speedBoostHoldDelay?: number;
40
+ /** Pull-down distance in px to trigger speed lock (default: 50) */
41
+ speedBoostPullDownThreshold?: number;
30
42
  }
31
43
  /**
32
44
  * VideoSlotHeadless Component
@@ -59,7 +71,7 @@ interface VideoSlotHeadlessExtendedProps extends VideoSlotHeadlessProps {
59
71
  *
60
72
  * Wrapped with React.memo to prevent unnecessary re-renders.
61
73
  */
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;
74
+ declare function VideoSlotHeadlessBase({ video, resourceState, playerState, playerControls, className, children, onVisible: _onVisible, onHidden: _onHidden, onTap, onDoubleTap, onLongPress, disableTap, renderError, renderLoading, restoreFrame, onSpeedBoost, onSpeedReset, onSpeedLock, style, disableSpeedBoost, speedBoostSpeed, speedBoostHoldDelay, speedBoostPullDownThreshold, }: VideoSlotHeadlessExtendedProps): React.ReactElement;
63
75
  /**
64
76
  * VideoSlotHeadless - Memoized for performance
65
77
  *
@@ -1,2 +1,2 @@
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-6JOXPX7S.js';
2
- export { VideoSlotContext, VideoSlotPlayIndicator, VideoSlotPlayIndicatorInner, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from '../../chunk-VS54DRIS.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-YPSLSX7P.js';
2
+ export { VideoSlotContext, VideoSlotPlayIndicator, VideoSlotPlayIndicatorInner, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from '../../chunk-3LINB7GV.js';
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  export { Skeleton, SkeletonAvatar, SkeletonText, SkeletonVideo } from './chunk-4RIMQOBR.js';
2
2
  export { DEFAULT_SPEEDS, SPEED_PICKER_CSS, SpeedPickerHeadless } from './chunk-QCRRF76W.js';
3
- export { VIDEO_INFO_CSS, VideoAuthorName, VideoCaption, VideoHashtags, VideoInfoContext, VideoInfoHeadless, VideoLocation, VideoMusic, useOptionalVideoInfoContext, useVideoInfoContext } from './chunk-7WXAQHJI.js';
3
+ export { VIDEO_INFO_CSS, VideoAuthorName, VideoCaption, VideoHashtags, VideoInfoContext, VideoInfoHeadless, VideoLocation, VideoMusic, useOptionalVideoInfoContext, useVideoInfoContext } from './chunk-4WTGO44D.js';
4
4
  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, 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, VideoPlayerHeadless, createFirstFrameCache, firstFrameCache, useAutoFirstFrameCapture, useFirstFrameCapture, useVideoElement } from './chunk-OM4L7RE5.js';
5
- export { LOADING_ATTR, LOADING_DATASET_KEY, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, ReportedVideoOverlay, 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-6JOXPX7S.js';
5
+ export { LOADING_ATTR, LOADING_DATASET_KEY, PLAYER_STATE_ATTR, PLAYER_STATE_DATASET_KEY, ReportedVideoOverlay, 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-YPSLSX7P.js';
6
6
  export { ZOOMABLE_CONTAINER_CSS, ZoomableContainer } from './chunk-TJCPW4AO.js';
7
7
  export { DETAIL_VIEW_CSS, DetailViewAuthor, DetailViewCaption, DetailViewGallery, DetailViewHeadless, DetailViewMusic, DetailViewStats, useDetailViewContext } from './chunk-BADA7OLG.js';
8
8
  export { ErrorBoundary } from './chunk-IWSBYOSS.js';
@@ -12,13 +12,13 @@ export { PlaylistBarHeadless, PlaylistCollectionHeadless, PlaylistSheetHeadless
12
12
  export { PROGRESS_BAR_CSS, ProgressBarHeadless, calculateProgress, formatTime } from './chunk-VXW7AOGM.js';
13
13
  export { QUALITY_PICKER_CSS, QualityPickerHeadless } from './chunk-DR7KR7OT.js';
14
14
  export { REPORT_SHEET_CSS, ReportSheetHeadless, injectReportSheetCSS } from './chunk-DGKMO3AE.js';
15
- export { ACTION_BAR_CSS, CompoundBookmark as ActionBarBookmark, CompoundComment as ActionBarComment, ActionBarHeadless, CompoundLike as ActionBarLike, CompoundShare as ActionBarShare, ActionButton, BookmarkButton, CommentButton, LikeButton, ShareButton } from './chunk-NJXIYSDZ.js';
15
+ export { ACTION_BAR_CSS, CompoundBookmark as ActionBarBookmark, CompoundComment as ActionBarComment, ActionBarHeadless, CompoundLike as ActionBarLike, CompoundShare as ActionBarShare, ActionButton, BookmarkButton, CommentButton, LikeButton, ShareButton } from './chunk-C27FC7E2.js';
16
16
  export { ADVANCE_MENU_CSS, AdvanceMenuHeadless } from './chunk-HXQPEZRG.js';
17
- export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, ArticleSlotBottom, ArticleSlotCaption, ArticleSlotHeadless, ArticleSlotMusic, ArticleSlotOverlay, ArticleSlotPlayIndicator, ArticleSlotReadMore, 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, ArticleSlotBottom as ImagePostSlotBottom, ArticleSlotCaption as ImagePostSlotCaption, ArticleSlotHeadless as ImagePostSlotHeadless, ArticleSlotMusic as ImagePostSlotMusic, ArticleSlotOverlay as ImagePostSlotOverlay, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, ArticleSlotReadMore as ImagePostSlotReadMore, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext } from './chunk-TX3D3C2M.js';
18
- export { VideoSlotContext, VideoSlotPlayIndicator, useDoubleTap, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from './chunk-VS54DRIS.js';
17
+ export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, ArticleSlotBottom, ArticleSlotCaption, ArticleSlotHeadless, ArticleSlotMusic, ArticleSlotOverlay, ArticleSlotPlayIndicator, ArticleSlotReadMore, 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, ArticleSlotBottom as ImagePostSlotBottom, ArticleSlotCaption as ImagePostSlotCaption, ArticleSlotHeadless as ImagePostSlotHeadless, ArticleSlotMusic as ImagePostSlotMusic, ArticleSlotOverlay as ImagePostSlotOverlay, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, ArticleSlotReadMore as ImagePostSlotReadMore, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext } from './chunk-OTCSGHTG.js';
18
+ export { VideoSlotContext, VideoSlotPlayIndicator, useDoubleTap, useOptionalVideoSlotContext, useVideoSlotContext, useVideoSlotIsActive, useVideoSlotIsPlaying, useVideoSlotPlayer, useVideoSlotResource, useVideoSlotVideo } from './chunk-3LINB7GV.js';
19
19
  export { usePinchZoom } from './chunk-UTLVQ3FL.js';
20
20
  export { IMAGE_CAROUSEL_CSS, ImageCarouselHeadless } from './chunk-GSNIZ6DF.js';
21
- export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext } from './chunk-3OB3OVYR.js';
21
+ export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext } from './chunk-26KDWJRI.js';
22
22
  export { BookmarkFilledIcon, BookmarkIcon, CloseIcon, CommentIcon, HeartFilledIcon, HeartIcon, MoreIcon, MusicIcon, PauseIcon, PlayIcon, PlusIcon, ShareIcon, UserCheckIcon, UserPlusIcon, VerifiedIcon, VolumeIcon, VolumeMutedIcon } from './chunk-ANCP53F3.js';
23
23
  export { CLEAN_MODE_OVERLAY_CSS, CleanModeOverlayHeadless, injectCleanModeOverlayCSS } from './chunk-QUEJHA24.js';
24
24
  export { clsx, clsx2 as cn } from './chunk-EDWS2IPH.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xhub-short/ui",
3
- "version": "1.0.0-beta.21",
3
+ "version": "1.0.0-beta.23",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -73,7 +73,7 @@
73
73
  ],
74
74
  "dependencies": {
75
75
  "clsx": "^2.1.0",
76
- "@xhub-short/contracts": "1.0.0-beta.21"
76
+ "@xhub-short/contracts": "1.0.0-beta.23"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "react": "^19.0.0",
@@ -97,8 +97,8 @@
97
97
  "tsup": "^8.3.0",
98
98
  "typescript": "^5.7.0",
99
99
  "vitest": "^2.1.0",
100
- "@xhub-short/tsconfig": "0.0.1-beta.2",
101
- "@xhub-short/vitest-config": "0.1.0-beta.13"
100
+ "@xhub-short/tsconfig": "0.1.0-beta.3",
101
+ "@xhub-short/vitest-config": "0.1.0-beta.14"
102
102
  },
103
103
  "scripts": {
104
104
  "build": "tsup",