@minicode-dev/chat 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/chunks/{BattleshipGameCard-8H-sBCsv.js → BattleshipGameCard-DwNzgH5G.js} +199 -199
  3. package/dist/chunks/{BattleshipGameCard-8H-sBCsv.js.map → BattleshipGameCard-DwNzgH5G.js.map} +1 -1
  4. package/dist/chunks/{BattleshipPrototype-CmQd5AUO.js → BattleshipPrototype-CSQxQJt5.js} +52 -52
  5. package/dist/chunks/{BattleshipPrototype-CmQd5AUO.js.map → BattleshipPrototype-CSQxQJt5.js.map} +1 -1
  6. package/dist/chunks/{ChatContext-CVW58bzC.js → ChatContext-D5rqvt5D.js} +2 -2
  7. package/dist/chunks/{ChatContext-CVW58bzC.js.map → ChatContext-D5rqvt5D.js.map} +1 -1
  8. package/dist/chunks/RacingLiveGameCard-_wvhDRlG.js +1873 -0
  9. package/dist/chunks/RacingLiveGameCard-_wvhDRlG.js.map +1 -0
  10. package/dist/chunks/{TanksGameCard-DnCufSH6.js → TanksGameCard-B-gtDYYg.js} +137 -137
  11. package/dist/chunks/{TanksGameCard-DnCufSH6.js.map → TanksGameCard-B-gtDYYg.js.map} +1 -1
  12. package/dist/chunks/{TanksLiveGameCard-D_27Jomp.js → TanksLiveGameCard-DXgd1J2Y.js} +392 -392
  13. package/dist/chunks/{TanksLiveGameCard-D_27Jomp.js.map → TanksLiveGameCard-DXgd1J2Y.js.map} +1 -1
  14. package/dist/chunks/{avalancheScene3d-CIE2WKQn.js → avalancheScene3d-CNbQyGUd.js} +2 -2
  15. package/dist/chunks/{avalancheScene3d-CIE2WKQn.js.map → avalancheScene3d-CNbQyGUd.js.map} +1 -1
  16. package/dist/chunks/{connect4Sounds-BqEHULjv.js → connect4Sounds-3a6h7gUC.js} +8 -8
  17. package/dist/chunks/{connect4Sounds-BqEHULjv.js.map → connect4Sounds-3a6h7gUC.js.map} +1 -1
  18. package/dist/chunks/createLiveScene-jrzyQogh.js +756 -0
  19. package/dist/chunks/{createLiveScene-MTGRv8rx.js.map → createLiveScene-jrzyQogh.js.map} +1 -1
  20. package/dist/chunks/createRaceScene-C-aw0dlX.js +291 -0
  21. package/dist/chunks/createRaceScene-C-aw0dlX.js.map +1 -0
  22. package/dist/chunks/{createTankScene-yhX6la27.js → createTankScene-6asWHKFf.js} +123 -125
  23. package/dist/chunks/{createTankScene-yhX6la27.js.map → createTankScene-6asWHKFf.js.map} +1 -1
  24. package/dist/chunks/fx-BNJvJYOu.js +871 -0
  25. package/dist/chunks/fx-BNJvJYOu.js.map +1 -0
  26. package/dist/chunks/{games-Bl_8raG6.js → games-D_9SiSBT.js} +708 -697
  27. package/dist/chunks/games-D_9SiSBT.js.map +1 -0
  28. package/dist/chunks/tank-DIn6Jyt8.js +605 -0
  29. package/dist/chunks/tank-DIn6Jyt8.js.map +1 -0
  30. package/dist/chunks/{tanks-live-BcKmrhnV.js → tanks-live-BRhYW4MG.js} +36 -36
  31. package/dist/chunks/{tanks-live-BcKmrhnV.js.map → tanks-live-BRhYW4MG.js.map} +1 -1
  32. package/dist/chunks/{tanksSounds-DTnidbiq.js → tanksSounds-tYPzje61.js} +4 -4
  33. package/dist/chunks/{tanksSounds-DTnidbiq.js.map → tanksSounds-tYPzje61.js.map} +1 -1
  34. package/dist/chunks/track-C1TWWT19.js +557 -0
  35. package/dist/chunks/track-C1TWWT19.js.map +1 -0
  36. package/dist/index.js +4234 -4018
  37. package/dist/index.js.map +1 -1
  38. package/dist/styles.css +1 -1
  39. package/index.d.ts +2 -0
  40. package/package.json +1 -1
  41. package/dist/chunks/RacingLiveGameCard-8j9QLnxW.js +0 -1654
  42. package/dist/chunks/RacingLiveGameCard-8j9QLnxW.js.map +0 -1
  43. package/dist/chunks/createLiveScene-MTGRv8rx.js +0 -758
  44. package/dist/chunks/createRaceScene-BiEtQsVs.js +0 -306
  45. package/dist/chunks/createRaceScene-BiEtQsVs.js.map +0 -1
  46. package/dist/chunks/decor-CyyCnmct.js +0 -418
  47. package/dist/chunks/decor-CyyCnmct.js.map +0 -1
  48. package/dist/chunks/fx-1ZwzmPWj.js +0 -458
  49. package/dist/chunks/fx-1ZwzmPWj.js.map +0 -1
  50. package/dist/chunks/games-Bl_8raG6.js.map +0 -1
  51. package/dist/chunks/rolldown-runtime-CGnMp29N.js +0 -10
  52. package/dist/chunks/tank-DjEQ4FXF.js +0 -553
  53. package/dist/chunks/tank-DjEQ4FXF.js.map +0 -1
  54. package/dist/chunks/track-BcnnpnAm.js +0 -259
  55. package/dist/chunks/track-BcnnpnAm.js.map +0 -1
  56. package/dist/chunks/util-DwI9bfS7.js +0 -57
  57. package/dist/chunks/util-DwI9bfS7.js.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["MAX_EMOJI_LENGTH","pending","read","identity","prefersReducedMotion","prefersReducedMotion","_Fragment","key","_Fragment","ERROR_MESSAGE","PREVIEW_SIZES","FULL_SIZES","categoriesCache","normalizeItem","request","toPage","pageParams","PRESENCE_TEXT","PRESENCE_TEXT","_Fragment","safeUrl","File","_Fragment","identity","STORAGE_KEY","hasWindow","cleanList","readStorage","writeStorage","_Fragment","prefersReducedMotion","ReactionBar","GameCard","ConnectedGameCard","keyOf","hasWindow","prefersReducedMotion","_Fragment","PER_PAGE","SEARCH_DEBOUNCE_MS","GifCategoryBar","_Fragment","_Fragment","_Fragment","ConnectedGameCard","ChatWindow","_Fragment","createStore","ChatWindowShell","ChatWindowShell","rtcSignals","useChatGames","createChatSignaling","isGameMessage","randomUuid","getChatAssetsBaseUrl","setChatAssetsBaseUrl","chatSoundUrl","WEBRTC_PREFIX","isWebrtcMessage","MAX_SIGNAL_LENGTH","createPeerLink","decodeSignal","encodeSignal","DEFAULT_ICE_SERVERS","requestNotification","isSoundEnabled","useChatContext","subscribeSoundPreference","initChatSounds","toggleSound","ChatContext","boltFlicker","THUNDER_CUES","THUNDER_DURATION_MS","setChatConnectionStatus","useChatConnectionStatus","chatConnectionStore","isBattleshipGame","isTerminalGame","sameUser","getGameTitle","isLiveGame","getShortGameStatus","isTanksGame","getGameStatus","startConnect4Sounds","isConnect4SoundsRunning","GameSoundControls","settleConnect4Drop","connect4Sounds","withSignalFaults","createStore$1","File$1","dayjs","noop","DEFAULT_CONFIG","isPlainObject","value","normalizeUser","user","id","ids","uniqueIds","name","SECTIONS","SCALARS","mergeSection","defaults","merged","key","entry","normalizeConfig","input","config","result","section","detach","callbacks","OPEN","DEFAULT_TIMEOUT_MS","defaultIsFatal","frame","idCounter","newId","withToken","token","tokenParam","url","createStandaloneTransport","maxRetries","reconnect","baseMs","capMs","pingAction","ping","pingEvery","socket","connectionId","status","attempts","fatal","voluntary","connecting","retryTimer","pingTimer","handlers","statusListeners","pending","setStatus","next","prev","err","rejectAll","timer","reject","message","clearRetry","stopPing","startPing","send","scheduleReconnect","delay","connect","settle","body","ev","dispatch","h","resolveUrl","base","getToken","WebSocketImpl","target","opened","ws","resolve","msg","isFatal","evt","close","code","payload","request","request_id","timeoutMs","action","handler","cb","identity","PREFIX","SEEN_LIMIT","record","safeTime","unreadStorageKey","scope","unreadScope","userId","backend","dictionary","empty","mergeUnread","first","second","readThrough","source","room","time","unread","seen","rooms","entries","info","b","a","unreadCounts","ledger","messages","totalUnread","state","total","count","normalizeChatMessage","envelope","fingerprint","index","parseServerTime","unreadCandidate","text","ownIds","connectedAt","browserStorage","createUnreadStore","read","storage","save","store","createStore","commit","get","set","candidate","roomId","times","latest","stopStorageSync","onStorage","event","stop","unreadStore","useChatUnread","useStore","selector","startUnreadStorageSync","EDIT_PREFIX","REACT_PREFIX","MAX_EDIT_LENGTH","MAX_EMOJI_LENGTH$1","MAX_TRACKED","STICKER_NAME_PREFIX","isStickerAttachment","item","stickerTitle","isMessageAction","messageId","encodeEdit","targetId","encodeReaction","emoji","on","parseMessageAction","edit","data","bounded","keys","map","messageExtrasStore","author","frameId","original","previous","current","users","nextForMessage","useChatMessageExtras","groupReactions","own","byEmoji","findLastOwnEditable","preferenceKey","previewKey","channel","activeNotifications","pending$1","conversation","read$1","desktopSettings","supported","setDesktopPreviews","toggleDesktopNotifications","settings","enabled","setDesktopConversation","isVisible","onChannelMessage","pause","ms","clearDesktopNotifications","notification","notifyDesktopMessage","visible","query","isCurrent","show","storageKey","previews","sender","onClick","closeDisplayed","desktopUsers","startDesktopNotifications","stopped","MAX_CHAT_MESSAGES","PRESENCE_STATUSES","MANUAL_STATUSES","initialPresence","STALE_REPLY_MS","SEARCH_TIMEOUT_MS","PRESENCE_SYNC_MS","ACTIVITY_EVENTS","initialChatState","normalizeUsers","byId","rememberUsers","known","revokeBlobs","attachment","appendBounded","nextItems","items","fileBytes","sum","file","retainedBytes","limit","removed","createChatStore","chatGamesStore","transport","getOwnIds","isOpen","session","newSession","live","s","pruneStale","now","search","releaseUserSearch","stale","pumpUserSearch","startActivityTracker","lastSentAt","lastInputAt","sendActivity","onInput","onVisibility","options","interval","endSession","startSession","onStatus","games","receiveMessage","ownId","senderId","parsed","isIncoming","roomKey","parts","otherId","nested","gameMessage","gameText","maxMessages","isOptimistic","liveIncoming","msgId","onOpenChat","handleFrame","eventType","kind","type","groups","group","rawId","i","room_id","recipient_user_id","from_user_id","errorBody","errorAction","offEvent","offStatus","extras","kindOf","presence","onlineUsers","manual","sendMessage","attachments","tab","recipientUserId","noopUnsubscribe","IDLE","useChatConfig","useChatTransport","identity$2","useChatStore","chatStore","useChatStoreApi","readStatus","raw","readConnectionId","useChatConnection","subscribe","useCallback","unsubscribe","notify","useSyncExternalStore","sumCounts","counts","useChatUnreadTotal","valid","getSnapshot","useChatIdentity","fromTransport","idsKey","useMemo","list","CONFETTI_DURATION_MS","CONFETTI_CUES","AVALANCHE_DURATION_MS","AVALANCHE_CUES","EFFECT_CATALOG","getChatEffect","effect","RECORDINGS","playEffectSound","recording","effectId","audio","reported","failed","onBlocked","playing","onPlaying","volume","rand","min","max","jagged","points","x1","y1","x2","y2","pass","passes","ax","ay","bx","by","length","spread","createThunderScene2d","ctx","canvas","width","height","flash","bolts","sparks","path","x","y","startX","endX","endY","main","branches","power","dt","bolt","opacity","branch","scale","spark","t","ratio","nextWidth","nextHeight","SHAKE_STEPS","shake","frames","k","step","ThunderEffect","hostRef","useRef","flashRef","useEffect","host","reducedMotion","mountedAt","animations","scene","disposed","last","track","animation","mount","factory","fallback","createThunderScene","elapsed","audioTime","clockRef","wall","waitForAudio","fire","targetRef","tick","observer","prefersReducedMotion$4","ConfettiEffect","useFallback","setUseFallback","useState","lastTime","onContextLost","createConfettiScene","peak","cue","seeded","seed","KINDS","CUE_MIX","LAND","BINS","buildLayout","range","pieces","gusts","tanks","mix","at","cueIndex","heights","half","piece","from","to","finale","LAYOUT","AvalancheFallback","startMs","still","p","g","f","prefersReducedMotion$3","flashOf","AvalancheEffect","fallbackAt","setFallbackAt","toFallback","createAvalancheScene","CONFETTI","Pig","confettiFallback","EffectScene","Fragment","sound","EffectPlayer","closeRef","onClose","blocked","setBlocked","fallDistance","setFallDistance","update","onKey","player","createPortal","EFFECT_PREFIX","COUNTDOWN_PREFIX","validCountdown","IDS","createEffectId","crypto","encodeEffect","sentAt","label","endsAt","decodeEffect","prefix","effectMessageText","foreground","preferences","key$1","setForegroundRoom","isForegroundRoom","setEffectPreferences","getEffectPreferences","rememberBackgroundEffect","takeBackgroundEffect","maxAgeMs","EffectsContext","createContext","subscribeVisibility","listener","isPageVisible","claimAutoEffect","recent","ChatEffects","globalSound","pageVisible","active","setActive","setSound","auto","setAuto","lastAuto","play","eventSound","replace","changed","age","currentUserIds","identityScope","release","missed","timers","children","CountdownCard","setNow","mountedBeforeEnd","seconds","done","burst","context","EffectCard","useContext","EffectPicker","countdown","setCountdown","duration","setDuration","customDuration","setCustomDuration","customValue","setCustomValue","customUnit","setCustomUnit","finalEffect","setFinalEffect","countdownSound","setCountdownSound","sending","setSending","feedback","setFeedback","mounted","pickerRef","latestContext","closeOutside","durationSeconds","validDuration","selectedEffect","durationLabel","disabled","timed","sessionKey","onSend","error","Sparkles","X","sent","Icon","Zap","PartyPopper","Rocket","subtitle","Loader2","jsx","Check","ArrowUpRight","unit","Volume2","VolumeX","Play","CLAIM_DELAY_MS","field","BackgroundEffects","lastByRoom","consider","effects","picker","LiraChatProvider","injectedTransport","injectedChatStore","normalized","configRef","ownedTransport","websocket","auth","ownedChatStore","onConnectionChange","stores","TRANSPORT_STATUSES","REQUIRED_METHODS","assertTransport","obj","missing","CUSTOMER_ID_KEY","memoryCustomerId","randomId","bytes","hex","getKlipyCustomerId","stored","configureKlipy","apiKey","locale","categoriesLocale","getApiKey","getKlipyApiRoot","getBaseUrl","ERROR_MESSAGE$1","TRUSTED_HOSTS","PREVIEW_SIZES$1","FULL_SIZES$1","getKlipyLocale","getKlipyCategoriesLocale","categoriesCache$1","isTrustedKlipyUrl","pickGif","size","sizes","media","toDimension","n","normalizeItem$1","full","preview","tag","request$1","params","response","toPage$1","json","hasNext","perPage","pageParams$1","page","withCountryLocale","toCategoriesLocale","lang","country","fetchTrendingGifs","signal","searchGifsPage","q","fetchRecentGifs","fetchGifCategories","apiLocale","cacheKey","categories","category","shareGif","slug","normalize","useChatTextSize","setSize","sync","FOCUSABLE","useFocusTrap","autoFocus","ref","nodes","node","DEFAULT_INITIAL","DEFAULT_MIN","RESIZE_KEYS","useResizable","startRef","initial","isResizing","setResizing","targetRect","constrainSize","onPointerDown","rect","onPointerMove","start","endResize","PRESENCE_TEXT$2","ChatHeader","isPrivate","privateSubtitle","secondary","notificationRef","desktop","setDesktop","soundEnabled","setSoundEnabled","onToggleSidebar","showSidebar","PanelLeft","title","Hash","Bell","BellOff","textSize","onTextSizeChange","RotateCcw","onDetach","ExternalLink","onInstall","Download","onMinimize","Minimize2","onMaximize","isMaximized","onRestore","Maximize2","PRESENCE_TEXT$1","ConversationItem","isPerson","conv","typeClass","statusHidden","presenceText","selected","onSelect","User","ConversationList","conversations","MessageCircle","selectedId","PRESENCE_LABELS","StatusMenu","open","setOpen","rootRef","buttonRef","onKeyDown","select","onChange","option","userIdOf","displayName","PRESENCE_TEXT","secondaryOf","buildConversations","convs","privateRooms","c","knownUsers","u","presenceById","ChatSidebar","setQuery","searchQuery","groupName","setGroupName","creating","setCreating","onSearch","selfIds","currentUserId","isSelf","peers","found","searchResults","onlySelf","renderUser","explicitOnline","connected","online","onSelectUser","onSetPresence","currentUserName","myPresence","onCreateGroup","presenceStatus","searchStatus","ChatEmptyState","customEmojis","CUSTOM_EMOJI_NAME","rasterData","isCustomEmojiUrl","origin","normalizeCustomEmojis","names","searchCustomEmojis","folded","records","useCustomEmojis","catalog","InlineEmoji","setFailed","MessageText","part","safeUrl$1","fileSize","clock","VoicePlayer","audioRef","setPlaying","position","setPosition","playError","setPlayError","updateDuration","Pause","Mic","AttachmentCard","mime","sticker","visual","available","extension","FileArchive","FileSpreadsheet","FileText","history","onExpand","AlertCircle","onRemove","MediaPreview","activeImage","setActiveImage","previousFocus","VIDEO_ID","HOSTS","parseYouTubeUrl","suffix","findYouTubeVideo","candidates","video","YouTubePreview","loadSources","modules","mod","EMOJI_SHORTCUTS","SPANISH_ALIASES","normalizeEmojiQuery","TONE_RE","identity$1","baseIdentity","asList","capitalize","compact","COMPONENT_GROUP","SKIN_TONES","buildCategories","emojiCategories","legacyByEmoji","alias","curatedByEmoji","toneOfHex","tones","hexcode","tone","buildSkins","byTone","skin","skins","buildUnicodeIndex","spanishByHex","spanish","english","localized","primary","githubShortcodes","emojibaseShortcodes","iamcalShortcodes","curated","shortcodes","shortcode","labelEs","keywords","customIndex","words","setOnce","buildState","primaryAliases","unicodeIndex","searchData","aliases","labels","word","keyword","aliasMap","labelMap","termMap","term","customByCode","loaded","loading","listeners","isEmojiDataLoaded","subscribeEmojiData","loadEmojiData","ensureEmojiData","TIER","NO_MATCH","scoreWord","best","scoreQuery","score","worst","searchEmojiShortcodes","results","getEmojisByCategory","getEmojiRecord","applySkinTone","itemOrEmoji","level","resolveEmojiShortcode","STORAGE_KEY$1","LEGACY_RECENTS_KEY","MAX_EMOJI_LENGTH","hasWindow$2","CONTROL_CHARS","sanitizeEmoji","sanitizeSkinTone","cleanList$1","out","EMPTY","parse","readStorage$1","writeStorage$1","migrateLegacy","wrote","legacy","recents","createEmojiPreferencesStore","favorites","rest","syncRefs","migrated","emojiPreferencesStore","useEmojiPreferences","startEmojiPreferencesSync","useEmojiDataReady","ready","categoryIcons","Clock","Star","Smile","Hand","Puzzle","PawPrint","Utensils","Car","Trophy","Lightbulb","Heart","Flag","CELL_SIZE","ESTIMATED_COLUMNS","LONG_PRESS_MS","resolveRecord","customRecords","EmojiCell","memo","longPressed","clear","favorite","onPreview","onToggleFavorite","onPick","EmojiSection","cellProps","setVisible","lazy","minHeight","EmojiPicker","skinTone","addRecent","toggleFavorite","setSkinTone","emojiReady","toneOpen","setToneOpen","activeSection","setActiveSection","setPreview","bodyRef","searchRef","scrollFrame","favoriteSet","toValue","trimmed","sections","wrap","firstItem","shown","updateActive","top","scrollToSection","focusCell","cell","columnsOf","cells","grid","onBodyKeyDown","grids","all","gridIndex","cols","prevCols","lastRowStart","currentTone","navTabs","previewFav","previewCode","QUICK_REACTIONS","ReactionPicker","setFull","quickRef","onCloseRef","handlePointerDown","choose","align","buttons","Plus","ChatPeopleContext","useChatPeople","MAX_NAMES","BUMP_MS","prefersReducedMotion$2","ReactionBar","ownIdList","bumped","setBumped","prevCounts","grown","reactions","copy","nameOf","resolveName","titleFor","userIds","mine","onToggle","ReactionBar_default","MessageBubble","quoteUnavailable","setQuoteUnavailable","copyState","setCopyState","pickerOpen","setPickerOpen","reactBtnRef","quote","date","timestamp","validDate","isSticker","hasReactions","closePicker","bubbleClass","isMine","isEditing","senderName","onJumpQuote","onReact","v","SmilePlus","onEdit","Pencil","onReply","Reply","onCopy","Copy","createGamePanelStore","minimized","gamePanelStore","useGamePanelStore","SyncControls","onAdoptOffer","onResync","GameCard","isHost","game","isGuest","isParticipant","myTurn","controlsDisabled","canMove","terminal","board","variant","soundControls","ChevronDown","onDismiss","column","onMove","ArrowDown","row","occupied","owner","rowIndex","winning","col","onDropSettled","onAccept","onDecline","onRetry","GameCard_default","_typeof","o","toPrimitive","e","r","toPropertyKey","_defineProperty","LAZY_CARDS","lazyCards","lazyCard","LazyCardFallback","LazyCardErrorBoundary","Component","_args","ConnectedGameCard","gameKey","Card","Suspense","act","run","ConnectedGameCard_default","GameTimelineEntry","inPanel","Gamepad2","validTime","MessageList","scrollRef","nearBottom","hasNew","setHasNew","scrollToBottom","prevLength","grew","editingId","Paperclip","previousTimed","sameDay","gap","grouped","occurrence","panelGameKey","onEditMessage","matches","LIMIT_SECONDS","useVoiceRecorder","setSeconds","setError","sessionRef","mountedRef","callbackRef","onRecorded","finish","cancelled","stream","mimeType","recorder","blob","failure","MAX_VARIANTS","STOPWORDS","SPORTS_TERMS","AVOID_TERMS","PHRASE_RULES","WORDS","EN_WORDS","normalizeQuery","tokenize","kept","squash","lev","j","cur","rowMin","COMPILED_RULES","findRule","padded","bestScore","rule","translateWord","uniq","arr","expandGifQuery","tokens","isEnglish","translated","enPhrase","idx","variants","push","match","intent","sports","factor","exact","en","hasMeme","RANK_DECAY","TITLE_PHRASE","TAG_PHRASE","TITLE_TOKEN","TAG_TOKEN","PARTIAL_PHRASE","AVOID_PENALTY","EMPTY_PENALTY","PROTECT_TOP","PROTECT_SLACK","norm","keyOf$1","prepareTerms","prep","intentTerms","avoidTerms","prepareItem","tags","tagText","intentMatch","bonus","matched","doc","hits","tk","scoreWith","prior","rank","variantWeight","terms","rankGifs","expansion","noIntent","seq","weight","protectedRank","gi","sorted","pinned","maxIdx","hasGoodResults","STORAGE_KEY","hasWindow$1","safeUrl","dimension","sanitizeItem","savedAt","cleanList","readStorage","writeStorage","idOf","createGifLibraryStore","gifLibraryStore","useGifLibrary","startGifLibrarySync","CACHE_TTL_MS","CACHE_MAX","MAX_VARIANTS_PAGE1","MAX_VARIANTS_NEXT","APPROX_NOTICE","cache","inflight","makeAbortError","isAbortError","cacheGet","cacheSet","cachedRequest","hit","controller","fetcher","shared","settled","onAbort","keyOf","normalizeResult","res","loadTrending","loadVariant","pickVariants","picked","originalNorm","orig","loadSearch","firstError","hasMore","notice","loadRecent","local","loadFavorites","favs","loadGifFeed","DEFAULT_CATEGORY_ID","GIF_CATEGORIES","Flame","Laugh","Frown","Angry","Eye","HandHeart","Music","CATEGORY_SYNONYMS","safeNormalize","matchKeys","findKlipyMatch","klipyCategories","mergeKlipyCategories","klipy","cat","kq","prefersReducedMotion$1","GifCategoryBar","scrollerRef","chipRefs","canPrev","setCanPrev","canNext","setCanNext","updateOverflow","el","ro","onWheel","before","chip","activeId","scrollByPage","dir","handleKeyDown","hasActive","ChevronLeft","focusable","ChevronRight","GifCategoryBar_default","WIDE_BREAKPOINT","PREVIEW_DELAY","SKELETON_RATIOS","ratioOf","w","distribute","columns","getRatio","prefersReducedMotion","isFocusVisible","GifTile","setLoaded","broken","setBroken","previewFailed","setPreviewFailed","timerRef","aspectRatio","canPreview","showPreview","clearTimer","startPreview","immediate","stopPreview","fav","findNeighbor","container","fx","fy","btn","cx","cy","dx","dy","GifGrid","containerRef","sentinelRef","setCols","handlersRef","stableSelect","stableToggle","stateRef","intersectingRef","lastFiredCountRef","requestMore","scrollKey","root","sentinel","skeletonColumns","showSkeletons","showEmpty","EmptyIcon","isFavorite","PER_PAGE$1","SEARCH_DEBOUNCE_MS$1","isSafeGif","gif","getEmptyState","SearchX","ImageOff","GifPicker","categoryId","setCategoryId","klipyCats","setKlipyCats","setItems","setLoading","setPage","setHasMore","setNotice","requestRef","versionRef","favoriteIds","cats","activeCategory","trimmedQuery","feedQuery","libraryKey","feedRef","loadPage","version","src","pageNum","safe","append","handleLoadMore","handleRetry","handleCategorySelect","handleSelect","handleToggleFavorite","Search","getStickersUrl","PREVIEW_SIZES","FULL_SIZES","FORMATS","ERROR_MESSAGE","categoriesCache","getStickerCustomerId","pickMedia","format","normalizeItem","toPage","pageParams","fetchTrendingStickers","searchStickers","fetchRecentStickers","fetchStickerCategories","previewUrl","shareSticker","toStickerAttachment","PER_PAGE","SEARCH_DEBOUNCE_MS","EMPTY_TEXT","requestFor","mode","StickerPicker","setMode","setActiveCategory","setCategories","stickers","setStickers","previewItem","setPreviewItem","gridRef","loadMoreRef","prevTabRef","loadStickers","more","loadMode","loadTerm","handleQueryChange","selectTab","nextMode","handleGridKeyDown","firstTop","isTabSelected","tabMode","shortcuts","findEmojiToken","cursor","face","RESULT_LIMIT","RECENT_POOL_LIMIT","recentValue","stripVariation","foldText","HighlightedShortcode","EmojiAutocomplete","suggestions","setSuggestions","selectedIndex","setSelectedIndex","dropdownRef","shortcodeStartRef","listId","useId","optionId","valueFor","recentList","textareaRef","cursorPos","pool","ranked","insertEmoji","textarea","end","onInsert","newPos","dismiss","display","suggestion","DEFAULT_GAME_TYPES","GAME_MENU","CircleDot","Anchor","Crosshair","RACE_CLASS_MENU","TANK_MAP_MENU","TANK_LIVES_MENU","MessageComposer","composerRef","pickerHeight","setPickerHeight","pickerAvailableHeight","setPickerAvailableHeight","pickerResizeRef","fileInputRef","gameMenuRef","gameButtonRef","popover","setPopover","raceMenu","setRaceMenu","tankMenu","setTankMenu","tankMap","setTankMap","autocompleteOpen","setAutocompleteOpen","handleAutocompleteClose","handleAutocompleteInsert","voice","onAddAttachment","sendingMedia","sendingTitle","canSend","editing","pickerKind","reply","composer","parent","resize","chooseGame","handleGameMenuKeyDown","fromGames","onCancelEdit","onStartEditLast","handlePaste","files","handleInputChange","newValue","caret","completed","attachmentError","onCancelReply","onRemoveAttachment","Square","onInviteGame","onOpenBattleshipPreview","gameInviteDisabled","onSendEffect","Clapperboard","Sticker","Send","hint","lives","gameTypes","Box","GripHorizontal","ChatGamePanel","keepMounted","canDismiss","setMinimized","ChevronUp","ChatWindow$1","setTextSize","dialogRef","setShowSidebar","battleshipPreview","setBattleshipPreview","isFullscreen","setFullscreen","wide","standalone","resizable","resizeHandleProps","listVisible","showingConversation","isMinimized","selectRoom","onSelectRoom","trapFocus","placement","theme","effectScope","effectIdentityScope","effectsConfig","headerType","Grip","headerSecondary","headerPresence","onToggleMaximize","installHelp","onDismissInstallHelp","ArrowLeft","gamePanelKey","BattleshipPreviewComponent","effectError","gameError","inputValue","onInputChange","installPrompt","hasWindow","notifyInstall","installUsers","removeInstallListeners","startChatApp","onPrompt","onInstalled","useChatInstall","installed","setInstalled","setAvailable","setInstallHelp","prompt","chatPopup","openChatWindow","windowName","registerChatWorker","swUrl","MAX_PREVIEW_BYTES","useChatController","installation","rawEffectsConfig","gamesFeatures","features","effectCooldowns","effectPending","setEffectError","useShallow","chatIdentity","effectConnection","websocketStatus","unreadRooms","rawPrivateRooms","rawKnownUsers","setReply","setEditing","setGameError","edits","chatState","setInputValue","setAttachments","sendingRef","objectUrls","setAttachmentError","attachmentRef","activeRoom","gameScope","gameKeys","gameMessages","hasLiveGame","gamePanels","handleSelectUser","recipientId","existingRoom","openPrivateChat","people","fetchGroups","presenceTrigger","searchUsers","userSearchQuery","urls","chatMessages","timeline","inferredType","selectChat","startEdit","cancelEdit","handleReact","handleSend","sendChatMessage","outgoingAttachments","quoted","handleAddAttachment","removeAttachment","peer","wait","setMyPresence","userSearchResults","userSearchStatus","setUserSearchQuery","opponentId","gameType","createGroup","chatUiStore","useChatUi","isChatEscapeTarget","useChatLayout","alwaysOpen","controlled","storeOpen","setMaximized","isControlled","onConfigOpenChange","canMinimize","minimize","restore","toggleMinimize","toggleMaximize","pwa","handleKey","POPUP_BLOCKED","portalTarget","ModalFrame","frameRef","trap","ChatWindow","layout","chat","floating","canDetach","shell","content","className","ChatPage","ChatButton","isPressed","pressed","iconSize","badgeClassName","running","call","args","nav","method","onFail","isAppBadgeRunning","startAppBadge","apply","retry","schedule","ChatNotifications","notifications","badge","MAX_BYTES","sessions","sessionFor","relayRequest","consumeRelayEvent","hydrateRelayMessage","closeRelay","sendRelayMessage","outgoing","chunk","WebRtcLab","MINICODE_CHAT_VERSION","loadBattleshipPreview"],"sources":["../src/config/normalizeConfig.js","../src/core/transport/createStandaloneTransport.js","../src/core/unread/unreadMessages.js","../src/core/extras/messageExtras.js","../src/notifications/desktopNotifications.js","../src/core/chat/createChatStore.js","../src/provider/hooks.js","../src/effects/confetti/timeline.js","../src/effects/avalanche/timeline.js","../src/effects/catalog.js","../src/effects/effectAudio.js","../src/effects/thunder/thunderScene2d.js","../src/effects/thunder/ThunderEffect.jsx","../src/effects/confetti/ConfettiEffect.jsx","../src/effects/avalanche/AvalancheFallback.jsx","../src/effects/avalanche/AvalancheEffect.jsx","../src/effects/EffectPlayer.jsx","../src/effects/protocol.js","../src/effects/backgroundEffects.js","../src/effects/ChatEffects.jsx","../src/effects/BackgroundEffects.jsx","../src/provider/LiraChatProvider.jsx","../src/core/transport/chatTransport.js","../src/media/klipy/klipyCustomer.js","../src/media/klipy/klipy.js","../src/ui/hooks/useChatTextSize.js","../src/ui/hooks/useFocusTrap.js","../src/ui/hooks/useResizable.js","../src/ui/components/ChatHeader.jsx","../src/ui/components/ConversationItem.jsx","../src/ui/components/ConversationList.jsx","../src/ui/components/StatusMenu.jsx","../src/ui/components/ChatSidebar.jsx","../src/ui/components/ChatEmptyState.jsx","../src/media/emoji/customEmojis.js","../src/media/emoji/customEmojiCatalog.js","../src/media/emoji/useCustomEmojis.js","../src/ui/components/MessageText.jsx","../src/ui/components/MediaPreview.jsx","../src/media/youtube/youtubeLinks.js","../src/ui/components/YouTubePreview.jsx","../src/media/emoji/emojiShortcodes.js","../src/media/emoji/emojiPreferences.js","../src/media/emoji/useEmojiData.js","../src/ui/components/EmojiPicker.jsx","../src/ui/components/ReactionPicker.jsx","../src/ui/chatPeopleContext.js","../src/ui/components/ReactionBar.jsx","../src/ui/components/MessageBubble.jsx","../src/games/shared/useGamePanelStore.js","../src/games/connect4/GameCard.jsx","../src/games/shared/ConnectedGameCard.jsx","../src/games/shared/GameTimelineEntry.jsx","../src/ui/components/MessageList.jsx","../src/ui/hooks/useVoiceRecorder.js","../src/media/gif-search/gifQueryExpansion.js","../src/media/gif-search/gifRelevance.js","../src/media/gif-search/gifLibrary.js","../src/media/gif-search/gifSearchEngine.js","../src/media/gif-search/gifCategories.js","../src/ui/components/GifCategoryBar.jsx","../src/ui/components/GifGrid.jsx","../src/ui/components/GifPicker.jsx","../src/media/klipy/klipyStickers.js","../src/ui/components/StickerPicker.jsx","../src/media/emoji/emojiAutocompleteToken.js","../src/ui/components/EmojiAutocomplete.jsx","../src/ui/components/MessageComposer.jsx","../src/games/shared/ChatGamePanel.jsx","../src/ui/components/ChatWindow.jsx","../src/pwa/chatApp.js","../src/ui/connected/useChatController.js","../src/ui/connected/chatUiStore.js","../src/ui/connected/useChatLayout.js","../src/ui/connected/ChatWindow.jsx","../src/ui/connected/ChatPage.jsx","../src/ui/connected/ChatButton.jsx","../src/notifications/appBadge.js","../src/ui/connected/ChatNotifications.jsx","../src/core/relay/fileRelay.js","../src/net/webrtc/index.js","../src/index.js"],"sourcesContent":["// Applies defaults to the public config schema (doc §3.2). Each section is\n// shallow-merged over its defaults; the result is frozen (one level deep).\n\nconst noop = () => {};\n\nexport const DEFAULT_CONFIG = Object.freeze({\n websocket: Object.freeze({\n url: null,\n reconnect: Object.freeze({ max: 3, baseMs: 1000, capMs: 10000 }),\n ping: false,\n legacyRoomIdRouting: true,\n }),\n webrtc: Object.freeze({ iceServers: undefined, iceTransportPolicy: 'all' }),\n auth: Object.freeze({ getToken: null, tokenParam: 'token' }),\n user: null,\n scope: null,\n features: Object.freeze({\n reactions: true, editing: true, replies: true, files: true, voice: true,\n gifs: true, stickers: true, youtube: true, presence: true, groups: true, privateChats: true,\n games: Object.freeze({ connect4: true, battleship: true, battleshipPreview: true, tanks: false, tanksLive: false, racingLive: false }),\n detach: Object.freeze({ path: '/chat', windowName: 'lira-independent-chat' }),\n install: true,\n }),\n theme: Object.freeze({ mode: 'auto', tokens: Object.freeze({}), fontSize: 14 }),\n media: Object.freeze({\n klipy: false,\n emoji: Object.freeze({ custom: [], lazy: true }),\n maxAttachmentBytes: 10 * 1024 * 1024,\n trustedMediaHosts: Object.freeze(['static.klipy.com', 'media.klipy.com', 'cdn.klipy.com']),\n }),\n notifications: Object.freeze({ desktop: true, previews: false, sound: true, appBadge: true }),\n effects: Object.freeze({ enabled: true, sound: true, backgroundSound: true, volume: 0.35, autoPlay: true, cooldownMs: 5000, maxAgeMs: 10000, allowGroups: false }),\n assets: Object.freeze({ baseUrl: null }),\n storage: Object.freeze({ prefix: 'lira', adapter: undefined }),\n locale: 'es',\n portalContainer: undefined,\n callbacks: Object.freeze({\n onError: noop, onOpenChange: noop, onOpenConversation: noop,\n onUnreadChange: noop, onConnectionChange: noop,\n }),\n});\n\nconst isPlainObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);\n\n/**\n * Normalizes the host user to `{ id, ids, name }` (strings; frozen). Accepts LIRA/Cognito-like\n * shapes: `id`/`user_id`/`sub` and `name`/`username`/`email`. Returns null without an id.\n */\nexport function normalizeUser(user) {\n if (!isPlainObject(user)) return null;\n const id = user.id ?? user.user_id ?? null;\n const ids = Array.isArray(user.ids) ? user.ids : [id, user.user_id, user.sub];\n const uniqueIds = [...new Set(ids.filter((value) => value != null && String(value) !== '').map(String))];\n const name = user.name || user.username || user.email || null;\n if (id == null && !uniqueIds.length) return null;\n return Object.freeze({ id: id == null ? uniqueIds[0] : String(id), ids: Object.freeze(uniqueIds), name });\n}\n\nconst SECTIONS = ['websocket', 'webrtc', 'auth', 'features', 'theme', 'media', 'notifications', 'effects', 'assets', 'storage', 'callbacks'];\nconst SCALARS = ['user', 'scope', 'locale', 'portalContainer'];\n\nfunction mergeSection(defaults, value) {\n if (value === false) return false; // e.g. features disabled wholesale\n if (!isPlainObject(value)) return defaults;\n const merged = { ...defaults };\n for (const [key, entry] of Object.entries(value)) if (entry !== undefined) merged[key] = entry;\n return Object.freeze(merged);\n}\n\nexport function normalizeConfig(config = {}) {\n const input = isPlainObject(config) ? config : {};\n const result = { ...input };\n for (const section of SECTIONS) result[section] = mergeSection(DEFAULT_CONFIG[section], input[section]);\n for (const key of SCALARS) result[key] = input[key] === undefined ? DEFAULT_CONFIG[key] : input[key];\n result.user = normalizeUser(result.user);\n // PWA / detached window: `pwa.path`/`pwa.windowName` win over `features.detach`.\n const detach = isPlainObject(result.features?.detach) ? result.features.detach : DEFAULT_CONFIG.features.detach;\n result.pwa = Object.freeze({ ...detach, ...(isPlainObject(input.pwa) ? input.pwa : {}) });\n // Nested objects that callers commonly pass partially.\n if (isPlainObject(result.media) && isPlainObject(input.media?.emoji)) {\n result.media = Object.freeze({ ...result.media, emoji: mergeSection(DEFAULT_CONFIG.media.emoji, input.media.emoji) });\n }\n if (isPlainObject(result.websocket) && isPlainObject(input.websocket?.reconnect)) {\n result.websocket = Object.freeze({ ...result.websocket, reconnect: Object.freeze({ ...DEFAULT_CONFIG.websocket.reconnect, ...input.websocket.reconnect }) });\n }\n if (isPlainObject(result.features) && isPlainObject(input.features?.games)) {\n result.features = Object.freeze({ ...result.features, games: Object.freeze({ ...DEFAULT_CONFIG.features.games, ...input.features.games }) });\n }\n if (isPlainObject(result.callbacks)) {\n const callbacks = { ...result.callbacks };\n for (const key of Object.keys(DEFAULT_CONFIG.callbacks)) if (typeof callbacks[key] !== 'function') callbacks[key] = noop;\n result.callbacks = Object.freeze(callbacks);\n }\n return Object.freeze(result);\n}\n","// Transporte WebSocket propio del paquete para backends distintos de LIRA.\n// Misma semántica que connectSocket de LIRA (backoff, isFatal, request/ACK de fileRelay).\n\n/** @typedef {import('./chatTransport.js').ChatTransport} ChatTransport */\n/** @typedef {import('./chatTransport.js').TransportStatus} TransportStatus */\n/** @typedef {import('./chatTransport.js').InboundFrame} InboundFrame */\n\nconst OPEN = 1;\nconst DEFAULT_TIMEOUT_MS = 15000;\n\nconst defaultIsFatal = (frame) =>\n frame?.type === 'ERROR' && /no esta habilitado/.test(frame?.data?.message ?? '');\n\nlet idCounter = 0;\nconst newId = () => {\n try {\n if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();\n } catch {\n /* fallback */\n }\n idCounter += 1;\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}-${idCounter}`;\n};\n\nconst withToken = (url, token, tokenParam) => {\n if (!token) return url;\n const re = new RegExp(`[?&]${tokenParam}=`);\n if (re.test(url)) return url;\n const sep = url.includes('?') ? '&' : '?';\n return `${url}${sep}${tokenParam}=${encodeURIComponent(token)}`;\n};\n\n/**\n * @param {{\n * url: string | (() => string | Promise<string>),\n * getToken?: () => (string | null | undefined | Promise<string | null | undefined>),\n * tokenParam?: string,\n * reconnect?: { max?: number, baseMs?: number, capMs?: number },\n * isFatal?: (frame: InboundFrame) => boolean,\n * ping?: false | { action?: string, everyMs: number },\n * identity?: () => { userId: string|null, scope: string },\n * WebSocketImpl?: typeof WebSocket,\n * }} opts\n * @returns {ChatTransport}\n */\nexport function createStandaloneTransport({\n url,\n getToken,\n tokenParam = 'token',\n reconnect = { max: 3, baseMs: 1000, capMs: 10000 },\n isFatal = defaultIsFatal,\n ping = false,\n identity = () => ({ userId: null, scope: '' }),\n WebSocketImpl = globalThis.WebSocket,\n} = {}) {\n const maxRetries = reconnect?.max ?? 3;\n const baseMs = reconnect?.baseMs ?? 1000;\n const capMs = reconnect?.capMs ?? 10000;\n const pingAction = ping ? ping.action ?? 'PING' : null;\n const pingEvery = ping ? ping.everyMs : 0;\n\n /** @type {WebSocket|null} */\n let socket = null;\n let connectionId = null;\n /** @type {TransportStatus} */\n let status = 'idle';\n let attempts = 0;\n let fatal = false;\n let voluntary = false;\n let connecting = null;\n let retryTimer = null;\n let pingTimer = null;\n\n const handlers = new Set();\n const statusListeners = new Set();\n const pending = new Map(); // request_id -> { resolve, reject, timer }\n\n const setStatus = (next) => {\n if (next === status) return;\n const prev = status;\n status = next;\n statusListeners.forEach((cb) => {\n try {\n cb(next, prev);\n } catch (err) {\n console.error('[chat] status listener error', err);\n }\n });\n };\n\n const rejectAll = (message) => {\n pending.forEach(({ reject, timer }) => {\n clearTimeout(timer);\n reject(new Error(message));\n });\n pending.clear();\n };\n\n const clearRetry = () => {\n if (retryTimer) clearTimeout(retryTimer);\n retryTimer = null;\n };\n\n const stopPing = () => {\n if (pingTimer) clearInterval(pingTimer);\n pingTimer = null;\n };\n\n const startPing = () => {\n stopPing();\n if (!pingAction || !(pingEvery > 0)) return;\n pingTimer = setInterval(() => send(pingAction), pingEvery);\n };\n\n const scheduleReconnect = () => {\n if (fatal || voluntary || attempts >= maxRetries) return;\n const delay = Math.min(capMs, 2 ** attempts * baseMs);\n attempts += 1;\n clearRetry();\n retryTimer = setTimeout(() => {\n retryTimer = null;\n connect().catch(() => {});\n }, delay);\n };\n\n const settle = (ev, body, frame) => {\n const entry = pending.get(body.request_id);\n if (!entry) return false;\n clearTimeout(entry.timer);\n pending.delete(body.request_id);\n if (ev === 'CHAT_ACK') {\n entry.resolve(frame);\n } else {\n const err = new Error(body.message || 'No se pudo enviar');\n if (body.code !== undefined) err.code = body.code;\n entry.reject(err);\n }\n return true;\n };\n\n const dispatch = (frame) => {\n const ev = frame?.event ?? frame?.type;\n const body = frame?.data ?? frame?.payload ?? {};\n if ((ev === 'CHAT_ACK' || ev === 'ERROR') && body?.request_id != null) {\n if (settle(ev, body, frame)) return;\n }\n if (pingAction && ev === 'PONG') return;\n for (const h of handlers) {\n try {\n if (h(frame) === true) return;\n } catch (err) {\n console.error('[chat] transport handler error', err);\n }\n }\n };\n\n const resolveUrl = async () => {\n const base = typeof url === 'function' ? await url() : url;\n if (!base) throw new Error('[chat] createStandaloneTransport: url vacía');\n const token = getToken ? await getToken() : null;\n return withToken(String(base), token, tokenParam);\n };\n\n function connect() {\n if (socket && (socket.readyState === OPEN || socket.readyState === 0)) return Promise.resolve();\n if (connecting) return connecting;\n if (!WebSocketImpl) return Promise.reject(new Error('[chat] WebSocket no disponible'));\n\n voluntary = false;\n fatal = false;\n clearRetry();\n setStatus('connecting');\n\n connecting = (async () => {\n let target;\n try {\n target = await resolveUrl();\n } catch (err) {\n setStatus('error');\n scheduleReconnect();\n throw err;\n }\n if (voluntary) return;\n\n await new Promise((resolve, reject) => {\n let opened = false;\n const ws = new WebSocketImpl(target);\n socket = ws;\n connectionId = newId();\n\n ws.onopen = () => {\n if (socket !== ws) return;\n opened = true;\n attempts = 0;\n setStatus('connected');\n startPing();\n resolve();\n };\n\n ws.onmessage = (msg) => {\n if (socket !== ws) return;\n let frame;\n try {\n frame = JSON.parse(msg.data);\n } catch {\n return;\n }\n if (isFatal && isFatal(frame)) fatal = true;\n dispatch(frame);\n };\n\n ws.onerror = () => {\n if (socket !== ws) return;\n setStatus('error');\n };\n\n ws.onclose = (evt) => {\n if (socket !== ws) return;\n socket = null;\n connectionId = null;\n stopPing();\n rejectAll('Conexión interrumpida. Reintenta el envío.');\n setStatus('disconnected');\n if (!opened) reject(new Error('[chat] no se pudo abrir el WebSocket'));\n if (evt?.code !== 1000) scheduleReconnect();\n };\n });\n })().finally(() => {\n connecting = null;\n });\n\n return connecting;\n }\n\n function close(code = 1000) {\n voluntary = true;\n clearRetry();\n stopPing();\n const ws = socket;\n socket = null;\n connectionId = null;\n rejectAll('Conexión cerrada');\n if (ws) {\n try {\n ws.close(code);\n } catch {\n /* ignore */\n }\n }\n setStatus('disconnected');\n }\n\n function send(action, payload) {\n if (!socket || socket.readyState !== OPEN) return false;\n try {\n socket.send(JSON.stringify(payload === undefined ? { action } : { action, payload }));\n return true;\n } catch {\n return false;\n }\n }\n\n function request(action, payload = {}, { timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {\n if (!socket || socket.readyState !== OPEN) return Promise.reject(new Error('Sin conexión'));\n const request_id = newId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(request_id);\n reject(new Error('El servidor no confirmó el envío. Conservamos el borrador.'));\n }, timeoutMs);\n pending.set(request_id, { resolve, reject, timer });\n if (!send(action, { ...payload, request_id })) {\n clearTimeout(timer);\n pending.delete(request_id);\n reject(new Error('Sin conexión'));\n }\n });\n }\n\n return {\n connect,\n close,\n send,\n request,\n onEvent(handler) {\n handlers.add(handler);\n return () => handlers.delete(handler);\n },\n getStatus: () => status,\n onStatus(cb) {\n statusListeners.add(cb);\n return () => statusListeners.delete(cb);\n },\n getConnectionId: () => connectionId,\n getIdentity: () => identity(),\n };\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\nconst PREFIX = 'lira-chat-unread:v1:';\nconst SEEN_LIMIT = 2000;\n/**\n * Clock skew: message timestamps come from the server while `connectedAt`/`now()` are client\n * clocks, so they are never compared with each other. The backend never replays history over\n * WebSocket: every dated frame received on an open socket is live. Id dedup (`seen`) plus the\n * per-room `readThrough` watermark (server time only) prevent double counting and reconnect\n * inflation. History-flagged and undated frames are still dropped.\n */\nconst record = (value) => value && typeof value === 'object' && !Array.isArray(value) ? value : {};\nconst safeTime = (value) => Number.isFinite(value) && value >= 0;\nexport const unreadStorageKey = (scope) => PREFIX + encodeURIComponent(scope);\nexport const unreadScope = (backend, userId) => userId == null ? null : JSON.stringify([backend, String(userId)]);\nconst dictionary = () => Object.create(null);\nconst empty = () => ({ unread: dictionary(), readThrough: dictionary(), seen: dictionary(), rooms: dictionary() });\n\n/** Merge by message identity and read watermark, including across tabs. No text is stored. */\nexport function mergeUnread(first = {}, second = {}) {\n first = record(first); second = record(second);\n const readThrough = dictionary();\n for (const source of [first, second]) {\n for (const [room, time] of Object.entries(record(source.readThrough))) {\n if (safeTime(time)) readThrough[room] = Math.max(readThrough[room] ?? 0, time);\n }\n }\n const unread = dictionary();\n const seen = dictionary();\n const rooms = dictionary();\n for (const source of [first, second]) {\n for (const [room, entries] of Object.entries(record(source.unread))) {\n for (const [id, time] of Object.entries(record(entries))) {\n if (safeTime(time) && time > (readThrough[room] ?? -1)) {\n if (!Object.hasOwn(unread, room)) Object.defineProperty(unread, room, { value: {}, enumerable: true, writable: true });\n Object.defineProperty(unread[room], id, { value: time, enumerable: true, configurable: true, writable: true });\n }\n }\n }\n for (const [id, time] of Object.entries(record(source.seen))) if (safeTime(time)) seen[id] = time;\n for (const [room, info] of Object.entries(record(source.rooms))) {\n if (info && typeof info.peerId === 'string') {\n Object.defineProperty(rooms, room, { value: { peerId: info.peerId, username: String(info.username ?? '').slice(0, 256) }, enumerable: true, configurable: true, writable: true });\n }\n }\n }\n const boundedSeen = Object.fromEntries(Object.entries(seen).sort((a, b) => b[1] - a[1]).slice(0, SEEN_LIMIT));\n return { unread, readThrough, seen: boundedSeen, rooms };\n}\nexport const unreadCounts = (ledger) => Object.fromEntries(Object.entries(ledger.unread).map(([room, messages]) => [room, Object.keys(messages).length]));\nexport const totalUnread = (state) => Object.values(state.counts).reduce((total, count) => total + count, 0);\n\nexport function normalizeChatMessage(envelope) {\n const body = record(envelope.data ?? envelope.payload);\n return { ...body, ...envelope,\n room_id: envelope.room_id ?? body.room_id, user_id: envelope.user_id ?? body.user_id,\n message: envelope.message ?? body.message, text: envelope.text ?? body.text,\n id: envelope.message_id ?? envelope.id ?? body.message_id ?? body.id,\n timestamp: envelope.timestamp ?? body.timestamp,\n };\n}\n// Synchronous compact fingerprint only for legacy messages without a server ID.\n// Persisting a fallback identifier must not persist the message body or file URL.\nfunction fingerprint(value) {\n let first = 2166136261; let second = 5381;\n for (let index = 0; index < value.length; index += 1) {\n first = Math.imul(first ^ value.charCodeAt(index), 16777619);\n second = Math.imul(second, 33) ^ value.charCodeAt(index);\n }\n return `${value.length}:${(first >>> 0).toString(16)}:${(second >>> 0).toString(16)}`;\n}\n// Django isoformat() may carry microseconds (\"…:00.123456+00:00\"); older Safari rejects >3 digits.\nexport function parseServerTime(value) {\n if (typeof value !== 'string') return NaN;\n return Date.parse(value.replace(/(\\.\\d{3})\\d+/, '$1'));\n}\nexport function unreadCandidate(envelope, ownIds, connectedAt) {\n const message = normalizeChatMessage(envelope);\n const text = message.message ?? message.text ?? '';\n const type = envelope.event ?? envelope.type;\n if (type !== 'CHAT_MESSAGE' || !message.room_id || message.user_id == null\n || ownIds.map(String).includes(String(message.user_id))\n || message.localOnly || message.optimistic || message.is_history || message.history || message.replay\n || message.kind === 'game' || message.content?.kind === 'game'\n || (typeof text === 'string' && (text.startsWith('LIRA_GAME_') || text.startsWith('LIRA_WEBRTC_')))) return null;\n if (!(typeof text === 'string' && text.trim()) && !message.attachments?.length && !message.attachment) return null;\n const time = parseServerTime(message.timestamp);\n // Undated frames cannot be proved live; nothing counts before the socket is open.\n if (!Number.isFinite(time) || !Number.isFinite(connectedAt)) return null;\n const room = String(message.room_id);\n const id = JSON.stringify([room, message.id ?? fingerprint(JSON.stringify([String(message.user_id), message.timestamp, text, message.attachments ?? message.attachment ?? null]))]);\n return { room, id, time, peerId: String(message.user_id), username: message.username ?? '' };\n}\n\nconst browserStorage = () => { try { return globalThis.localStorage; } catch { return null; } };\nexport function createUnreadStore({ storage = browserStorage } = {}) {\n const read = (scope) => {\n try { return mergeUnread(empty(), JSON.parse(storage()?.getItem(unreadStorageKey(scope)) ?? '{}')); }\n catch { return empty(); }\n };\n const save = (scope, ledger) => {\n try { storage()?.setItem(unreadStorageKey(scope), JSON.stringify(ledger)); } catch { /* Keep in-memory counts if storage is unavailable/full. */ }\n };\n const store = createStore((set, get) => {\n const commit = (ledger) => {\n const scope = get().scope;\n save(scope, ledger);\n set({ ledger, counts: unreadCounts(ledger) });\n };\n return {\n scope: null, ledger: empty(), counts: {}, visibleRoom: null,\n activateScope: (scope) => {\n if (scope === get().scope) return;\n const ledger = scope ? read(scope) : empty();\n set({ scope, ledger, counts: unreadCounts(ledger), visibleRoom: null });\n },\n receive: (message, { ownIds, connectedAt }) => {\n if (!get().scope) return false;\n const candidate = unreadCandidate(message, ownIds, connectedAt);\n if (!candidate) return false;\n const { room, id, time, peerId, username } = candidate;\n const ledger = mergeUnread(read(get().scope), get().ledger);\n if (Object.hasOwn(ledger.seen, id) || Object.hasOwn(ledger.unread[room] ?? {}, id)\n || time <= (ledger.readThrough[room] ?? -1)) {\n set({ ledger, counts: unreadCounts(ledger) });\n return false;\n }\n ledger.seen[id] = time;\n if (room.startsWith('private_')) ledger.rooms[room] = { peerId, username };\n // Watermarks track server time; the client clock only acts as a skew-tolerant floor so a\n // client running ahead never swallows later live messages once the room is hidden again.\n if (get().visibleRoom === room) ledger.readThrough[room] = Math.max(ledger.readThrough[room] ?? 0, time);\n else ledger.unread[room] = { ...ledger.unread[room], [id]: time };\n commit(mergeUnread(ledger));\n return true;\n },\n setVisibleRoom: (roomId) => {\n const room = roomId == null ? null : String(roomId);\n set({ visibleRoom: room });\n if (room !== null) get().markRead(room);\n },\n markRead: (roomId) => {\n if (!get().scope || roomId == null) return;\n const room = String(roomId);\n const ledger = mergeUnread(read(get().scope), get().ledger);\n const times = Object.values(ledger.unread[room] ?? {});\n ledger.readThrough[room] = times.reduce((latest, time) => Math.max(latest, time),\n ledger.readThrough[room] ?? 0);\n commit(mergeUnread(ledger));\n },\n syncStorage: () => {\n if (!get().scope) return;\n const ledger = mergeUnread(read(get().scope), get().ledger);\n set({ ledger, counts: unreadCounts(ledger) });\n if (get().visibleRoom !== null && get().counts[get().visibleRoom] > 0) get().markRead(get().visibleRoom);\n },\n };\n });\n let stopStorageSync = null;\n /** Cross-tab sync via `storage` events. Idempotent per store; returns `stop()`. */\n store.startStorageSync = () => {\n if (stopStorageSync) return stopStorageSync;\n if (typeof window === 'undefined') return () => {};\n const onStorage = (event) => {\n const scope = store.getState().scope;\n if (scope && event.key === unreadStorageKey(scope)) store.getState().syncStorage();\n };\n window.addEventListener('storage', onStorage);\n const stop = () => {\n window.removeEventListener('storage', onStorage);\n if (stopStorageSync === stop) stopStorageSync = null;\n };\n stopStorageSync = stop;\n return stop;\n };\n return store;\n}\nconst unreadStore = createUnreadStore();\n/** Backward-compatible singleton hook (with vanilla store API attached). */\nexport const useChatUnread = Object.assign((selector) => useStore(unreadStore, selector), {\n getState: unreadStore.getState, setState: unreadStore.setState, subscribe: unreadStore.subscribe,\n});\n/** Cross-tab sync via `storage` events. Idempotent; returns `stop()` which removes the listener. */\nexport function startUnreadStorageSync(store = unreadStore) {\n return (store === useChatUnread ? unreadStore : store).startStorageSync();\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n/**\n * Edits and reactions without backend support: they travel as ordinary\n * CHAT_MESSAGE frames with a versioned prefix (same idea as LIRA_GAME_V1:).\n * The backend stamps user_id, so authorship cannot be forged:\n * - an edit applies only when its author is the original message's author;\n * - a reaction is attributed to the author of the reaction frame.\n * Nothing is persisted server-side: clients that were offline never see them,\n * exactly like ordinary messages (the relay keeps no history).\n * Unread counters already ignore every \"LIRA_\" prefixed frame.\n */\nexport const EDIT_PREFIX = 'LIRA_EDIT_V1:';\nexport const REACT_PREFIX = 'LIRA_REACT_V1:';\nexport const MAX_EDIT_LENGTH = 9000;\nconst MAX_EMOJI_LENGTH = 32;\nconst MAX_TRACKED = 1000;\n\n// Stickers reuse the backend's GIF attachment contract ({kind:'gif', url, name});\n// the name prefix is the only field the backend keeps that can mark them.\nexport const STICKER_NAME_PREFIX = 'sticker:';\nexport const isStickerAttachment = (item) => typeof item?.name === 'string' && item.name.startsWith(STICKER_NAME_PREFIX);\nexport const stickerTitle = (item) => (isStickerAttachment(item) ? item.name.slice(STICKER_NAME_PREFIX.length) : item?.name) || 'Sticker';\n\nexport const isMessageAction = (text) => typeof text === 'string' && (text.startsWith(EDIT_PREFIX) || text.startsWith(REACT_PREFIX));\n\nexport const messageId = (message) => {\n const id = message?.message_id ?? message?.id;\n return id == null ? null : String(id);\n};\n\nexport const encodeEdit = ({ targetId, text }) => EDIT_PREFIX + JSON.stringify({ target_id: String(targetId), text: String(text).slice(0, MAX_EDIT_LENGTH) });\nexport const encodeReaction = ({ targetId, emoji, on }) => REACT_PREFIX + JSON.stringify({ target_id: String(targetId), emoji: String(emoji), on: Boolean(on) });\n\n/** { type: 'edit', targetId, text } | { type: 'react', targetId, emoji, on } | null */\nexport function parseMessageAction(text) {\n if (!isMessageAction(text)) return null;\n const edit = text.startsWith(EDIT_PREFIX);\n let data;\n try { data = JSON.parse(text.slice((edit ? EDIT_PREFIX : REACT_PREFIX).length)); } catch { return null; }\n if (!data || typeof data !== 'object' || typeof data.target_id !== 'string' || !data.target_id) return null;\n if (edit) {\n if (typeof data.text !== 'string' || !data.text.trim() || data.text.length > MAX_EDIT_LENGTH) return null;\n return { type: 'edit', targetId: data.target_id, text: data.text };\n }\n if (typeof data.emoji !== 'string' || !data.emoji || data.emoji.length > MAX_EMOJI_LENGTH) return null;\n return { type: 'react', targetId: data.target_id, emoji: data.emoji, on: data.on !== false };\n}\n\nconst bounded = (map) => {\n const keys = Object.keys(map);\n if (keys.length <= MAX_TRACKED) return map;\n const next = { ...map };\n keys.slice(0, keys.length - MAX_TRACKED).forEach((key) => { delete next[key]; });\n return next;\n};\n\n/**\n * edits: { [messageId]: { text, editedAt } }\n * reactions: { [messageId]: { [emoji]: string[] userIds } } (insertion order kept)\n */\nexport const createMessageExtrasStore = () => createStore((set, get) => ({\n edits: {},\n reactions: {},\n seen: {},\n /**\n * Applies one action frame. `original` is the target message (or null when it\n * never reached this client: the action is ignored). Returns true if applied.\n */\n apply: (frame, original) => {\n const text = frame?.message ?? frame?.text;\n const action = parseMessageAction(text);\n const author = frame?.user_id == null ? null : String(frame.user_id);\n const frameId = messageId(frame);\n if (!action || !author || !original) return false;\n if (frameId && get().seen[frameId]) return false;\n if (String(original.room_id) !== String(frame.room_id) || messageId(original) !== action.targetId) return false;\n const seen = frameId ? bounded({ ...get().seen, [frameId]: true }) : get().seen;\n if (action.type === 'edit') {\n if (String(original.user_id) !== author) return false;\n const previous = get().edits[action.targetId];\n if (previous && previous.editedAt && frame.timestamp && previous.editedAt > frame.timestamp) { set({ seen }); return false; }\n set({ seen, edits: bounded({ ...get().edits, [action.targetId]: { text: action.text, editedAt: frame.timestamp ?? null } }) });\n return true;\n }\n const current = get().reactions[action.targetId] ?? {};\n const users = (current[action.emoji] ?? []).filter((id) => id !== author);\n if (action.on) users.push(author);\n const nextForMessage = { ...current, [action.emoji]: users };\n if (!users.length) delete nextForMessage[action.emoji];\n set({ seen, reactions: bounded({ ...get().reactions, [action.targetId]: nextForMessage }) });\n return true;\n },\n reset: () => set({ edits: {}, reactions: {}, seen: {} }),\n}));\n\nconst messageExtrasStore = createMessageExtrasStore();\n/** Backward-compatible singleton hook (with vanilla store API attached). */\nexport const useChatMessageExtras = Object.assign((selector) => useStore(messageExtrasStore, selector), {\n getState: messageExtrasStore.getState, setState: messageExtrasStore.setState, subscribe: messageExtrasStore.subscribe,\n});\n\n/** Groups reactions for display: [{ emoji, count, mine, userIds }]. */\nexport function groupReactions(byEmoji, ownIds = []) {\n const own = new Set(ownIds.filter((id) => id != null).map(String));\n return Object.entries(byEmoji || {})\n .filter(([, users]) => users?.length)\n .map(([emoji, users]) => ({ emoji, count: users.length, mine: users.some((id) => own.has(String(id))), userIds: users }));\n}\n\n/** Last own, editable (has text, not a game/action/local-only) message of a list, or null. */\nexport function findLastOwnEditable(messages, ownIds) {\n const own = new Set((ownIds || []).filter((id) => id != null).map(String));\n for (let index = (messages?.length ?? 0) - 1; index >= 0; index -= 1) {\n const message = messages[index];\n const text = message?.message ?? message?.text;\n if (message?.gameKey || message?.localOnly || !messageId(message) || !own.has(String(message.user_id))) continue;\n if (typeof text === 'string' && text.trim() && !isMessageAction(text)) return message;\n }\n return null;\n}\n","import { randomUuid } from '../core/ids/randomUuid.js';\n// Separate from sound notifications: permission is requested only by the header button.\nconst preferenceKey = 'lira-chat-desktop';\nconst previewKey = 'lira-chat-desktop-previews';\nlet channel = null;\nconst seen = new Set();\nconst activeNotifications = new Set();\nconst pending = new Map();\nlet conversation = null;\nconst read = (key) => { try { return localStorage.getItem(key) === 'true'; } catch { return false; } };\nexport function desktopSettings() {\n const supported = typeof window !== 'undefined' && window.isSecureContext && 'Notification' in window;\n return { supported, permission: supported ? Notification.permission : 'unsupported', enabled: read(preferenceKey), previews: read(previewKey) };\n}\nexport function setDesktopPreviews(value) {\n try { localStorage.setItem(previewKey, String(value)); } catch { /* Unavailable storage leaves previews off. */ }\n window.dispatchEvent(new Event('lira-desktop-settings'));\n}\nexport async function toggleDesktopNotifications() {\n const settings = desktopSettings();\n if (!settings.supported) return;\n let enabled = false;\n if (!settings.enabled || settings.permission !== 'granted') {\n try { enabled = (await Notification.requestPermission()) === 'granted'; } catch { /* Browser declined. */ }\n }\n try { localStorage.setItem(preferenceKey, String(enabled)); } catch { /* No persistent opt-in. */ }\n window.dispatchEvent(new Event('lira-desktop-settings'));\n}\nexport function setDesktopConversation(value) { conversation = value; }\nconst isVisible = (scope, room) => conversation?.scope === scope && String(conversation.room) === String(room)\n && conversation.open && document.visibilityState === 'visible' && document.hasFocus();\nconst onChannelMessage = ({ data }) => {\n if (data?.type === 'visible-query' && isVisible(data.scope, data.room)) channel?.postMessage({ type: 'visible', id: data.id });\n if (data?.type === 'visible') pending.get(data.id)?.();\n if (data?.type === 'shown') seen.add(data.id);\n if (seen.size > 500) seen.delete(seen.values().next().value);\n};\nconst pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\nexport function clearDesktopNotifications() {\n activeNotifications.forEach((notification) => notification.close());\n activeNotifications.clear();\n conversation = null;\n}\nexport async function notifyDesktopMessage(message, { scope, room, id, onClick, connectedAt, isCurrent }) {\n const settings = desktopSettings();\n if (!settings.supported || !settings.enabled || settings.permission !== 'granted' || room == null || !id) return;\n // Live CHAT_MESSAGE events only. Reject stale replays, history and undated events.\n const time = Date.parse(message.timestamp);\n if (!Number.isFinite(time) || time < connectedAt || message.localOnly || message.optimistic || message.is_history || message.history) return;\n const key = `${scope}:${id}`;\n if (seen.has(key)) return;\n seen.add(key);\n if (seen.size > 500) seen.delete(seen.values().next().value);\n let visible = isVisible(scope, room);\n const query = randomUuid();\n pending.set(query, () => { visible = true; });\n channel?.postMessage({ type: 'visible-query', id: query, scope, room });\n await pause(150);\n pending.delete(query);\n if (visible || isVisible(scope, room) || !isCurrent()) return;\n const show = async () => {\n // Persist only identifiers, never message text. Shared across Dashboard and popup.\n const storageKey = `lira-chat-desktop-seen:${key}`;\n try {\n if (localStorage.getItem(storageKey)) return;\n localStorage.setItem(storageKey, String(Date.now()));\n // Bounded retention, also protects against replay after reload/reconnect.\n const keys = Object.keys(localStorage).filter((item) => item.startsWith('lira-chat-desktop-seen:'));\n if (keys.length > 500) keys.sort((a, b) => Number(localStorage.getItem(a)) - Number(localStorage.getItem(b))).slice(0, keys.length - 500).forEach((item) => localStorage.removeItem(item));\n } catch { return; } // Avoid duplicates when cross-window storage is unavailable.\n if (!isCurrent() || !desktopSettings().enabled || Notification.permission !== 'granted' || isVisible(scope, room)) return;\n // Do not expose private conversations or explicitly private content in system UI.\n const previews = read(previewKey) && !String(room).startsWith('private') && !message.private && !message.sensitive;\n const sender = String(message.username || 'Nuevo mensaje').replace(/\\s+/g, ' ').slice(0, 70);\n const body = previews ? String(message.message || message.text || 'Archivo adjunto').replace(/\\s+/g, ' ').slice(0, 140) : 'Tienes un nuevo mensaje en LIRA Chat';\n try {\n const notification = new Notification(previews ? sender : 'LIRA Chat', { body, tag: key, silent: true });\n activeNotifications.add(notification);\n notification.onclose = () => activeNotifications.delete(notification);\n notification.onclick = () => { notification.close(); if (isCurrent()) { window.focus(); onClick(); } };\n channel?.postMessage({ type: 'shown', id: key });\n } catch { /* Some browsers expose permission but do not support desktop constructors. */ }\n };\n try {\n if (navigator.locks) await navigator.locks.request(`lira-desktop:${key}`, show);\n else {\n // A shared notification tag and storage claim provide best-effort fallback.\n await pause(Math.random() * 100);\n await show();\n }\n } catch { /* Notifications must never interrupt WebSocket processing. */ }\n}\n\n// Remove displayed previews when privacy preferences or account state change.\nconst closeDisplayed = () => { activeNotifications.forEach((item) => item.close()); activeNotifications.clear(); };\nconst onStorage = (event) => { if (!event.key || event.key === preferenceKey || event.key === previewKey) closeDisplayed(); };\n\n// Ref-counted, idempotent: channel and listeners are created once; the last stop() tears them down.\nlet desktopUsers = 0;\nexport function startDesktopNotifications() {\n if (typeof window === 'undefined') return () => {};\n if (desktopUsers++ === 0) {\n channel = typeof BroadcastChannel === 'function' ? new BroadcastChannel('lira-chat-desktop') : null;\n channel?.addEventListener('message', onChannelMessage);\n window.addEventListener('lira-desktop-settings', closeDisplayed);\n window.addEventListener('storage', onStorage);\n }\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n if (--desktopUsers === 0) {\n window.removeEventListener('lira-desktop-settings', closeDisplayed);\n window.removeEventListener('storage', onStorage);\n channel?.removeEventListener('message', onChannelMessage);\n channel?.close();\n channel = null;\n }\n };\n}\n","import { createStore } from 'zustand/vanilla';\nimport { useChatUnread, normalizeChatMessage } from '../unread/unreadMessages.js';\nimport { isMessageAction, messageId, parseMessageAction, useChatMessageExtras } from '../extras/messageExtras.js';\nimport { chatGamesStore } from '../../games/shared/useChatGames.js';\nimport { GAME_PREFIX } from '../../games/shared/protocol.js';\nimport { isWebrtcMessage } from '../../net/webrtc/protocol.js';\nimport { rtcSignals } from '../../net/webrtc/rtcSignals.js';\nimport { notifyDesktopMessage, clearDesktopNotifications } from '../../notifications/desktopNotifications.js';\nimport { initChatSounds, requestNotification } from '../../notifications/chatSounds.js';\n\n// Chat domain store (messages, rooms, presence, user search) driven by a ChatTransport.\n// Moved from LIRA's useWebSocket.js (phase 9b). Wire format is frozen by test/contract.\n// The old \"same socket?\" checks are now \"same connection id?\" (transport.getConnectionId()).\n\nexport const MAX_CHAT_MESSAGES = 500;\nexport const PRESENCE_STATUSES = ['online', 'away', 'busy'];\nexport const MANUAL_STATUSES = ['auto', 'busy', 'invisible'];\nconst initialPresence = { status: 'online', manual: 'auto' };\nconst STALE_REPLY_MS = 15000;\nconst SEARCH_TIMEOUT_MS = 10000;\nconst PRESENCE_SYNC_MS = 30000;\nconst ACTIVITY_EVENTS = ['pointerdown', 'keydown', 'wheel', 'touchstart', 'focus'];\n\nconst initialChatState = () => ({\n chatMessages: [],\n chatState: {\n activeTab: 'chats', // 'chats' | 'users' | 'groups'\n currentChat: null, // { id, type: 'group' | 'private' } or null when nothing is selected\n availableGroups: [],\n },\n onlineUsers: [],\n presenceStatus: 'idle',\n userSearchResults: [],\n userSearchQuery: '',\n userSearchStatus: 'idle',\n privateRooms: {},\n knownUsers: {}, // user_id -> last known info, keeps private chat names after the user goes offline\n myPresence: { ...initialPresence }, // status: online | away | busy | invisible (from MY_STATUS); manual: auto | busy | invisible\n});\n\nexport const normalizeUsers = (users) => {\n const byId = new Map();\n for (const user of Array.isArray(users) ? users : []) {\n if (!user || typeof user !== 'object' || (user.user_id ?? user.id) == null) continue;\n const id = String(user.user_id ?? user.id);\n if (id) byId.set(id, { ...user, user_id: id });\n }\n return [...byId.values()];\n};\nconst rememberUsers = (known, users) => ({ ...known, ...Object.fromEntries(users.map((user) => [user.user_id, user])) });\n\nconst revokeBlobs = (message) => {\n for (const attachment of message?.attachments || []) {\n if (attachment.url?.startsWith('blob:')) URL.revokeObjectURL(attachment.url);\n }\n};\nexport const appendBounded = (items, item, limit) => {\n const nextItems = [...items, item];\n const fileBytes = (message) => (message.attachments || []).reduce((sum, file) => sum + (file.url?.startsWith('blob:') ? file.size || 0 : 0), 0);\n let retainedBytes = nextItems.reduce((sum, message) => sum + fileBytes(message), 0);\n while (nextItems.length > limit || retainedBytes > 64 * 1024 * 1024) {\n const removed = nextItems.shift();\n retainedBytes -= fileBytes(removed);\n revokeBlobs(removed);\n }\n return nextItems;\n};\n\n/**\n * @param {object} options\n * @param {import('../transport/chatTransport.js').ChatTransport} options.transport\n * @param {(roomId: string, message: string, attachments?: any[]) => Promise<void>} [options.sendMessage]\n * Defaults to a CHAT_MESSAGE request without attachments (hosts with file relay inject theirs).\n * @param {() => string[]} [options.getOwnIds] Every id form of the current user (id, user_id, sub).\n * @param {(room: string) => void} [options.onOpenChat] Desktop notification click (after selectChat).\n * @param {number} [options.maxMessages]\n */\nexport function createChatStore({\n transport,\n sendMessage,\n getOwnIds,\n onOpenChat,\n maxMessages = MAX_CHAT_MESSAGES,\n games = chatGamesStore,\n unread = useChatUnread,\n extras = useChatMessageExtras,\n} = {}) {\n const identity = () => transport.getIdentity?.() ?? { userId: null, scope: '' };\n const ownIds = () => (getOwnIds ? getOwnIds() : [identity().userId].filter((id) => id != null).map(String));\n const connectionId = () => transport.getConnectionId?.() ?? null;\n const isOpen = () => transport.getStatus?.() === 'connected';\n const send = (action, payload) => transport.send(action, payload);\n\n // Per-connection runtime state (the old WeakMaps keyed by socket).\n let session = null;\n const newSession = (id) => ({\n id, joinedRooms: new Set(), connectedAt: Date.now(),\n search: { active: null, queue: [], timer: null, deltas: new Map(), lastPresence: 0, stale: [] },\n presenceTimer: null, stopActivity: null,\n });\n const live = (s) => s && session === s && connectionId() === s.id && isOpen();\n\n return createStore((set, get) => {\n const pruneStale = (search) => {\n const now = Date.now();\n search.stale = search.stale.filter((item) => now - item.at < STALE_REPLY_MS);\n };\n\n // Releases the active slot (timeout / server error) and moves on to the next query.\n const releaseUserSearch = (s, { stale = false } = {}) => {\n const search = s.search;\n const query = search.active;\n if (query === null) return;\n clearTimeout(search.timer);\n search.timer = null;\n search.active = null;\n search.deltas.clear();\n if (stale) search.stale = [...search.stale, { query, at: Date.now() }].slice(-5);\n if (session !== s) return;\n if (!query) set({ presenceStatus: 'error' });\n else if (query === get().userSearchQuery) set({ userSearchStatus: 'error' });\n pumpUserSearch(s);\n };\n\n // The server does not echo query/request IDs. Serialize searches on each connection\n // and keep only the latest queued text query, separately from presence refreshes.\n const pumpUserSearch = (s) => {\n const search = s.search;\n if (search.active !== null || !search.queue.length || !live(s)) return;\n const query = search.queue.shift();\n search.active = query;\n search.deltas.clear();\n if (!query) set({ presenceStatus: 'loading' });\n else if (query === get().userSearchQuery) set({ userSearchStatus: 'loading' });\n send('SEARCH_USERS', { query });\n search.timer = setTimeout(() => {\n if (session !== s || search.active !== query) return;\n // Free the slot; the untagged late reply is discarded via search.stale.\n releaseUserSearch(s, { stale: true });\n }, SEARCH_TIMEOUT_MS);\n };\n\n // Activity detector, one per connection. Listeners only record input; ACTIVITY is\n // throttled to once a minute, except when leaving 'away' (sent right away).\n const startActivityTracker = (s) => {\n if (typeof window === 'undefined') return;\n // The connect itself counts as activity on the server.\n let lastSentAt = Date.now();\n let lastInputAt = lastSentAt;\n const sendActivity = () => {\n if (!live(s)) return;\n send('ACTIVITY', {});\n lastSentAt = Date.now();\n };\n const onInput = () => {\n lastInputAt = Date.now();\n if (get().myPresence.status === 'away' && lastInputAt - lastSentAt > 5000) sendActivity();\n };\n const onVisibility = () => { if (document.visibilityState === 'visible') onInput(); };\n const options = { passive: true };\n ACTIVITY_EVENTS.forEach((name) => window.addEventListener(name, onInput, options));\n document.addEventListener('visibilitychange', onVisibility, options);\n const interval = setInterval(() => {\n if (!live(s)) return;\n if (lastInputAt > lastSentAt && Date.now() - lastSentAt >= 60000) sendActivity();\n }, 15000);\n s.stopActivity = () => {\n clearInterval(interval);\n ACTIVITY_EVENTS.forEach((name) => window.removeEventListener(name, onInput, options));\n document.removeEventListener('visibilitychange', onVisibility, options);\n };\n };\n\n const endSession = () => {\n const s = session;\n if (!s) return;\n session = null;\n clearTimeout(s.search.timer);\n clearInterval(s.presenceTimer);\n s.stopActivity?.();\n };\n\n const startSession = () => {\n endSession();\n const s = newSession(connectionId());\n session = s;\n initChatSounds();\n s.presenceTimer = setInterval(() => { if (live(s)) get().searchUsers(''); }, PRESENCE_SYNC_MS);\n startActivityTracker(s);\n };\n\n const onStatus = (status, previous) => {\n if (status === 'connected') {\n if (!session || session.id !== connectionId()) startSession();\n return;\n }\n if (previous === 'connected' || session) {\n // Connection lost: search slots and presence belong to the old connection.\n get().resetUserSearch();\n endSession();\n games.getState().markDisconnected?.(identity().scope);\n }\n };\n\n const receiveMessage = (parsed) => {\n // Sound/notification only for incoming (not own, not optimistic) messages.\n const ids = ownIds();\n const ownId = identity().userId;\n const senderId = parsed.user_id ?? parsed.payload?.user_id ?? parsed.data?.user_id;\n const isIncoming = senderId != null && ownId != null && !ids.includes(String(senderId));\n // Register the private conversation even if PRIVATE_INVITED was missed (e.g. after reconnect).\n const roomKey = String(parsed.room_id ?? parsed.data?.room_id ?? parsed.payload?.room_id ?? '');\n const parts = roomKey.startsWith('private_') ? roomKey.slice('private_'.length).split('_') : [];\n if (parts.length === 2 && parts.includes(ownId)) {\n const otherId = parts.find((id) => id !== ownId);\n if (otherId && get().privateRooms[otherId] !== roomKey) {\n set((state) => ({ privateRooms: { ...state.privateRooms, [otherId]: roomKey } }));\n }\n }\n if (senderId != null && parsed.username && !get().knownUsers[String(senderId)]) {\n set((state) => ({ knownUsers: { ...state.knownUsers, [String(senderId)]: { user_id: String(senderId), username: parsed.username } } }));\n }\n const nested = parsed.data ?? parsed.payload;\n const gameMessage = nested && typeof nested === 'object' ? { ...nested, ...parsed,\n message: parsed.message ?? nested.message, text: parsed.text ?? nested.text,\n room_id: parsed.room_id ?? nested.room_id, user_id: senderId,\n } : parsed;\n const gameText = gameMessage.message ?? gameMessage.text;\n // Edit/reaction frames modify an earlier message; they are never shown or counted.\n if (isMessageAction(gameText)) {\n const targetId = parseMessageAction(gameText)?.targetId;\n const original = targetId && get().chatMessages.map((item) => {\n const body = item.data ?? item.payload;\n return body && typeof body === 'object' ? { ...item, ...body } : item;\n }).find((item) => messageId(item) === targetId);\n extras.getState().apply(gameMessage, original || null);\n return;\n }\n // WebRTC signaling (LIRA_WEBRTC_V1:) is routed to peer links, never shown or counted.\n if (isWebrtcMessage(gameText)) {\n rtcSignals.emit({ userId: String(senderId ?? ''), roomId: String(gameMessage.room_id ?? ''), text: gameText });\n return;\n }\n const scope = identity().scope;\n if (typeof gameText === 'string' && gameText.startsWith(GAME_PREFIX) && String(gameMessage.room_id ?? '').startsWith('private_')) {\n games.getState().ingest(gameMessage, { scope, currentUserId: ownId });\n return;\n }\n set((state) => ({ chatMessages: appendBounded(state.chatMessages, parsed, maxMessages) }));\n const connectedAt = session?.connectedAt ?? Infinity;\n const isOptimistic = parsed.localOnly === true;\n const liveIncoming = unread.getState().receive(parsed, { ownIds: ids, connectedAt });\n const msgId = parsed.message_id ?? parsed.id ?? `${parsed.room_id}:${senderId}:${parsed.timestamp}`;\n if (!isIncoming || isOptimistic || !liveIncoming) return;\n requestNotification(msgId);\n if ((parsed.event || parsed.type) !== 'CHAT_MESSAGE') return;\n const message = normalizeChatMessage(parsed);\n const room = message.room_id;\n const s = session;\n void notifyDesktopMessage(message, {\n scope, room,\n id: message.message_id ?? message.id ?? `${room}:${senderId}:${message.timestamp}`,\n connectedAt,\n isCurrent: () => session === s && identity().userId === ownId,\n onClick: () => {\n if (session !== s || identity().userId == null) return;\n get().selectChat(room, String(room).startsWith('private') ? 'private' : 'group');\n onOpenChat?.(room);\n },\n });\n };\n\n // Returns true when the frame belongs to the chat domain (consumed).\n const handleFrame = (parsed) => {\n if (!parsed || typeof parsed !== 'object') return false;\n const { event: eventType, data, payload, type } = parsed;\n const kind = parsed.event ?? parsed.type;\n\n if (eventType === 'GROUPS_LIST' || type === 'groups_list') {\n const groups = data || payload;\n set((state) => ({ chatState: { ...state.chatState, availableGroups: groups } }));\n // Public channels stay subscribed while viewing other chats. Private rooms\n // need no CHAT_JOIN: they arrive through the user_{id} group.\n const s = session;\n (Array.isArray(groups) ? groups : []).forEach((group) => {\n const roomId = group?.id;\n if (roomId == null || String(roomId).startsWith('private_') || !s || s.joinedRooms.has(roomId)) return;\n s.joinedRooms.add(roomId);\n send('CHAT_JOIN', { room_id: roomId });\n });\n return true;\n }\n\n if (parsed.room_id || eventType === 'CHAT_MESSAGE' || type === 'CHAT_MESSAGE') {\n receiveMessage(parsed);\n return true;\n }\n\n // Subscription acks are not messages.\n if (eventType === 'CHAT_JOINED' || eventType === 'CHAT_LEFT') return true;\n\n if (kind === 'SEARCH_RESULTS') {\n get().receiveUserSearch(parsed);\n return true;\n }\n\n if (kind === 'USER_ONLINE') {\n const source = parsed.user ?? data?.user ?? payload?.user;\n const user = normalizeUsers([source])[0];\n if (user) {\n if (session?.search.active === '') session.search.deltas.set(user.user_id, user);\n set((state) => ({\n onlineUsers: [...state.onlineUsers.filter((item) => item.user_id !== user.user_id), user],\n knownUsers: rememberUsers(state.knownUsers, [user]),\n }));\n }\n return true;\n }\n\n if (kind === 'USER_OFFLINE') {\n const rawId = parsed.user_id ?? data?.user_id ?? payload?.user_id;\n if (rawId != null) {\n const userId = String(rawId);\n if (session?.search.active === '') session.search.deltas.set(userId, null);\n set((state) => ({ onlineUsers: state.onlineUsers.filter((user) => user.user_id !== userId) }));\n }\n return true;\n }\n\n if (kind === 'MY_STATUS') {\n const body = { ...(data ?? payload ?? {}), ...parsed };\n set((state) => ({ myPresence: {\n status: [...PRESENCE_STATUSES, 'invisible'].includes(body.status) ? body.status : state.myPresence.status,\n manual: MANUAL_STATUSES.includes(body.manual) ? body.manual : state.myPresence.manual,\n } }));\n return true;\n }\n\n if (kind === 'USER_STATUS') {\n const body = { ...(data ?? payload ?? {}), ...parsed };\n if (body.user_id == null || !PRESENCE_STATUSES.includes(body.status)) return true;\n const userId = String(body.user_id);\n const { status } = body;\n // A presence snapshot in flight would otherwise overwrite this change.\n if (session?.search.active === '') {\n const pending = session.search.deltas.get(userId);\n const current = pending === undefined ? get().onlineUsers.find((user) => user.user_id === userId) : pending;\n if (current) session.search.deltas.set(userId, { ...current, status });\n }\n set((state) => {\n const known = state.knownUsers[userId];\n const index = state.onlineUsers.findIndex((user) => user.user_id === userId);\n if (index === -1 && !known) return state;\n const onlineUsers = index === -1 ? state.onlineUsers\n : state.onlineUsers.map((user, i) => (i === index ? { ...user, status } : user));\n return { onlineUsers, knownUsers: known ? { ...state.knownUsers, [userId]: { ...known, status } } : state.knownUsers };\n });\n return true;\n }\n\n if (eventType === 'PRIVATE_RESOLVED') {\n const { room_id, recipient_user_id } = data || payload || {};\n if (room_id && recipient_user_id) {\n set((state) => ({ privateRooms: { ...state.privateRooms, [recipient_user_id]: room_id } }));\n get().selectChat(room_id, 'private');\n }\n return true;\n }\n\n if (eventType === 'PRIVATE_INVITED') {\n const { room_id, from_user_id } = data || payload || {};\n if (room_id && from_user_id) {\n set((state) => ({ privateRooms: { ...state.privateRooms, [from_user_id]: room_id } }));\n }\n return true;\n }\n\n if (kind === 'ERROR') {\n const errorBody = data ?? payload ?? {};\n const errorAction = parsed.action ?? errorBody.action;\n if (session && (errorAction === 'SEARCH_USERS' || String(errorBody.message ?? '').includes('SEARCH_USERS'))) {\n // Replies are ordered per connection: the error belongs to the oldest pending request.\n pruneStale(session.search);\n if (session.search.stale.length) session.search.stale.shift();\n else releaseUserSearch(session);\n }\n return false; // the host still reports the error\n }\n\n return false;\n };\n\n let detach = null;\n\n return {\n ...initialChatState(),\n\n // Subscribes to the transport. Idempotent; returns detach().\n attach: () => {\n if (detach) return detach;\n const offEvent = transport.onEvent(handleFrame);\n const offStatus = transport.onStatus(onStatus);\n if (isOpen()) startSession();\n detach = () => {\n offEvent?.();\n offStatus?.();\n endSession();\n detach = null;\n };\n return detach;\n },\n handleFrame,\n\n // Logout / identity change: release browser-only files and private conversation state.\n reset: () => {\n get().resetUserSearch();\n endSession();\n if (isOpen()) startSession();\n clearDesktopNotifications();\n get().chatMessages.forEach(revokeBlobs);\n set(initialChatState());\n extras.getState().reset();\n },\n\n //////////////////// --- SEARCH USER --- ////////////////////\n setUserSearchQuery: (value) => {\n const query = String(value ?? '').trim().toLowerCase();\n if (query === get().userSearchQuery) return;\n if (session) session.search.queue = session.search.queue.filter((item) => item === '');\n set({ userSearchQuery: query, userSearchResults: [], userSearchStatus: query ? 'loading' : 'idle' });\n },\n\n searchUsers: (value = '') => {\n const s = session;\n if (!live(s)) return;\n const query = String(value).trim().toLowerCase();\n if (query && query !== get().userSearchQuery) return;\n const search = s.search;\n if (search.active === query || search.queue.includes(query)) return;\n if (!query && Date.now() - search.lastPresence < 500) return;\n if (query) search.queue = search.queue.filter((item) => item === '');\n search.queue.push(query);\n pumpUserSearch(s);\n },\n\n receiveUserSearch: (message) => {\n const s = session;\n if (!s) return;\n const search = s.search;\n const body = message.data ?? message.payload;\n const result = body && typeof body === 'object' ? { ...body, ...message } : message;\n // is_full_list true <=> presence ('') request; false <=> text query; absent = unknown.\n const kind = result.is_full_list === true ? 'presence' : result.is_full_list === false ? 'text' : null;\n const kindOf = (item) => (item === '' ? 'presence' : 'text');\n pruneStale(search);\n if (search.stale.length) {\n if (!kind || kindOf(search.stale[0].query) === kind) {\n search.stale.shift(); // Late reply of a timed-out request.\n return;\n }\n // Replies are ordered: a reply matching the active request means the stale ones were lost.\n if (search.active === null || kindOf(search.active) !== kind) return;\n search.stale = [];\n }\n const query = search.active;\n if (query === null) return; // Unsolicited/duplicate uncorrelated response.\n if (kind && kindOf(query) !== kind) return; // Does not belong to the active request.\n clearTimeout(search.timer);\n search.timer = null;\n search.active = null;\n if (!Array.isArray(result.users)) {\n set(query ? { userSearchStatus: 'error' } : { presenceStatus: 'error' });\n pumpUserSearch(s);\n return;\n }\n const users = normalizeUsers(result.users);\n if (query === '') {\n const presence = new Map(users.map((user) => [user.user_id, user]));\n for (const [id, user] of search.deltas) {\n if (user) presence.set(id, user);\n else presence.delete(id);\n }\n const onlineUsers = [...presence.values()];\n search.lastPresence = Date.now();\n set((state) => ({ onlineUsers, presenceStatus: 'ready', knownUsers: rememberUsers(state.knownUsers, onlineUsers) }));\n } else if (query === get().userSearchQuery) {\n set((state) => ({ userSearchResults: users, userSearchStatus: 'ready', knownUsers: rememberUsers(state.knownUsers, users) }));\n }\n search.deltas.clear();\n pumpUserSearch(s);\n },\n\n resetUserSearch: () => {\n if (session) {\n clearTimeout(session.search.timer);\n session.search = newSession(session.id).search;\n }\n set({ onlineUsers: [], presenceStatus: 'idle', userSearchResults: [], userSearchQuery: '', userSearchStatus: 'idle' });\n },\n //////////////////// --- SEARCH USER --- ////////////////////\n\n // Manual presence: 'auto' | 'busy' | 'invisible'. The effective status arrives via MY_STATUS.\n setMyPresence: (manual) => {\n if (!MANUAL_STATUSES.includes(manual) || !send('SET_STATUS', { status: manual })) return false;\n set((state) => ({ myPresence: { ...state.myPresence, manual } }));\n return true;\n },\n\n //////////////////// --- ACCIONES DE CHAT --- ////////////////////\n joinChat: (roomId) => { send('CHAT_JOIN', { room_id: roomId }); },\n leaveChat: (roomId) => { send('CHAT_LEAVE', { room_id: roomId }); },\n\n sendChatMessage: (roomId, message, attachments = []) => {\n if (sendMessage) return sendMessage(roomId, message, attachments);\n if (attachments.length) return Promise.reject(new Error('Este transporte no admite adjuntos.'));\n return transport.request('CHAT_MESSAGE', { room_id: roomId, message, attachments: [] }).then(() => undefined);\n },\n\n setChatTab: (tab) => set((state) => ({ chatState: { ...state.chatState, activeTab: tab } })),\n\n // Selecting from a notification/list is not a read until its panel is visible.\n selectChat: (id, type) => set((state) => ({ chatState: { ...state.chatState, currentChat: { id, type } } })),\n\n searchOnlineUsers: (query) => { get().setUserSearchQuery(query); get().searchUsers(query); },\n createGroup: (name) => { send('CREATE_GROUP', { name }); },\n fetchGroups: () => { send('FETCH_GROUPS'); },\n openPrivateChat: (recipientUserId) => { send('OPEN_PRIVATE', { recipient_user_id: recipientUserId }); },\n //////////////////// --- ACCIONES DE CHAT --- ////////////////////\n };\n });\n}\n","import { useCallback, useMemo, useSyncExternalStore } from 'react';\nimport { useStore } from 'zustand';\nimport { useChatContext } from './ChatContext.js';\n\nconst noopUnsubscribe = () => {};\nconst IDLE = 'idle';\n\nexport const useChatConfig = () => useChatContext().config;\nexport const useChatTransport = () => useChatContext().transport ?? null;\n\nconst identity = (state) => state;\n// Selector over the provider's chat domain store (createChatStore).\nexport function useChatStore(selector = identity) {\n const { chatStore } = useChatContext();\n if (!chatStore) throw new Error('LiraChatProvider sin chatStore: pasa `transport` o `chatStore`');\n return useStore(chatStore, selector);\n}\nexport const useChatStoreApi = () => useChatContext().chatStore ?? null;\n\n// getStatus() may return a string or `{ status, connectionId }`.\nconst readStatus = (transport) => {\n const raw = transport?.getStatus?.();\n if (raw && typeof raw === 'object') return raw.status ?? IDLE;\n return raw ?? IDLE;\n};\nconst readConnectionId = (transport) => {\n const raw = transport?.getStatus?.();\n if (raw && typeof raw === 'object' && 'connectionId' in raw) return raw.connectionId ?? null;\n if (typeof transport?.getConnectionId === 'function') return transport.getConnectionId() ?? null;\n return transport?.connectionId ?? null;\n};\n\nexport function useChatConnection() {\n const transport = useChatTransport();\n const subscribe = useCallback((notify) => {\n if (!transport?.onStatus) return noopUnsubscribe;\n const unsubscribe = transport.onStatus(notify);\n return typeof unsubscribe === 'function' ? unsubscribe : noopUnsubscribe;\n }, [transport]);\n const status = useSyncExternalStore(subscribe, () => readStatus(transport), () => IDLE);\n const connectionId = useSyncExternalStore(subscribe, () => readConnectionId(transport), () => null);\n return { status, connectionId };\n}\n\nconst sumCounts = (counts) => {\n if (!counts || typeof counts !== 'object') return 0;\n let total = 0;\n for (const value of Object.values(counts)) total += Number(value) || 0;\n return total;\n};\n\n// `stores.unread`: zustand vanilla store or bound hook (anything with getState/subscribe).\nexport function useChatUnreadTotal() {\n const unread = useChatContext().stores?.unread;\n const valid = Boolean(unread && typeof unread.getState === 'function' && typeof unread.subscribe === 'function');\n const subscribe = useCallback(\n (notify) => (valid ? unread.subscribe(notify) : noopUnsubscribe),\n [unread, valid],\n );\n const getSnapshot = () => (valid ? sumCounts(unread.getState()?.counts) : 0);\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Current chat identity: `{ userId, ids, name, scope }`. userId/scope come from\n * `transport.getIdentity()` when available, else from `config.user`/`config.scope`.\n * Re-evaluated on render (config changes and connection status changes re-render consumers).\n */\nexport function useChatIdentity() {\n const { config, transport } = useChatContext();\n const { status } = useChatConnection();\n const fromTransport = transport?.getIdentity?.() ?? null;\n const user = config?.user ?? null;\n const userId = fromTransport?.userId ?? user?.id ?? null;\n const scope = fromTransport?.scope || config?.scope || (userId == null ? '' : String(userId));\n const idsKey = (user?.ids ?? []).join('|');\n const ids = useMemo(() => {\n const list = [...(idsKey ? idsKey.split('|') : [])];\n if (userId != null && !list.includes(String(userId))) list.unshift(String(userId));\n return list;\n }, [idsKey, userId]);\n return { userId: userId == null ? null : String(userId), ids, name: user?.name ?? null, scope, status };\n}\n","/**\n * Timing for the Confeti effect, in ms from the start of `effects/confetti.mp3`.\n * Cues match the recording's low-band hits (5450 is the riser into the final blast);\n * recalibrate them whenever the mix changes.\n */\nexport const CONFETTI_DURATION_MS = 7000;\n// Without a playing recording the visuals wait this long so both starts line up.\nexport const AUDIO_WAIT_MS = 400;\nexport const CONFETTI_CUES = Object.freeze([\n { at: 300, kind: 'cannons', power: 0.9 },\n { at: 1200, kind: 'left', power: 0.7 },\n { at: 1950, kind: 'right', power: 0.8 },\n { at: 2750, kind: 'rain', power: 0.6 },\n { at: 3400, kind: 'balloons', power: 0.9 },\n { at: 4550, kind: 'sky', power: 0.75 },\n { at: 5450, kind: 'swirl', power: 0.5 },\n { at: 5700, kind: 'finale', power: 1 },\n]);\n","/**\n * Timing for the Avalancha effect, in ms from the start of `effects/avalanche.mp3`.\n * The recording was produced against these cues (loudest hits measured at 250, 2300\n * and 3800 ms); recalibrate them whenever the mix changes.\n */\nexport const AVALANCHE_DURATION_MS = 7000;\n// Without a playing recording the visuals wait this long so both starts line up.\nexport const AUDIO_WAIT_MS = 400;\nexport const AVALANCHE_CUES = Object.freeze([\n { at: 250, kind: 'confetti', power: 0.8 },\n { at: 600, kind: 'money', power: 0.7 },\n { at: 1400, kind: 'cars', power: 0.8 },\n { at: 2300, kind: 'tanks', power: 0.9 },\n { at: 3100, kind: 'coins', power: 0.8 },\n { at: 3800, kind: 'mix', power: 1 },\n { at: 4800, kind: 'cars', power: 0.6 },\n { at: 5500, kind: 'finale', power: 1 },\n]);\n","import { THUNDER_DURATION_MS } from './thunder/timeline.js';\nimport { CONFETTI_DURATION_MS } from './confetti/timeline.js';\nimport { AVALANCHE_DURATION_MS } from './avalanche/timeline.js';\n\n/** Original, bundled effects. No remote assets or audio services are required. */\nexport const EFFECT_CATALOG = Object.freeze([\n { id: 'nudge', label: 'Zumbido', emoji: '⚡', durationMs: THUNDER_DURATION_MS, description: 'Una tormenta eléctrica con rayos, chispas y trueno.' },\n { id: 'pig-disco', label: 'Cerdito disco', emoji: '🐷', durationMs: 5200, description: 'Un cerdito original bailando su propia melodía.' },\n { id: 'confetti', label: 'Confeti', emoji: '🎉', durationMs: CONFETTI_DURATION_MS, description: 'Una fiesta 3D de confeti, globos, regalos y serpentinas.' },\n { id: 'avalanche', label: 'Avalancha', emoji: '🚀', durationMs: AVALANCHE_DURATION_MS, description: 'Una avalancha 3D de dinero, carros, tanques y confeti.' },\n]);\nexport function getChatEffect(id) { return EFFECT_CATALOG.find((effect) => effect.id === id); }\nexport const getEffect = getChatEffect;\n","import { chatSoundUrl } from '../assets/chatAssets.js';\n\n// `level` scales the configured effects volume (clamped to 1) for cinematic recordings.\nconst RECORDINGS = new Map([\n ['pig-disco', { file: 'cerdito_disco_original.mp3' }],\n ['nudge', { file: 'nudge.mp3', level: 2.6 }],\n ['confetti', { file: 'confetti.mp3', level: 2 }],\n // Approved recording pending; until it ships playback reports onBlocked and visuals use the wall clock.\n ['avalanche', { file: 'avalanche.mp3', level: 2 }],\n]);\n\n/**\n * Play an approved effect recording; return cleanup for close, mute or navigation.\n * `onPlaying(audio)` fires once playback really starts, so visuals can follow `audio.currentTime`.\n */\nexport function playEffectSound(effectId, { volume = 0.4, onBlocked, onPlaying } = {}) {\n const recording = RECORDINGS.get(effectId);\n if (!recording) return () => {};\n let audio;\n let stopped = false;\n let reported = false;\n const failed = () => {\n if (!stopped && !reported) { reported = true; onBlocked?.(); }\n };\n const playing = () => { if (!stopped) onPlaying?.(audio); };\n try {\n audio = new Audio(chatSoundUrl(`effects/${recording.file}`));\n audio.volume = Math.max(0, Math.min(1, (Number(volume) || 0) * (recording.level ?? 1)));\n audio.preload = 'auto';\n audio.addEventListener('error', failed);\n audio.addEventListener('playing', playing);\n audio.play()?.catch(failed);\n } catch { failed(); }\n return () => {\n if (stopped) return;\n stopped = true;\n if (!audio) return;\n audio.removeEventListener('error', failed);\n audio.removeEventListener('playing', playing);\n audio.pause();\n audio.removeAttribute('src');\n audio.load();\n };\n}\n","// Canvas 2D storm used when `three` or WebGL is unavailable. Same API as thunderScene3d.\nimport { BOLT_LIFE_S, boltFlicker } from './timeline.js';\n\nconst rand = (min, max) => min + Math.random() * (max - min);\n\nfunction jagged(x1, y1, x2, y2, passes, spread) {\n let points = [[x1, y1], [x2, y2]];\n for (let pass = 0; pass < passes; pass += 1) {\n const next = [points[0]];\n for (let i = 1; i < points.length; i += 1) {\n const [ax, ay] = points[i - 1];\n const [bx, by] = points[i];\n const length = Math.hypot(bx - ax, by - ay);\n next.push([(ax + bx) / 2 + rand(-0.5, 0.5) * length * spread, (ay + by) / 2 + rand(-0.1, 0.1) * length * spread], [bx, by]);\n }\n points = next;\n }\n return points;\n}\n\nexport function createThunderScene2d(canvas) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Canvas 2D no disponible');\n let width = 1;\n let height = 1;\n let flash = 0;\n const bolts = [];\n const sparks = [];\n\n const path = (points) => {\n ctx.beginPath();\n points.forEach(([x, y], index) => (index ? ctx.lineTo(x, y) : ctx.moveTo(x, y)));\n };\n\n return {\n strike(power = 1, x = 0) {\n const startX = width * (0.5 + x * 0.35) + rand(-30, 30);\n const endX = startX + rand(-width * 0.2, width * 0.2);\n const endY = height * rand(0.65, 0.95);\n const main = jagged(startX, -10, endX, endY, 6, 0.4);\n const branches = Array.from({ length: 2 + Math.round(power * 2) }, () => {\n const [bx, by] = main[Math.floor(rand(0.15, 0.7) * main.length)];\n return jagged(bx, by, bx + rand(-90, 90), by + rand(60, 160), 4, 0.45);\n });\n bolts.push({ main, branches, power, age: 0 });\n for (let i = 0; i < 70 * power; i += 1) {\n sparks.push({ x: endX, y: endY, vx: rand(-260, 260), vy: rand(-320, -40), life: rand(0.4, 1), max: 1 });\n }\n flash = Math.max(flash, power);\n },\n render(dt) {\n flash = Math.max(0, flash - dt * 3.2);\n ctx.clearRect(0, 0, width, height);\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n for (let i = bolts.length - 1; i >= 0; i -= 1) {\n const bolt = bolts[i];\n bolt.age += dt;\n if (bolt.age >= BOLT_LIFE_S) { bolts.splice(i, 1); continue; }\n const opacity = boltFlicker(bolt.age);\n [[bolt.main, 1], ...bolt.branches.map((branch) => [branch, 0.45])].forEach(([points, scale]) => {\n path(points);\n ctx.shadowColor = '#8fb4ff';\n ctx.shadowBlur = 24;\n ctx.strokeStyle = `rgba(127,168,255,${0.45 * opacity})`;\n ctx.lineWidth = 9 * scale * (0.6 + bolt.power);\n ctx.stroke();\n ctx.shadowBlur = 0;\n ctx.strokeStyle = `rgba(255,255,255,${opacity})`;\n ctx.lineWidth = 2.2 * scale * (0.6 + bolt.power);\n ctx.stroke();\n });\n }\n for (let i = sparks.length - 1; i >= 0; i -= 1) {\n const spark = sparks[i];\n spark.life -= dt;\n if (spark.life <= 0) { sparks.splice(i, 1); continue; }\n spark.vy += 520 * dt;\n spark.x += spark.vx * dt;\n spark.y += spark.vy * dt;\n const t = spark.life / spark.max;\n ctx.fillStyle = `rgba(255,${Math.round(150 + 105 * t)},${Math.round(90 + 165 * t)},${t})`;\n ctx.fillRect(spark.x, spark.y, 2.5, 2.5);\n }\n if (flash > 0) {\n ctx.fillStyle = `rgba(185,200,255,${flash * 0.18})`;\n ctx.fillRect(0, 0, width, height);\n }\n },\n resize(nextWidth, nextHeight) {\n const ratio = Math.min(2, window.devicePixelRatio || 1);\n width = nextWidth;\n height = nextHeight;\n canvas.width = Math.round(width * ratio);\n canvas.height = Math.round(height * ratio);\n ctx.setTransform(ratio, 0, 0, ratio, 0, 0);\n },\n dispose() {\n bolts.length = 0;\n sparks.length = 0;\n },\n };\n}\n","import React, { useEffect, useRef } from 'react';\nimport { AUDIO_WAIT_MS, THUNDER_CUES } from './timeline.js';\nimport { createThunderScene2d } from './thunderScene2d.js';\n\nconst SHAKE_STEPS = 9;\n\nfunction shake(target, power) {\n if (!target?.animate) return null;\n const frames = Array.from({ length: SHAKE_STEPS }, (_, step) => {\n const k = power * (1 - step / SHAKE_STEPS);\n return { transform: `translate(${(Math.random() - 0.5) * 22 * k}px, ${(Math.random() - 0.5) * 14 * k}px) rotate(${(Math.random() - 0.5) * 1.6 * k}deg)` };\n });\n frames.push({ transform: 'none' });\n return target.animate(frames, { duration: 420 + power * 260, easing: 'ease-out' });\n}\n\n/**\n * Storm scene for the Zumbido effect. `clockRef.current()` returns the recording's\n * playback time in ms once it plays, so strikes land on the audio's transients.\n */\nexport default function ThunderEffect({ clockRef, targetRef, waitForAudio = true }) {\n const hostRef = useRef(null);\n const flashRef = useRef(null);\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return undefined;\n const reducedMotion = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n const mountedAt = performance.now();\n const animations = new Set();\n let scene = null;\n let canvas = null;\n let disposed = false;\n let frame = 0;\n let next = 0;\n let last = mountedAt;\n\n const track = (animation) => {\n if (!animation) return;\n animations.add(animation);\n animation.onfinish = () => animations.delete(animation);\n };\n // A canvas that failed to get a WebGL context cannot switch to 2D, so each scene gets its own.\n const mount = (factory) => {\n scene?.dispose();\n canvas?.remove();\n canvas = document.createElement('canvas');\n canvas.className = 'lira-thunder-canvas';\n host.prepend(canvas);\n scene = factory(canvas, { reducedMotion });\n scene.resize(host.clientWidth || 1, host.clientHeight || 1);\n };\n const fallback = () => {\n try { mount(createThunderScene2d); } catch { scene = null; }\n };\n import('./thunderScene3d.js')\n .then(({ createThunderScene }) => { if (!disposed) mount(createThunderScene); })\n .catch(() => { if (!disposed) fallback(); });\n\n const elapsed = () => {\n const audioTime = clockRef?.current?.();\n if (audioTime != null) return audioTime;\n const wall = performance.now() - mountedAt;\n return waitForAudio ? wall - AUDIO_WAIT_MS : wall;\n };\n const fire = ({ power, x }) => {\n scene?.strike(power, x);\n track(flashRef.current?.animate?.([{ opacity: reducedMotion ? 0.12 : 0.7 * power }, { opacity: 0 }], { duration: 420, easing: 'cubic-bezier(.1,.7,.3,1)' }));\n if (!reducedMotion) track(shake(targetRef?.current, power));\n };\n const tick = (now) => {\n const dt = Math.min(0.05, (now - last) / 1000);\n last = now;\n const time = elapsed();\n while (next < THUNDER_CUES.length && time >= THUNDER_CUES[next].at) fire(THUNDER_CUES[next++]);\n try { scene?.render(dt); } catch { fallback(); }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => scene?.resize(host.clientWidth || 1, host.clientHeight || 1));\n observer?.observe(host);\n return () => {\n disposed = true;\n cancelAnimationFrame(frame);\n observer?.disconnect();\n animations.forEach((animation) => animation.cancel());\n scene?.dispose();\n canvas?.remove();\n };\n }, [clockRef, targetRef, waitForAudio]);\n return <div ref={hostRef} className=\"lira-thunder\" aria-hidden=\"true\"><div ref={flashRef} className=\"lira-thunder-flash\" /></div>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { AUDIO_WAIT_MS, CONFETTI_CUES } from './timeline.js';\n\nconst prefersReducedMotion = () => typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n/**\n * 3D party for the Confeti effect. `clockRef.current()` returns the recording's playback\n * time in ms once it plays, so bursts land on the audio's hits. Reduced motion, missing\n * `three` or WebGL render `fallback` (the CSS confetti) instead.\n */\nexport default function ConfettiEffect({ clockRef, waitForAudio = true, fallback = null }) {\n const hostRef = useRef(null);\n const flashRef = useRef(null);\n const [useFallback, setUseFallback] = useState(prefersReducedMotion);\n useEffect(() => {\n const host = hostRef.current;\n if (useFallback || !host) return undefined;\n const mountedAt = performance.now();\n const animations = new Set();\n let scene = null;\n let canvas = null;\n let disposed = false;\n let frame = 0;\n let next = 0;\n let last = mountedAt;\n let lastTime = -Infinity;\n\n const onContextLost = (event) => { event.preventDefault(); setUseFallback(true); };\n const track = (animation) => {\n if (!animation) return;\n animations.add(animation);\n animation.onfinish = () => animations.delete(animation);\n };\n import('./confettiScene3d.js')\n .then(({ createConfettiScene }) => {\n if (disposed) return;\n canvas = document.createElement('canvas');\n canvas.className = 'lira-confetti3d-canvas';\n canvas.addEventListener('webglcontextlost', onContextLost);\n host.prepend(canvas);\n scene = createConfettiScene(canvas);\n scene.resize(host.clientWidth || 1, host.clientHeight || 1);\n })\n .catch(() => { if (!disposed) setUseFallback(true); });\n\n const elapsed = () => {\n const audioTime = clockRef?.current?.();\n if (audioTime != null) return audioTime;\n const wall = performance.now() - mountedAt;\n return waitForAudio ? wall - AUDIO_WAIT_MS : wall;\n };\n const fire = ({ kind, power }) => {\n scene?.burst(kind, power);\n const peak = kind === 'finale' ? 0.55 : 0.18 * power;\n track(flashRef.current?.animate?.([{ opacity: peak }, { opacity: 0 }], { duration: kind === 'finale' ? 700 : 380, easing: 'ease-out' }));\n };\n const tick = (now) => {\n const dt = Math.min(0.05, (now - last) / 1000);\n last = now;\n if (scene) {\n const time = elapsed();\n // A late scene (slow import or shader compile) or a restarted recording resyncs\n // to the audio instead of replaying every overdue burst at once.\n if (lastTime === -Infinity || time < lastTime - 500) {\n next = CONFETTI_CUES.findIndex((cue) => cue.at >= time - 250);\n if (next < 0) next = CONFETTI_CUES.length;\n }\n lastTime = time;\n while (next < CONFETTI_CUES.length && time >= CONFETTI_CUES[next].at) fire(CONFETTI_CUES[next++]);\n try { scene.render(dt); } catch { setUseFallback(true); return; }\n }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => scene?.resize(host.clientWidth || 1, host.clientHeight || 1));\n observer?.observe(host);\n return () => {\n disposed = true;\n cancelAnimationFrame(frame);\n observer?.disconnect();\n animations.forEach((animation) => animation.cancel());\n canvas?.removeEventListener('webglcontextlost', onContextLost);\n scene?.dispose();\n canvas?.remove();\n };\n }, [clockRef, waitForAudio, useFallback]);\n if (useFallback) return fallback;\n return <div ref={hostRef} className=\"lira-confetti3d\" aria-hidden=\"true\"><div ref={flashRef} className=\"lira-confetti3d-flash\" /></div>;\n}\n","import React from 'react';\nimport { AVALANCHE_CUES } from './timeline.js';\n\n// Deterministic PRNG (mulberry32) so every client builds the same pile.\nconst seeded = (seed) => () => {\n seed = (seed + 0x6d2b79f5) | 0;\n let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n};\n\n// s: size factor, hop: bounce height (% of the host), dur: fall+bounce ms, spin/tilt: degrees.\nconst KINDS = {\n bill: { glyph: '💵', s: 1, hop: 4, dur: 1500, spin: 40, tilt: 18 },\n bag: { glyph: '💰', s: 1.1, hop: 5, dur: 1250, spin: 25, tilt: 10 },\n coin: { glyph: '🪙', s: 0.75, hop: 9, dur: 1100, spin: 60, tilt: 25 },\n race: { glyph: '🏎️', s: 1.45, hop: 3.5, dur: 1050, spin: 14, tilt: 6 },\n car: { glyph: '🚗', s: 1.4, hop: 3.5, dur: 1050, spin: 14, tilt: 6 },\n suv: { glyph: '🚙', s: 1.4, hop: 3, dur: 1050, spin: 12, tilt: 5 },\n tank: { glyph: '', s: 1.3, hop: 2, dur: 1000, spin: 10, tilt: 4 },\n helmet: { glyph: '🪖', s: 1.05, hop: 4, dur: 1150, spin: 30, tilt: 14 },\n party: { glyph: '🎉', s: 0.85, hop: 6, dur: 1600, spin: 50, tilt: 25 },\n star: { glyph: '⭐', s: 0.8, hop: 7, dur: 1650, spin: 90, tilt: 30 },\n};\n// Pieces per cue at power 1, cycling through `kinds`.\nconst CUE_MIX = {\n confetti: { base: 6, kinds: ['party', 'star'] },\n money: { base: 10, kinds: ['bill', 'bag', 'bill'] },\n cars: { base: 5, kinds: ['race', 'car', 'suv'] },\n tanks: { base: 4, kinds: ['tank', 'helmet'] },\n coins: { base: 8, kinds: ['coin'] },\n mix: { base: 6, kinds: ['bill', 'race', 'bag', 'party', 'coin', 'car'] },\n finale: { base: 8, kinds: ['bill'] },\n};\nconst LAND = 0.58; // fraction of `dur` where the first impact happens (matches the keyframes)\nconst BINS = 20;\n\nfunction buildLayout() {\n const rand = seeded(0x5eed7a1c);\n const range = (min, max) => min + rand() * (max - min);\n const pieces = [];\n const gusts = [];\n let tanks = 0;\n AVALANCHE_CUES.forEach((cue, cueIndex) => {\n const mix = CUE_MIX[cue.kind];\n if (!mix) return;\n const count = Math.max(1, Math.round(mix.base * cue.power));\n const spread = cue.kind === 'finale' ? 520 : 380;\n for (let i = 0; i < count; i += 1) {\n const type = KINDS[mix.kinds[i % mix.kinds.length]];\n const at = Math.round(cue.at + (i * spread) / count + range(0, 60));\n if (cue.kind === 'finale') {\n gusts.push({ id: `g${i}`, glyph: type.glyph, at, dur: Math.round(range(1100, 1450)), y: range(6, 58).toFixed(1), dy: range(12, 34).toFixed(1), rot: Math.round(range(-35, 35)), s: range(0.9, 1.15).toFixed(2) });\n continue;\n }\n const s = type.s * range(0.92, 1.08);\n pieces.push({\n id: `p${cueIndex}-${i}`,\n glyph: type.glyph,\n tank: type === KINDS.tank ? (tanks++ % 2 ? 'red' : 'green') : '',\n s,\n at,\n dur: Math.round(type.dur * range(0.9, 1.1)),\n hop: type.hop,\n x: range(6, 94),\n r0: Math.round(range(-type.spin, type.spin)),\n r1: Math.round(range(-type.tilt, type.tilt)),\n flip: rand() < 0.5 ? -1 : 1,\n });\n }\n });\n // Rough heightmap: later landings rest on earlier ones (units = base piece size).\n const heights = new Array(BINS).fill(0);\n [...pieces].sort((a, b) => a.at + a.dur * LAND - (b.at + b.dur * LAND)).forEach((piece) => {\n const half = piece.s * 6; // piece ≈ 12%·s of the host width\n const from = Math.max(0, Math.floor(((piece.x - half) / 100) * BINS));\n const to = Math.min(BINS - 1, Math.floor(((piece.x + half) / 100) * BINS));\n let base = 0;\n for (let b = from; b <= to; b += 1) base = Math.max(base, heights[b]);\n base = Math.min(base, 1.8);\n for (let b = from; b <= to; b += 1) heights[b] = base + piece.s * 0.45;\n piece.pile = base / piece.s; // em of the piece's own font size\n });\n const finale = AVALANCHE_CUES.find((cue) => cue.kind === 'finale')?.at ?? Infinity;\n pieces.forEach((piece) => {\n // The finale gust blows left to right, so the left side of the pile goes first.\n piece.clearAt = Math.round(finale + 250 + piece.x * 4);\n piece.x = piece.x.toFixed(1);\n piece.s = piece.s.toFixed(2);\n piece.pile = piece.pile.toFixed(2);\n });\n const flashes = AVALANCHE_CUES\n .filter((cue) => cue.kind === 'tanks' || cue.kind === 'finale')\n .map((cue) => ({ id: `f${cue.at}`, at: cue.at, peak: cue.kind === 'finale' ? 0.5 : 0.3 * cue.power, dur: cue.kind === 'finale' ? 760 : 480 }));\n return { pieces, gusts, flashes };\n}\n\nconst LAYOUT = buildLayout();\n\n/**\n * CSS-only Avalancha: big emoji (and CSS tanks) fall with weight, bounce and pile up,\n * then the finale gust sweeps them away. `startMs` is the timeline time when this took\n * over (cues already passed start mid-flight via negative delays). `still` = static pile.\n */\nexport default function AvalancheFallback({ startMs = 0, still = false }) {\n const ms = (at) => `${Math.round(at - startMs)}ms`;\n return <div className={`lira-avalanche-fallback${still ? ' lira-avalanche-fallback--still' : ''}`} aria-hidden=\"true\">\n {LAYOUT.pieces.map((p) => <span key={p.id} className=\"lira-avalanche-fb-col\" style={{ left: `${p.x}%`, '--delay': ms(p.at), '--dur': `${p.dur}ms`, '--hop': `-${p.hop}%`, '--clear': ms(p.clearAt) }}>\n <span className={p.tank ? `lira-avalanche-fb-piece lira-avalanche-fb-tank lira-avalanche-fb-tank--${p.tank}` : 'lira-avalanche-fb-piece'} style={{ '--s': p.s, '--pile': `${p.pile}em`, '--r0': `${p.r0}deg`, '--r1': `${p.r1}deg`, '--flip': p.flip }}>{p.glyph}</span>\n </span>)}\n {!still && LAYOUT.gusts.map((g) => <span key={g.id} className=\"lira-avalanche-fb-gust\" style={{ '--s': g.s, '--delay': ms(g.at), '--dur': `${g.dur}ms`, '--dy': `${g.dy}%` }}>\n <span className=\"lira-avalanche-fb-bill\" style={{ top: `${g.y}%`, '--rot': `${g.rot}deg` }}>{g.glyph}</span>\n </span>)}\n {!still && LAYOUT.flashes.filter((f) => f.at >= startMs).map((f) => <span key={f.id} className=\"lira-avalanche-fb-flash\" style={{ '--delay': ms(f.at), '--dur': `${f.dur}ms`, '--peak': f.peak }} />)}\n </div>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { AUDIO_WAIT_MS, AVALANCHE_CUES } from './timeline.js';\nimport AvalancheFallback from './AvalancheFallback.jsx';\nimport './avalanche.css';\n\nconst prefersReducedMotion = () => typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nconst flashOf = ({ kind, power }) => {\n if (kind === 'finale') return { peak: 0.6, duration: 760 };\n if (kind === 'tanks') return { peak: 0.34 * power, duration: 480 };\n return { peak: 0.16 * power, duration: 380 };\n};\n\n/**\n * 3D Avalancha (money, cars, tanks, confetti). `clockRef.current()` returns the recording's\n * playback time in ms once it plays, so bursts land on the audio's hits. Reduced motion,\n * missing `three`/WebGL or a lost context render the built-in CSS fallback instead.\n */\nexport default function AvalancheEffect({ clockRef, waitForAudio = true }) {\n const hostRef = useRef(null);\n const flashRef = useRef(null);\n const [still] = useState(prefersReducedMotion);\n // Timeline ms at which the 2D fallback took over; null while 3D runs.\n const [fallbackAt, setFallbackAt] = useState(null);\n const fallback = still || fallbackAt != null;\n useEffect(() => {\n const host = hostRef.current;\n if (fallback || !host) return undefined;\n const mountedAt = performance.now();\n const animations = new Set();\n let scene = null;\n let canvas = null;\n let disposed = false;\n let frame = 0;\n let next = 0;\n let last = mountedAt;\n let lastTime = -Infinity;\n\n const elapsed = () => {\n const audioTime = clockRef?.current?.();\n if (audioTime != null) return audioTime;\n const wall = performance.now() - mountedAt;\n return waitForAudio ? wall - AUDIO_WAIT_MS : wall;\n };\n const toFallback = () => { if (!disposed) setFallbackAt((at) => at ?? elapsed()); };\n const onContextLost = (event) => { event.preventDefault(); toFallback(); };\n const track = (animation) => {\n if (!animation) return;\n animations.add(animation);\n animation.onfinish = () => animations.delete(animation);\n };\n import('./avalancheScene3d.js')\n .then(({ createAvalancheScene }) => {\n if (disposed) return;\n canvas = document.createElement('canvas');\n canvas.className = 'lira-avalanche-canvas';\n canvas.addEventListener('webglcontextlost', onContextLost);\n host.prepend(canvas);\n scene = createAvalancheScene(canvas);\n scene.resize(host.clientWidth || 1, host.clientHeight || 1);\n })\n .catch(toFallback);\n\n const fire = (cue) => {\n scene?.burst(cue.kind, cue.power);\n const { peak, duration } = flashOf(cue);\n track(flashRef.current?.animate?.([{ opacity: peak }, { opacity: 0 }], { duration, easing: 'ease-out' }));\n };\n const tick = (now) => {\n const dt = Math.min(0.05, (now - last) / 1000);\n last = now;\n if (scene) {\n const time = elapsed();\n // A late scene (slow import or shader compile) or a restarted recording resyncs\n // to the audio instead of replaying every overdue burst at once.\n if (lastTime === -Infinity || time < lastTime - 500) {\n next = AVALANCHE_CUES.findIndex((cue) => cue.at >= time - 250);\n if (next < 0) next = AVALANCHE_CUES.length;\n }\n lastTime = time;\n while (next < AVALANCHE_CUES.length && time >= AVALANCHE_CUES[next].at) fire(AVALANCHE_CUES[next++]);\n try { scene.render(dt); } catch { toFallback(); return; }\n }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => scene?.resize(host.clientWidth || 1, host.clientHeight || 1));\n observer?.observe(host);\n return () => {\n disposed = true;\n cancelAnimationFrame(frame);\n observer?.disconnect();\n animations.forEach((animation) => animation.cancel());\n canvas?.removeEventListener('webglcontextlost', onContextLost);\n scene?.dispose();\n canvas?.remove();\n };\n }, [clockRef, waitForAudio, fallback]);\n if (fallback) return <AvalancheFallback startMs={fallbackAt ?? 0} still={still} />;\n return <div ref={hostRef} className=\"lira-avalanche\" aria-hidden=\"true\"><div ref={flashRef} className=\"lira-avalanche-flash\" /></div>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { getChatEffect } from './catalog';\nimport { playEffectSound } from './effectAudio';\nimport ThunderEffect from './thunder/ThunderEffect.jsx';\nimport ConfettiEffect from './confetti/ConfettiEffect.jsx';\nimport AvalancheEffect from './avalanche/AvalancheEffect.jsx';\nimport './effects.css';\n\nconst CONFETTI = Array.from({ length: 220 }, (_, index) => ({\n left: `${((index * 61.8034) % 100).toFixed(2)}%`,\n top: `${(index * 43) % 100}%`,\n color: ['#ff72ad', '#9380ff', '#ffd65c', '#37d7b0', '#6fcaff', '#ff9b59'][index % 6],\n width: `${6 + (index * 7) % 8}px`,\n height: `${8 + (index * 11) % 14}px`,\n duration: `${2.2 + (index % 13) * .1}s`,\n delay: `${-((index * 137) % 3000) / 1000}s`,\n drift: `${((index * 23) % 180) - 90}px`,\n}));\n\nfunction Pig() {\n return <svg className=\"lira-effect-pig\" viewBox=\"0 0 240 250\" role=\"img\" aria-label=\"Cerdito bailarín original\">\n <ellipse cx=\"120\" cy=\"232\" rx=\"60\" ry=\"8\" fill=\"#392169\" opacity=\".2\" />\n <g className=\"lira-effect-pig-body\">\n <path d=\"M64 154Q27 136 31 111M176 154Q213 136 209 111\" fill=\"none\" stroke=\"#f58fab\" strokeWidth=\"17\" strokeLinecap=\"round\" />\n <path d=\"M94 193L86 222M146 193L154 222\" fill=\"none\" stroke=\"#f58fab\" strokeWidth=\"20\" strokeLinecap=\"round\" />\n <ellipse cx=\"120\" cy=\"158\" rx=\"49\" ry=\"51\" fill=\"#fbabc2\" />\n <path d=\"M83 61L72 22Q104 27 108 53M132 53Q137 27 168 22L157 66\" fill=\"#fbabc2\" stroke=\"#e27598\" strokeWidth=\"4\" strokeLinejoin=\"round\" />\n <ellipse cx=\"120\" cy=\"87\" rx=\"58\" ry=\"49\" fill=\"#ffc2d4\" />\n <path d=\"M81 80H109L105 94H87ZM131 80H159L153 94H135Z\" fill=\"#2d2148\" />\n <path d=\"M109 84H131\" stroke=\"#2d2148\" strokeWidth=\"5\" />\n <ellipse cx=\"120\" cy=\"106\" rx=\"23\" ry=\"16\" fill=\"#f18eac\" />\n <ellipse cx=\"111\" cy=\"106\" rx=\"3.8\" ry=\"5\" fill=\"#a54670\" /><ellipse cx=\"129\" cy=\"106\" rx=\"3.8\" ry=\"5\" fill=\"#a54670\" />\n <path d=\"M109 129Q120 138 131 129\" stroke=\"#a54670\" strokeWidth=\"3\" fill=\"none\" strokeLinecap=\"round\" />\n <path d=\"M94 153L120 177L146 153\" fill=\"none\" stroke=\"#fff3b5\" strokeWidth=\"6\" />\n <circle cx=\"120\" cy=\"178\" r=\"8\" fill=\"#ffd65c\" />\n </g>\n </svg>;\n}\n\nconst confettiFallback = CONFETTI.map((piece, index) => <i key={index} className={`lira-effect-confetti-piece lira-effect-confetti-piece--${index % 3}`} style={{ left: piece.left, '--static-top': piece.top, '--color': piece.color, width: piece.width, height: piece.height, '--duration': piece.duration, '--delay': piece.delay, '--drift': piece.drift }} />);\n\n// Scene per effect id; getChatEffect gates unknown ids before this renders.\nfunction EffectScene({ id, clockRef, targetRef, sound }) {\n switch (id) {\n case 'pig-disco':\n return <><div className=\"lira-effect-disco-ball\" /><Pig /><span className=\"lira-effect-note\">♪</span><span className=\"lira-effect-note lira-effect-note-two\">♫</span></>;\n case 'nudge':\n return <ThunderEffect clockRef={clockRef} targetRef={targetRef} waitForAudio={sound} />;\n case 'avalanche':\n return <AvalancheEffect clockRef={clockRef} waitForAudio={sound} />;\n default:\n return <ConfettiEffect clockRef={clockRef} waitForAudio={sound} fallback={confettiFallback} />;\n }\n}\n\nexport function EffectPlayer({ effectId, onClose, sound = true, volume = 0.4, targetRef }) {\n const effect = getChatEffect(effectId);\n const closeRef = useRef(onClose);\n const clockRef = useRef(null);\n const [blocked, setBlocked] = useState(false);\n const [fallDistance, setFallDistance] = useState(900);\n useEffect(() => {\n const target = targetRef?.current;\n const update = () => setFallDistance((target?.clientHeight || 800) + 100);\n update();\n if (!target || typeof ResizeObserver === 'undefined') return undefined;\n const observer = new ResizeObserver(update);\n observer.observe(target);\n return () => observer.disconnect();\n }, [targetRef]);\n closeRef.current = onClose;\n useEffect(() => {\n if (!effect) return undefined;\n const timer = setTimeout(() => closeRef.current?.(), effect.durationMs);\n const onKey = (event) => { if (event.key === 'Escape') closeRef.current?.(); };\n document.addEventListener('keydown', onKey);\n return () => { clearTimeout(timer); document.removeEventListener('keydown', onKey); };\n }, [effect]);\n useEffect(() => {\n setBlocked(false);\n clockRef.current = null;\n if (!sound || !effect) return undefined;\n const stop = playEffectSound(effect.id, {\n volume,\n onBlocked: () => setBlocked(true),\n onPlaying: (audio) => { clockRef.current = () => audio.currentTime * 1000; },\n });\n return () => { clockRef.current = null; stop(); };\n }, [effect, sound, volume]);\n if (!effect) return null;\n const player = <div className={`lira-effect-player lira-effect-${effect.id}`} role=\"region\" aria-label={`Efecto: ${effect.label}`} style={{ '--confetti-fall': `${fallDistance}px`, '--effect-duration': `${effect.durationMs}ms` }}>\n <div className=\"lira-effect-scene\" aria-hidden=\"true\">\n <EffectScene id={effect.id} clockRef={clockRef} targetRef={targetRef} sound={sound} />\n </div>\n <div className=\"lira-effect-caption\" role=\"status\">{effect.label}{blocked && <small>No se pudo reproducir el sonido</small>}</div>\n <button className=\"lira-effect-close\" type=\"button\" aria-label=\"Cerrar efecto\" onClick={onClose}>×</button>\n </div>;\n return targetRef?.current\n ? createPortal(player, targetRef.current)\n : <div className=\"lira-effect-standalone\">{player}</div>;\n}\nexport default EffectPlayer;\n","/** Text messages remain readable on clients without effects support. */\nexport const EFFECT_PREFIX = '[minicode-effect:v1]';\nconst COUNTDOWN_PREFIX = '[minicode-countdown:v1]';\nconst validCountdown = (value) => Number.isSafeInteger(value.endsAt) && Number.isFinite(new Date(value.endsAt).getTime()) && value.endsAt > value.sentAt && value.endsAt - value.sentAt <= 86400000 && typeof value.sound === 'boolean';\nconst IDS = new Set(['nudge', 'pig-disco', 'confetti', 'avalanche']);\nfunction createEffectId() {\n // Keep optional method calls out of parameter defaults: older consumer optimizers\n // can lose their receiver when lowering that syntax.\n const crypto = globalThis.crypto;\n if (crypto && typeof crypto.randomUUID === 'function') {\n try { return crypto.randomUUID(); } catch { /* Restricted browser context. */ }\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\nexport function encodeEffect({ effectId, id, sentAt = Date.now(), endsAt, sound = true }) {\n if (id === undefined) id = createEffectId();\n if (!IDS.has(effectId) || typeof id !== 'string' || !/^[\\w-]{1,100}$/.test(id) || !Number.isSafeInteger(sentAt) || sentAt <= 0) throw new Error('Efecto inválido');\n const label = { nudge: 'Zumbido', 'pig-disco': 'Cerdito disco', confetti: 'Confeti', avalanche: 'Avalancha' }[effectId];\n const event = { effectId, id, sentAt };\n if (endsAt !== undefined) {\n Object.assign(event, { endsAt, sound });\n if (!validCountdown(event)) throw new Error('Cuenta regresiva inválida (máximo 24 horas)');\n return `${COUNTDOWN_PREFIX}${JSON.stringify(event)}\\n⏳ Cuenta regresiva hasta ${new Date(endsAt).toISOString()} · una sorpresa al llegar a cero · abre este mensaje en un chat compatible.`;\n }\n return `${EFFECT_PREFIX}${JSON.stringify(event)}\\n✨ ${label} · abre este mensaje en un chat compatible para reproducirlo.`;\n}\nexport function decodeEffect(text) {\n if (typeof text !== 'string' || text.length > 1200) return null;\n const prefix = text.startsWith(COUNTDOWN_PREFIX) ? COUNTDOWN_PREFIX : text.startsWith(EFFECT_PREFIX) ? EFFECT_PREFIX : null;\n if (!prefix) return null;\n try {\n const value = JSON.parse(text.slice(prefix.length).split('\\n')[0]);\n if (!value || !IDS.has(value.effectId) || typeof value.id !== 'string' || !/^[\\w-]{1,100}$/.test(value.id) || !Number.isSafeInteger(value.sentAt) || value.sentAt <= 0) return null;\n if (prefix === COUNTDOWN_PREFIX && !validCountdown(value)) return null;\n return { effectId: value.effectId, id: value.id, sentAt: value.sentAt, ...(prefix === COUNTDOWN_PREFIX ? { endsAt: value.endsAt, sound: value.sound } : {}) };\n } catch { return null; }\n}\n\n/** A readable representation for quotes, clipboard and conversation previews. */\nexport function effectMessageText(text) {\n const effect = decodeEffect(text);\n if (!effect) return text;\n if (effect.endsAt) return `⏳ Cuenta regresiva · ${new Date(effect.endsAt).toLocaleString()} · una sorpresa al llegar a cero`;\n return `✨ ${{ nudge: 'Zumbido', 'pig-disco': 'Cerdito disco', confetti: 'Confeti', avalanche: 'Avalancha' }[effect.effectId]}`;\n}\n","// Coordination between the visible effect players (ChatEffects) and BackgroundEffects,\n// which plays only the recording of effects nobody can see: hidden tab, closed chat window\n// or another conversation. Module state is per page; claims in ChatEffects cover other tabs.\n\nconst foreground = new Map(); // `${scope}\\n${room}` -> mounted visible players\nconst preferences = new Map(); // scope -> { sound, auto } chosen in the effects picker\nconst pending = new Map(); // scope -> effect heard in the background, replayed on return\n\nconst key = (scope, room) => `${scope}\\n${room}`;\n\n/** Marks a room as on screen; returns the cleanup for unmount or when it stops being visible. */\nexport function setForegroundRoom(scope, room) {\n const id = key(scope, room);\n foreground.set(id, (foreground.get(id) ?? 0) + 1);\n return () => {\n const count = (foreground.get(id) ?? 1) - 1;\n if (count > 0) foreground.set(id, count); else foreground.delete(id);\n };\n}\n\nexport function isForegroundRoom(scope, room) {\n return typeof document !== 'undefined' && document.visibilityState === 'visible' && foreground.has(key(scope, room));\n}\n\nexport function setEffectPreferences(scope, value) { preferences.set(scope, value); }\nexport function getEffectPreferences(scope) { return preferences.get(scope) ?? {}; }\n\nexport function rememberBackgroundEffect(scope, effect) {\n pending.get(scope)?.stop?.();\n pending.set(scope, effect);\n}\n\n/** Takes the effect heard in the background for this room, stopping its recording. */\nexport function takeBackgroundEffect(scope, room, maxAgeMs) {\n const effect = pending.get(scope);\n if (!effect) return null;\n if (Date.now() - effect.sentAt > maxAgeMs) {\n pending.delete(scope);\n return null;\n }\n if (effect.room !== room) return null;\n pending.delete(scope);\n effect.stop?.();\n return effect;\n}\n","/* eslint-disable react/prop-types */\nimport { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { EFFECT_CATALOG } from './catalog.js';\nimport { ArrowUpRight, Check, Loader2, PartyPopper, Play, Rocket, Sparkles, Volume2, VolumeX, X, Zap } from 'lucide-react';\nimport EffectPlayer from './EffectPlayer.jsx';\nimport { isSoundEnabled, subscribeSoundPreference } from '../notifications/chatSounds.js';\nimport { decodeEffect } from './protocol.js';\nimport { setEffectPreferences, setForegroundRoom, takeBackgroundEffect } from './backgroundEffects.js';\nconst EffectsContext = createContext(null);\nconst subscribeVisibility = (listener) => {\n document.addEventListener('visibilitychange', listener);\n return () => document.removeEventListener('visibilitychange', listener);\n};\nconst isPageVisible = () => document.visibilityState === 'visible';\n// Best-effort same-origin claim; only visible conversations receive automatic effects.\nexport function claimAutoEffect(scope, id) {\n try {\n const key = `minicode-effects-seen:${scope}`;\n const raw = JSON.parse(localStorage.getItem(key) || '[]');\n const recent = Array.isArray(raw) ? raw.filter((entry) => Array.isArray(entry) && Date.now() - entry[1] < 60000).slice(-100) : [];\n if (recent.some((entry) => entry[0] === id)) return false;\n localStorage.setItem(key, JSON.stringify([...recent, [id, Date.now()]]));\n } catch { /* Storage is optional; the mounted timeline still deduplicates. */ }\n return true;\n}\nexport function ChatEffects({ children, roomId, scope, identityScope = scope, messages = [], currentUserIds = [], config = {}, visible = true, targetRef }) {\n const globalSound = useSyncExternalStore(subscribeSoundPreference, isSoundEnabled, () => false);\n const pageVisible = useSyncExternalStore(subscribeVisibility, isPageVisible, () => false);\n const [active, setActive] = useState(null);\n const [sound, setSound] = useState(config.sound !== false);\n const [auto, setAuto] = useState(config.autoPlay !== false);\n const ledger = useRef({ room: null, seen: new Set(), since: Date.now() });\n const playing = useRef(false);\n const lastAuto = useRef(new Map());\n const play = (effectId, { replace = false, sound: eventSound = true } = {}) => {\n if (config.enabled === false || (playing.current && !replace) || !EFFECT_CATALOG.some((item) => item.id === effectId)) return;\n playing.current = true; setActive({ effectId, key: Date.now(), sound: eventSound });\n };\n useEffect(() => { setSound(config.sound !== false); setAuto(config.autoPlay !== false); }, [config.sound, config.autoPlay]);\n useEffect(() => {\n const room = `${scope}:${roomId}`;\n const changed = ledger.current.room !== room;\n if (changed) { ledger.current = { room, seen: new Set(), since: Date.now() }; playing.current = false; setActive(null); }\n for (const message of messages) {\n const effect = decodeEffect(message.message ?? message.text);\n if (!effect || effect.endsAt || ledger.current.seen.has(effect.id)) continue;\n ledger.current.seen.add(effect.id);\n const age = Date.now() - effect.sentAt;\n if (!changed && auto && visible && document.visibilityState === 'visible'\n && !currentUserIds.includes(String(message.user_id)) && !message.localOnly\n && !message.history && !message.is_history && !message.replay && !message.optimistic\n && message.user_id != null && effect.sentAt >= ledger.current.since\n && age >= 0 && age <= (config.maxAgeMs ?? 10000)\n && Date.now() - (lastAuto.current.get(room) ?? 0) >= (config.cooldownMs ?? 5000)\n && claimAutoEffect(identityScope, effect.id)) {\n lastAuto.current.set(room, Date.now()); play(effect.effectId, { replace: true });\n }\n }\n // Bound memory; timestamps also prevent old entries from playing again.\n if (ledger.current.seen.size > 5000) ledger.current.seen = new Set([...ledger.current.seen].slice(-2500));\n }, [messages, roomId, scope, auto, visible, config.enabled, config.maxAgeMs, config.cooldownMs, identityScope, currentUserIds]);\n useEffect(() => { if (!visible || config.enabled === false) { playing.current = false; setActive(null); } }, [visible, config.enabled]);\n useEffect(() => { setEffectPreferences(identityScope, { sound, auto }); }, [identityScope, sound, auto]);\n // While on screen, BackgroundEffects leaves this room alone; an effect it played while the\n // tab was hidden or the chat closed replays here with its animation if it is still recent.\n useEffect(() => {\n if (!visible || !pageVisible || config.enabled === false || roomId == null) return undefined;\n const release = setForegroundRoom(identityScope, String(roomId));\n const missed = takeBackgroundEffect(identityScope, String(roomId), config.maxAgeMs ?? 10000);\n if (missed && auto) play(missed.effectId, { replace: true });\n return release;\n }, [visible, pageVisible, config.enabled, roomId, identityScope]);\n // Only arm future deadlines while this conversation is visible. Expired history stays quiet.\n useEffect(() => {\n if (!visible || !pageVisible || config.enabled === false || !auto) return undefined;\n const timers = [];\n for (const message of messages) {\n const event = decodeEffect(message.message ?? message.text);\n if (!event?.endsAt || event.endsAt <= Date.now() || message.localOnly || message.optimistic) continue;\n timers.push(setTimeout(() => {\n if (document.visibilityState !== 'visible' || Date.now() - event.endsAt > 1500) return;\n const room = `${scope}:${roomId}`;\n if (Date.now() - (lastAuto.current.get(room) ?? 0) < (config.cooldownMs ?? 5000)) return;\n if (!claimAutoEffect(identityScope, `countdown-${event.id}`)) return;\n lastAuto.current.set(room, Date.now());\n play(event.effectId, { replace: true, sound: event.sound });\n }, event.endsAt - Date.now()));\n }\n return () => timers.forEach(clearTimeout);\n }, [messages, roomId, scope, identityScope, visible, pageVisible, auto, config.enabled, config.cooldownMs]);\n const changeSound = (value) => {\n setSound(value);\n config.onPreferencesChange?.({ sound: value });\n };\n const changeAuto = (value) => {\n setAuto(value);\n config.onPreferencesChange?.({ autoPlay: value });\n };\n return <EffectsContext.Provider value={config.enabled === false ? null : { play, sound, setSound: changeSound, auto, setAuto: changeAuto, sessionKey: `${scope}:${roomId}` }}>\n {children}\n {active && visible && <EffectPlayer key={active.key} effectId={active.effectId} sound={active.sound && sound && globalSound} volume={config.volume ?? .35} targetRef={targetRef} onClose={() => { playing.current = false; setActive(null); }} />}\n </EffectsContext.Provider>;\n}\nfunction CountdownCard({ effect, item, context }) {\n const [now, setNow] = useState(Date.now);\n const mountedBeforeEnd = useRef(Date.now() < effect.endsAt);\n useEffect(() => {\n let timer;\n const tick = () => {\n const current = Date.now();\n setNow(current);\n if (current >= effect.endsAt + 1000) clearInterval(timer);\n };\n tick();\n if (Date.now() < effect.endsAt + 1000) timer = setInterval(tick, 250);\n return () => clearInterval(timer);\n }, [effect.endsAt]);\n const seconds = Math.max(0, Math.ceil((effect.endsAt - now) / 1000));\n const done = seconds === 0;\n const burst = done && mountedBeforeEnd.current && now - effect.endsAt < 900;\n return <div className={`chat-effect-card chat-countdown${seconds > 0 && seconds <= 10 ? ' is-urgent' : ''}${burst ? ' is-burst' : ''}`}>\n <span aria-hidden=\"true\">{done ? item.emoji : '⏳'}</span>\n <strong>{done ? 'Cuenta finalizada' : 'Se viene una sorpresa…'}</strong>\n <time className=\"chat-countdown__clock\" dateTime={new Date(effect.endsAt).toISOString()} aria-label={done ? 'Cuenta finalizada' : `${seconds} segundos restantes`}>{done ? '¡Tiempo!' : `${String(Math.floor(seconds / 60)).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}`}</time>\n <p>{done ? `${item.emoji} ${item.label}` : 'El efecto se revela al llegar a cero.'}</p>\n {done && <button type=\"button\" className=\"chat-btn\" disabled={!context} onClick={() => context?.play(effect.effectId, { sound: effect.sound })}>Reproducir efecto</button>}\n </div>;\n}\nexport function EffectCard({ effect }) {\n const context = useContext(EffectsContext);\n const item = EFFECT_CATALOG.find((entry) => entry.id === effect.effectId);\n if (effect.endsAt) return <CountdownCard key={effect.id} effect={effect} item={item} context={context} />;\n return <div className=\"chat-effect-card\"><span aria-hidden=\"true\">{item.emoji}</span><strong>{item.label}</strong><p>{item.description}</p><button type=\"button\" className=\"chat-btn\" disabled={!context} onClick={() => context?.play(effect.effectId)}>Reproducir efecto</button></div>;\n}\nexport function EffectPicker({ onSend, disabled, onClose }) {\n const context = useContext(EffectsContext);\n const [countdown, setCountdown] = useState(false);\n const [duration, setDuration] = useState('300');\n const [customDuration, setCustomDuration] = useState(false);\n const [customValue, setCustomValue] = useState('5');\n const [customUnit, setCustomUnit] = useState(60);\n const [finalEffect, setFinalEffect] = useState('pig-disco');\n const [countdownSound, setCountdownSound] = useState(true);\n const [sending, setSending] = useState(null);\n const [feedback, setFeedback] = useState(null);\n const pending = useRef(false);\n const mounted = useRef(true);\n const pickerRef = useRef(null);\n const latestContext = useRef(context);\n latestContext.current = context;\n useEffect(() => { setFeedback(null); }, [context?.sessionKey]);\n useEffect(() => {\n mounted.current = true;\n const closeOutside = (event) => {\n if (!pickerRef.current?.contains(event.target) && !event.target.closest?.('[aria-label=\"Efectos y zumbidos\"], .lira-effect-player')) onClose();\n };\n document.addEventListener('pointerdown', closeOutside);\n return () => { mounted.current = false; document.removeEventListener('pointerdown', closeOutside); };\n }, [onClose]);\n const durationSeconds = customDuration ? Number(customValue) * customUnit : Number(duration);\n const validDuration = Number.isSafeInteger(durationSeconds) && durationSeconds >= 1 && durationSeconds <= 86400;\n const selectedEffect = EFFECT_CATALOG.find((item) => item.id === finalEffect);\n const durationLabel = durationSeconds >= 60 && durationSeconds % 60 === 0 ? `${durationSeconds / 60} min` : `${durationSeconds} s`;\n const send = async (item, timed = false) => {\n if (disabled || pending.current || !context || (timed && !validDuration)) return;\n const sessionKey = context.sessionKey;\n pending.current = true;\n setSending(item.id);\n setFeedback(null);\n try {\n const result = await onSend(item.id, timed ? { durationMs: durationSeconds * 1000, sound: countdownSound } : undefined);\n if (!mounted.current || latestContext.current?.sessionKey !== sessionKey) return;\n if (!result?.ok) {\n setFeedback({ error: true, text: result?.error || 'No se pudo enviar. Inténtalo de nuevo.' });\n return;\n }\n setFeedback({ id: item.id, text: timed ? 'Cuenta regresiva enviada' : `${item.label} enviado` });\n if (!timed) latestContext.current.play(item.id, { replace: true });\n } catch (error) {\n if (mounted.current && latestContext.current?.sessionKey === sessionKey) setFeedback({ error: true, text: error.message || 'No se pudo enviar.' });\n } finally {\n pending.current = false;\n if (mounted.current) setSending(null);\n }\n };\n return <div ref={pickerRef} className={`chat-effects-picker${countdown ? ' chat-effects-picker--countdown' : ''}`} role=\"dialog\" aria-label=\"Efectos y zumbidos\">\n <div className=\"chat-effects-picker__header\">\n <div><strong><Sparkles size={15} aria-hidden=\"true\" /> Efectos y zumbidos</strong><p>Un toque para alegrar el chat.</p></div>\n <button type=\"button\" className=\"chat-effects-picker__close\" onClick={onClose} aria-label=\"Cerrar efectos\"><X size={16} /></button>\n </div>\n {!countdown && <div className=\"chat-effects-picker__list\" aria-label=\"Elige un efecto para enviarlo\">\n {EFFECT_CATALOG.map((item) => {\n const sent = feedback?.id === item.id;\n const Icon = { nudge: Zap, confetti: PartyPopper, avalanche: Rocket }[item.id] ?? null;\n const subtitle = { nudge: 'Llama su atención', 'pig-disco': 'Ponle ritmo a la conversación', confetti: 'Celebra una buena noticia', avalanche: 'Lanza una lluvia de premios' }[item.id];\n return <button key={item.id} type=\"button\" className={`chat-effects-picker__item chat-effects-picker__item--${item.id}${sent ? ' is-sent' : ''}`}\n disabled={disabled || sending !== null || !context} onClick={() => send(item)} aria-label={`Enviar ${item.label}`} aria-busy={sending === item.id}>\n <span className=\"chat-effects-picker__icon\" aria-hidden=\"true\">{Icon ? <Icon size={21} /> : item.emoji}</span>\n <span className=\"chat-effects-picker__copy\"><strong>{item.label}</strong><small>{subtitle}</small></span>\n <span className=\"chat-effects-picker__action\" aria-hidden=\"true\">{sending === item.id ? <Loader2 size={17} className=\"chat-effects-picker__spinner\" /> : sent ? <Check size={17} /> : <ArrowUpRight size={17} />}</span>\n </button>;\n })}\n </div>}\n <button type=\"button\" className={countdown ? 'chat-countdown-back' : 'chat-effects-picker__item'} aria-expanded={countdown} onClick={() => { setCountdown(!countdown); setFeedback(null); }}>\n {countdown ? '← Volver a efectos' : <><span className=\"chat-effects-picker__icon\" aria-hidden=\"true\">⏳</span><span className=\"chat-effects-picker__copy\"><strong>Cuenta regresiva</strong><small>Una sorpresa cuando llegue a cero</small></span></>}\n </button>\n {countdown && <form className=\"chat-countdown-form\" onSubmit={(event) => { event.preventDefault(); send(selectedEffect, true); }}>\n <div className=\"chat-countdown-form__body\">\n <div className=\"chat-countdown-form__title\"><span aria-hidden=\"true\">⏳</span><div><strong>Cuenta regresiva</strong><p>Elige cuándo y cómo sorprender.</p></div></div>\n <fieldset><legend>Duración</legend><div className=\"chat-countdown-choices chat-countdown-choices--duration\">\n {[['30', '30 s'], ['60', '1 min'], ['300', '5 min'], ['600', '10 min']].map(([value, label]) => <button key={value} type=\"button\" aria-pressed={!customDuration && duration === value} onClick={() => { setDuration(value); setCustomDuration(false); }}>{label}</button>)}\n <button type=\"button\" aria-pressed={customDuration} onClick={() => setCustomDuration(true)}>Otra</button>\n </div></fieldset>\n {customDuration && <div className=\"chat-countdown-custom\">\n <label>Tiempo<input autoFocus type=\"number\" min=\"1\" max={86400 / customUnit} step=\"1\" required value={customValue} onChange={(event) => setCustomValue(event.target.value)} /></label>\n <div className=\"chat-countdown-choices\" role=\"group\" aria-label=\"Unidad de tiempo\">{[[1, 'Segundos'], [60, 'Minutos']].map(([unit, label]) => <button key={unit} type=\"button\" aria-pressed={customUnit === unit} onClick={() => setCustomUnit(unit)}>{label}</button>)}</div>\n <small>Hasta 24 horas.</small>\n </div>}\n <fieldset><legend>Efecto al terminar</legend><div className=\"chat-countdown-choices chat-countdown-choices--effects\">\n {EFFECT_CATALOG.map((item) => <button key={item.id} type=\"button\" aria-pressed={finalEffect === item.id} onClick={() => setFinalEffect(item.id)}><span aria-hidden=\"true\">{item.emoji}</span><span>{item.id === 'pig-disco' ? 'Cerdito' : item.label}</span>{finalEffect === item.id && <Check size={12} aria-hidden=\"true\" />}</button>)}\n </div></fieldset>\n <div className=\"chat-countdown-tools\">\n <button className=\"chat-countdown-sound\" type=\"button\" role=\"switch\" aria-checked={countdownSound} onClick={() => setCountdownSound(!countdownSound)}>{countdownSound ? <Volume2 size={16} /> : <VolumeX size={16} />} Sonido<span className=\"chat-effects-picker__switch\" aria-hidden=\"true\" /></button>\n <button className=\"chat-countdown-preview\" type=\"button\" disabled={!context || sending !== null} onClick={() => context?.play(finalEffect, { replace: true, sound: countdownSound })}><Play size={14} aria-hidden=\"true\" /> Probar efecto</button>\n </div>\n </div>\n <div className=\"chat-countdown-form__footer\"><button className=\"chat-countdown-send\" type=\"submit\" disabled={disabled || sending !== null || !context || !validDuration}>\n {sending ? <><Loader2 size={16} className=\"chat-effects-picker__spinner\" aria-hidden=\"true\" /> Enviando…</> : <><span>Enviar cuenta{validDuration ? ` · ${durationLabel}` : ''}</span><span aria-hidden=\"true\">{selectedEffect.emoji}</span></>}\n </button></div>\n </form>}\n {context && !countdown && <div className=\"chat-effects-picker__preferences\">\n <button type=\"button\" role=\"switch\" aria-checked={context.sound} aria-label=\"Sonido de efectos\" onClick={() => context.setSound(!context.sound)}>\n {context.sound ? <Volume2 size={14} /> : <VolumeX size={14} />}<span>Sonido</span><span className=\"chat-effects-picker__switch\" aria-hidden=\"true\" />\n </button>\n <button type=\"button\" role=\"switch\" aria-checked={context.auto} aria-label=\"Reproducir nuevos efectos automáticamente\" title=\"Reproducir los efectos recibidos automáticamente\" onClick={() => context.setAuto(!context.auto)}>\n <Play size={13} /><span>Automático</span><span className=\"chat-effects-picker__switch\" aria-hidden=\"true\" />\n </button>\n </div>}\n <p className={`chat-effects-picker__feedback${feedback?.error ? ' is-error' : ''}`} role=\"status\" aria-live=\"polite\">\n {feedback && !feedback.error && <Check size={13} aria-hidden=\"true\" />}{feedback?.text || 'Los recibidos se pueden volver a reproducir.'}\n </p>\n </div>;\n}\n","import { useEffect, useRef } from 'react';\nimport { useChatContext } from '../provider/ChatContext.js';\nimport { useChatIdentity } from '../provider/hooks.js';\nimport { isSoundEnabled } from '../notifications/chatSounds.js';\nimport { claimAutoEffect } from './ChatEffects.jsx';\nimport { playEffectSound } from './effectAudio.js';\nimport { decodeEffect } from './protocol.js';\nimport { getEffectPreferences, isForegroundRoom, rememberBackgroundEffect } from './backgroundEffects.js';\n\n// Visible tabs get this long to claim an effect before a hidden one plays its sound.\nconst CLAIM_DELAY_MS = 300;\n\nconst field = (message, name) => message[name] ?? message.data?.[name] ?? message.payload?.[name];\n\n/**\n * Renders nothing. Plays the recording of incoming effects that no visible conversation\n * shows (hidden tab, closed chat, another room), like the new-message sound does.\n * Disabled with `effects.backgroundSound: false`.\n */\nexport default function BackgroundEffects() {\n const { config, chatStore } = useChatContext();\n const identity = useChatIdentity();\n const latest = useRef({ config, identity });\n latest.current = { config, identity };\n useEffect(() => {\n if (!chatStore?.subscribe) return undefined;\n const seen = new WeakSet();\n const lastByRoom = new Map();\n const timers = new Set();\n (chatStore.getState().chatMessages ?? []).forEach((message) => seen.add(message));\n\n const consider = (message) => {\n const effects = latest.current.config?.effects;\n if (!effects || effects.enabled === false || effects.backgroundSound === false || effects.sound === false || effects.autoPlay === false) return;\n const event = decodeEffect(field(message, 'message') ?? field(message, 'text'));\n if (event?.endsAt) return;\n if (!event) return;\n const { scope, ids } = latest.current.identity;\n const senderId = field(message, 'user_id');\n const room = String(field(message, 'room_id') ?? '');\n const age = Date.now() - event.sentAt;\n if (senderId == null || ids.includes(String(senderId)) || message.localOnly || message.history || message.is_history || message.replay || message.optimistic) return;\n if (!room.startsWith('private_') && effects.allowGroups !== true) return;\n if (age < 0 || age > (effects.maxAgeMs ?? 10000)) return;\n if (Date.now() - (lastByRoom.get(room) ?? 0) < (effects.cooldownMs ?? 5000)) return;\n const timer = setTimeout(() => {\n timers.delete(timer);\n const picker = getEffectPreferences(scope);\n if (isForegroundRoom(scope, room) || picker.sound === false || picker.auto === false || !isSoundEnabled()) return;\n if (!claimAutoEffect(scope, event.id)) return;\n lastByRoom.set(room, Date.now());\n const stop = playEffectSound(event.effectId, { volume: effects.volume ?? 0.35 });\n rememberBackgroundEffect(scope, { ...event, room, stop });\n }, CLAIM_DELAY_MS);\n timers.add(timer);\n };\n\n const unsubscribe = chatStore.subscribe((state) => {\n const messages = state.chatMessages ?? [];\n // New messages are appended, so walk back until the first one already handled.\n for (let i = messages.length - 1; i >= 0 && !seen.has(messages[i]); i -= 1) {\n seen.add(messages[i]);\n consider(messages[i]);\n }\n });\n return () => {\n unsubscribe();\n timers.forEach(clearTimeout);\n };\n }, [chatStore]);\n return null;\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { normalizeConfig } from '../config/normalizeConfig.js';\nimport { createStandaloneTransport } from '../core/transport/createStandaloneTransport.js';\nimport { createChatStore } from '../core/chat/createChatStore.js';\nimport BackgroundEffects from '../effects/BackgroundEffects.jsx';\nimport { ChatContext } from './ChatContext.js';\n\n// One provider = one chat instance. Options are read once; remount with `key` to change them.\nexport function LiraChatProvider({ config, transport: injectedTransport, stores, chatStore: injectedChatStore, children }) {\n const normalized = useMemo(() => normalizeConfig(config), [config]);\n // Latest config for the owned transport's identity (user/scope may change after login).\n const configRef = useRef(normalized);\n configRef.current = normalized;\n\n // Lazily owned transport: created once, only when none is injected and a URL is configured.\n const [ownedTransport] = useState(() => {\n if (injectedTransport || !normalized.websocket?.url) return null;\n const { websocket, auth } = normalized;\n return createStandaloneTransport({\n url: websocket.url,\n getToken: auth?.getToken,\n tokenParam: auth?.tokenParam,\n reconnect: websocket.reconnect,\n ping: websocket.ping,\n identity: () => {\n const { user, scope } = configRef.current;\n const userId = user?.id ?? null;\n return { userId, scope: scope ?? (userId == null ? '' : String(userId)) };\n },\n });\n });\n\n const transport = injectedTransport || ownedTransport;\n\n // Chat domain store: injected (host already attached it) or owned and attached here.\n const [ownedChatStore] = useState(() => (injectedChatStore || !transport ? null : createChatStore({ transport })));\n const chatStore = injectedChatStore || ownedChatStore;\n useEffect(() => (ownedChatStore ? ownedChatStore.getState().attach() : undefined), [ownedChatStore]);\n\n useEffect(() => {\n if (!ownedTransport) return undefined;\n ownedTransport.connect?.();\n return () => ownedTransport.close?.(); // never close an injected transport\n }, [ownedTransport]);\n\n const onConnectionChange = normalized.callbacks?.onConnectionChange;\n useEffect(() => {\n if (!transport?.onStatus || typeof onConnectionChange !== 'function') return undefined;\n const unsubscribe = transport.onStatus((status) => onConnectionChange(status));\n return typeof unsubscribe === 'function' ? unsubscribe : undefined;\n }, [transport, onConnectionChange]);\n\n const value = useMemo(() => ({ config: normalized, transport, chatStore, stores: stores ?? {} }), [normalized, transport, chatStore, stores]);\n\n return <ChatContext.Provider value={value}>{children}{chatStore && <BackgroundEffects />}</ChatContext.Provider>;\n}\n\nexport default LiraChatProvider;\n","// Contrato de transporte del chat (ver docs §2.3 y Anexo A §8.2).\n\n/**\n * @typedef {'idle'|'connecting'|'connected'|'disconnected'|'error'} TransportStatus\n */\n\n/**\n * @typedef {{ event?: string, type?: string, data?: any, payload?: any, [k: string]: any }} InboundFrame\n */\n\n/**\n * @typedef {Object} ChatTransport\n * @property {() => Promise<void>} connect\n * Abre la conexión (en el adaptador compartido delega en el host).\n * @property {(code?: number) => void} close\n * Cierre voluntario. El adaptador compartido NO cierra el socket del host.\n * @property {(action: string, payload?: object) => boolean} send\n * Fire-and-forget. Devuelve false si el socket no está OPEN; nunca lanza.\n * @property {(action: string, payload?: object, opts?: { timeoutMs?: number }) => Promise<InboundFrame>} request\n * Añade `request_id`, resuelve con CHAT_ACK y rechaza con ERROR correlado, timeout o cierre.\n * @property {(handler: (frame: InboundFrame) => boolean|void) => () => void} onEvent\n * El handler devuelve true si consumió el frame. Devuelve la función para desuscribirse.\n * @property {() => TransportStatus} getStatus\n * @property {(cb: (status: TransportStatus, prev: TransportStatus) => void) => () => void} onStatus\n * @property {() => string|null} getConnectionId\n * Cambia en cada reconexión.\n * @property {() => { userId: string|null, scope: string }} getIdentity\n * scope = `${backend}:${userId}`.\n */\n\nexport const TRANSPORT_STATUSES = Object.freeze(['idle', 'connecting', 'connected', 'disconnected', 'error']);\n\nconst REQUIRED_METHODS = [\n 'connect',\n 'close',\n 'send',\n 'request',\n 'onEvent',\n 'getStatus',\n 'onStatus',\n 'getConnectionId',\n 'getIdentity',\n];\n\n/**\n * Valida en desarrollo que `obj` cumple ChatTransport. Lanza con los miembros faltantes.\n * @param {any} obj\n * @returns {ChatTransport}\n */\nexport function assertTransport(obj) {\n if (!obj || typeof obj !== 'object') {\n throw new TypeError('[chat] transport inválido: se esperaba un objeto ChatTransport');\n }\n const missing = REQUIRED_METHODS.filter((name) => typeof obj[name] !== 'function');\n if (missing.length) {\n throw new TypeError(`[chat] transport inválido: faltan métodos ${missing.join(', ')}`);\n }\n return obj;\n}\n","const CUSTOMER_ID_KEY = 'lira-klipy-customer-id';\n\nlet memoryCustomerId = null;\n\nconst randomId = () => {\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n }\n } catch {\n // fall through\n }\n let hex = '';\n for (let i = 0; i < 32; i += 1) hex += Math.floor(Math.random() * 16).toString(16);\n return hex;\n};\n\n/** customer_id anónimo y estable por navegador, compartido por GIFs y stickers de KLIPY. */\nexport function getKlipyCustomerId() {\n try {\n const stored = localStorage.getItem(CUSTOMER_ID_KEY);\n if (stored) return stored;\n const id = memoryCustomerId || randomId();\n localStorage.setItem(CUSTOMER_ID_KEY, id);\n memoryCustomerId = id;\n return id;\n } catch {\n if (!memoryCustomerId) memoryCustomerId = randomId();\n return memoryCustomerId;\n }\n}\n","import { getKlipyCustomerId } from \"./klipyCustomer.js\";\n\n// Configuración del paquete: el host inyecta la app key vía configureKlipy(); nunca hardcodearla.\nconst config = { apiKey: \"\", locale: null, categoriesLocale: null };\nlet warnedMissingKey = false;\n\nexport function configureKlipy({ apiKey, locale, categoriesLocale } = {}) {\n if (apiKey !== undefined) config.apiKey = String(apiKey ?? \"\");\n if (locale !== undefined) config.locale = locale || null;\n if (categoriesLocale !== undefined) config.categoriesLocale = categoriesLocale || null;\n}\n\nconst getApiKey = () => {\n if (!config.apiKey && !warnedMissingKey && import.meta.env?.DEV) {\n warnedMissingKey = true;\n console.warn(\"[klipy] API key no configurada (configureKlipy): GIFs y stickers no cargarán.\");\n }\n return config.apiKey;\n};\n\n/** Raíz de la API calculada por request con la key configurada. */\nexport const getKlipyApiRoot = () => `https://api.klipy.com/api/v1/${getApiKey()}`;\nconst getBaseUrl = () => `${getKlipyApiRoot()}/gifs`;\n\nconst ERROR_MESSAGE = \"Error consultando KLIPY\";\nconst TRUSTED_HOSTS = new Set([\"static.klipy.com\", \"media.klipy.com\", \"cdn.klipy.com\"]);\nconst PREVIEW_SIZES = [\"sm\", \"xs\"];\nconst FULL_SIZES = [\"hd\", \"md\"];\n\n/**\n * Locale para trending/search. Según docs.klipy.com, `locale` en esos endpoints es\n * un código de país ISO 3166-1 alpha-2 (ejemplos de la doc: \"ge\", \"us\", \"uk\"), no un\n * código de idioma; por eso se usa \"do\" (República Dominicana) para usuarios es/LatAm.\n */\nexport const GIF_LOCALE = \"do\";\n\n/**\n * Locale para categorías. La doc de /gifs/categories exige formato xx_YY\n * (ISO 639-1 idioma + ISO 3166-1 alpha-2 país).\n */\nexport const GIF_CATEGORIES_LOCALE = \"es_DO\";\n\nexport const getKlipyLocale = () => config.locale || GIF_LOCALE;\nexport const getKlipyCategoriesLocale = () => config.categoriesLocale || GIF_CATEGORIES_LOCALE;\n\nconst categoriesCache = new Map();\n\nexport function isTrustedKlipyUrl(value) {\n if (typeof value !== \"string\" || !value) return false;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\"\n && !url.username\n && !url.password\n && TRUSTED_HOSTS.has(url.hostname.toLowerCase());\n } catch {\n return false;\n }\n}\n\nconst pickGif = (file, sizes) => {\n for (const size of sizes) {\n const media = file?.[size]?.gif;\n if (isTrustedKlipyUrl(media?.url)) return media;\n }\n return null;\n};\n\nconst toDimension = (value) => {\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : null;\n};\n\nconst normalizeItem = (item) => {\n if (!item || item.type === \"ad\") return null;\n const full = pickGif(item.file, FULL_SIZES);\n const preview = pickGif(item.file, PREVIEW_SIZES) || full;\n if (!full || !preview) return null;\n return {\n id: item.id,\n slug: item.slug,\n title: item.title || \"\",\n tags: Array.isArray(item.tags)\n ? item.tags.filter((tag) => typeof tag === \"string\" && tag.trim()).map((tag) => tag.trim())\n : [],\n preview: preview.url,\n url: full.url,\n width: toDimension(preview.width),\n height: toDimension(preview.height),\n };\n};\n\nconst request = async (path, params, signal) => {\n const query = params ? `?${new URLSearchParams(params)}` : \"\";\n const response = await fetch(`${getBaseUrl()}${path}${query}`, { signal });\n if (!response.ok) throw new Error(ERROR_MESSAGE);\n return response.json();\n};\n\nconst toPage = (json, perPage) => {\n const raw = Array.isArray(json?.data?.data) ? json.data.data : [];\n const items = raw.map(normalizeItem).filter(Boolean);\n const hasNext = json?.data?.has_next;\n return {\n items,\n hasMore: typeof hasNext === \"boolean\" ? hasNext : raw.length >= perPage,\n };\n};\n\nconst pageParams = (page, perPage) => ({\n page: String(page),\n per_page: String(perPage),\n});\n\n// trending/search: ISO 3166-1 alpha-2 (2 letras).\nconst withCountryLocale = (params, locale) => {\n const value = String(locale ?? \"\").trim();\n if (/^[a-z]{2}$/i.test(value)) params.locale = value.toLowerCase();\n return params;\n};\n\n// categories: xx_YY. Acepta GIF_LOCALE como alias del locale de categorías.\nconst toCategoriesLocale = (locale) => {\n const value = String(locale ?? \"\").trim();\n if (/^[a-z]{2}_[a-z]{2}$/i.test(value)) {\n const [lang, country] = value.split(\"_\");\n return `${lang.toLowerCase()}_${country.toUpperCase()}`;\n }\n if (value.toLowerCase() === getKlipyLocale().toLowerCase()) return getKlipyCategoriesLocale();\n return null;\n};\n\n/** API legacy: devuelve solo el array de items. */\nexport async function searchGifs(query = \"\", page = 1, signal) {\n const endpoint = query.trim() ? \"search\" : \"trending\";\n\n const params = new URLSearchParams({\n page: String(page),\n per_page: \"20\",\n });\n\n if (query.trim()) {\n params.set(\"q\", query.trim());\n }\n\n const response = await fetch(\n `${getBaseUrl()}/${endpoint}?${params}`, { signal }\n );\n\n if (!response.ok) {\n throw new Error(ERROR_MESSAGE);\n }\n\n const json = await response.json();\n\n return (json.data?.data || [])\n .filter(item => item.type !== \"ad\")\n .map(item => ({\n id: item.id,\n slug: item.slug,\n title: item.title,\n preview: item.file?.sm?.gif?.url,\n url: item.file?.hd?.gif?.url,\n }))\n .filter(item => item.url);\n}\n\nexport async function fetchTrendingGifs({ page = 1, perPage = 24, locale, signal } = {}) {\n const params = withCountryLocale({\n ...pageParams(page, perPage),\n customer_id: getKlipyCustomerId(),\n }, locale);\n const json = await request(\"/trending\", params, signal);\n return toPage(json, perPage);\n}\n\nexport async function searchGifsPage({ query, page = 1, perPage = 24, locale, signal } = {}) {\n const q = String(query ?? \"\").trim();\n if (!q) return fetchTrendingGifs({ page, perPage, locale, signal });\n const params = withCountryLocale({\n ...pageParams(page, perPage),\n q,\n customer_id: getKlipyCustomerId(),\n }, locale);\n const json = await request(\"/search\", params, signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchRecentGifs({ page = 1, perPage = 24, signal } = {}) {\n const customerId = encodeURIComponent(getKlipyCustomerId());\n const json = await request(`/recent/${customerId}`, pageParams(page, perPage), signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchGifCategories({ locale, signal } = {}) {\n const apiLocale = toCategoriesLocale(locale);\n const cacheKey = apiLocale || \"\";\n if (categoriesCache.has(cacheKey)) return categoriesCache.get(cacheKey);\n const json = await request(\"/categories\", apiLocale ? { locale: apiLocale } : null, signal);\n const list = Array.isArray(json?.data?.categories) ? json.data.categories : [];\n const categories = list\n .map((entry) => {\n const category = String(entry?.category ?? \"\").trim();\n const query = String(entry?.query ?? category).trim();\n if (!category || !query) return null;\n const preview = isTrustedKlipyUrl(entry?.preview_url) ? entry.preview_url : null;\n return { category, query, preview };\n })\n .filter(Boolean);\n categoriesCache.set(cacheKey, categories);\n return categories;\n}\n\n/** Registra el share (POST /gifs/share/{slug}). Nunca rechaza. */\nexport async function shareGif(slug, { query } = {}) {\n if (!slug) return false;\n try {\n const body = { customer_id: getKlipyCustomerId() };\n const q = String(query ?? \"\").trim();\n if (q) body.q = q;\n const response = await fetch(`${getBaseUrl()}/share/${encodeURIComponent(slug)}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n","import { useEffect, useState } from 'react';\nconst key = 'lira-chat-text-size';\nconst normalize = (value) => { const size = Number(value); return Number.isFinite(size) && size >= 13 && size <= 20 ? size : 14; };\nconst read = () => { try { return normalize(localStorage.getItem(key)); } catch { return 14; } };\nexport default function useChatTextSize() {\n const [size, setSize] = useState(read);\n useEffect(() => {\n const sync = (event) => { if (event.type === 'lira-chat-size') setSize(normalize(event.detail)); else if (!event.key || event.key === key) setSize(read()); };\n window.addEventListener('storage', sync);\n window.addEventListener('lira-chat-size', sync);\n return () => { window.removeEventListener('storage', sync); window.removeEventListener('lira-chat-size', sync); };\n }, []);\n const update = (value) => {\n const next = normalize(value); setSize(next);\n try { localStorage.setItem(key, String(next)); } catch { /* Keep session preference. */ }\n window.dispatchEvent(new CustomEvent('lira-chat-size', { detail: next }));\n };\n return [size, update];\n}\n","import { useCallback, useEffect } from 'react';\n\nconst FOCUSABLE = 'button:not(:disabled), input:not(:disabled), textarea:not(:disabled), summary, [tabindex=\"0\"]';\n\n/**\n * Focus management for a dialog-like container.\n * - `autoFocus`: while true, focuses the first control and restores the previously focused element when it turns false/unmounts.\n * - `active`: while true, Tab/Shift+Tab cycle inside `ref`.\n * Returns an `onKeyDown` handler to attach to the container.\n */\nexport default function useFocusTrap(ref, { active = false, autoFocus = false } = {}) {\n useEffect(() => {\n if (!autoFocus) return undefined;\n const previous = document.activeElement;\n ref.current?.querySelector('button, input, textarea')?.focus();\n return () => { if (previous?.isConnected) previous.focus(); };\n }, [autoFocus, ref]);\n\n return useCallback((event) => {\n if (!active || event.key !== 'Tab' || !ref.current) return;\n const nodes = [...ref.current.querySelectorAll(FOCUSABLE)].filter((node) => node.getClientRects().length);\n const first = nodes[0]; const last = nodes[nodes.length - 1];\n if (!first) { event.preventDefault(); return; }\n if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }\n else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }\n }, [active, ref]);\n}\n","import { useRef, useState } from 'react';\n\nconst DEFAULT_INITIAL = { width: 420, height: 740 };\nconst DEFAULT_MIN = { width: 360, height: 380 };\nconst RESIZE_KEYS = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];\n\n/**\n * Top-left resize handle for an element anchored bottom-right.\n * `targetRef` points at the resized element (used to read its current rect); defaults to the handle's parent.\n * Max size is bound to the viewport (vw - 48 × vh - 80).\n */\nexport default function useResizable({ initial = DEFAULT_INITIAL, min = DEFAULT_MIN, enabled = true, targetRef } = {}) {\n const startRef = useRef(null);\n const [size, setSize] = useState(initial);\n const [isResizing, setResizing] = useState(false);\n\n const targetRect = (event) => (targetRef?.current ?? event.currentTarget.parentElement).getBoundingClientRect();\n const constrainSize = (width, height) => ({\n width: Math.min(Math.max(min.width, width), window.innerWidth - 48),\n height: Math.min(Math.max(min.height, height), window.innerHeight - 80),\n });\n const onPointerDown = (event) => {\n if (!enabled || event.button !== 0) return;\n event.preventDefault();\n const rect = targetRect(event);\n startRef.current = { x: event.clientX, y: event.clientY, width: rect.width, height: rect.height };\n event.currentTarget.setPointerCapture(event.pointerId);\n setResizing(true);\n };\n const onPointerMove = (event) => {\n const start = startRef.current;\n if (!start) return;\n setSize(constrainSize(start.width + start.x - event.clientX, start.height + start.y - event.clientY));\n };\n const endResize = (event) => {\n startRef.current = null;\n setResizing(false);\n if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n };\n const onLostPointerCapture = () => { startRef.current = null; setResizing(false); };\n const onKeyDown = (event) => {\n if (!enabled || !RESIZE_KEYS.includes(event.key)) return;\n event.preventDefault();\n const rect = targetRect(event);\n const step = event.shiftKey ? 40 : 10;\n setSize(constrainSize(rect.width + (event.key === 'ArrowLeft' ? step : event.key === 'ArrowRight' ? -step : 0),\n rect.height + (event.key === 'ArrowUp' ? step : event.key === 'ArrowDown' ? -step : 0)));\n };\n\n return {\n size,\n isResizing,\n handleProps: {\n onPointerDown, onPointerMove, onPointerUp: endResize, onPointerCancel: endResize,\n onLostPointerCapture, onKeyDown,\n },\n };\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useRef } from 'react';\nimport { Minimize2, Maximize2, X, PanelLeft, Hash, ExternalLink, Download, Volume2, VolumeX, Bell, BellOff, RotateCcw } from 'lucide-react';\nimport { desktopSettings, toggleDesktopNotifications, setDesktopPreviews } from '../../notifications/desktopNotifications';\nimport { isSoundEnabled, toggleSound } from '../../notifications/chatSounds';\n\nconst PRESENCE_TEXT = { online: 'En línea', away: 'Ausente', busy: 'Ocupado' };\n\nexport default function ChatHeader({\n onDetach, onInstall, textSize, onTextSizeChange,\n title,\n subtitle,\n type = 'group',\n secondary,\n presence,\n onClose,\n onMinimize,\n onMaximize,\n onRestore,\n isMaximized,\n onToggleSidebar,\n showSidebar,\n}) {\n const isPrivate = type === 'private';\n const presenceText = presence ? PRESENCE_TEXT[presence] || PRESENCE_TEXT.online : 'Desconectado';\n const privateSubtitle = [presenceText, secondary].filter(Boolean).join(' · ');\n const notificationRef = useRef(null);\n useEffect(() => {\n const closeOutside = (event) => {\n if (!notificationRef.current?.contains(event.target)) notificationRef.current?.removeAttribute('open');\n };\n document.addEventListener('pointerdown', closeOutside);\n return () => document.removeEventListener('pointerdown', closeOutside);\n }, []);\n const [desktop, setDesktop] = useState(desktopSettings);\n useEffect(() => {\n const sync = () => setDesktop(desktopSettings());\n window.addEventListener('storage', sync);\n window.addEventListener('lira-desktop-settings', sync);\n window.addEventListener('focus', sync);\n return () => { window.removeEventListener('storage', sync); window.removeEventListener('lira-desktop-settings', sync); window.removeEventListener('focus', sync); };\n }, []);\n const [soundEnabled, setSoundEnabled] = useState(() => isSoundEnabled());\n\n const handleToggleSound = () => {\n const next = toggleSound();\n setSoundEnabled(next);\n };\n\n // Sync with other windows via storage event\n useEffect(() => {\n const onStorage = (e) => {\n if (e.key === 'lira-chat-sound') {\n setSoundEnabled(e.newValue !== 'false');\n }\n };\n window.addEventListener('storage', onStorage);\n return () => window.removeEventListener('storage', onStorage);\n }, []);\n\n return (\n <div className=\"chat-header\">\n <div className=\"chat-header-left\">\n <button type=\"button\" className=\"chat-btn chat-sidebar-toggle\" onClick={onToggleSidebar} aria-expanded={showSidebar} aria-label=\"Mostrar conversaciones\" title=\"Conversaciones\"><PanelLeft size={19} /></button>\n <div className={`chat-header-avatar chat-header-avatar--${isPrivate ? 'private' : 'group'}${isPrivate && presence ? ` chat-header-avatar--presence-${presence}` : ''}`} aria-hidden=\"true\">\n {isPrivate ? (title || '?').charAt(0).toUpperCase() : <Hash size={22} />}\n </div>\n <div className=\"chat-header-info\">\n <div className=\"chat-header-title\" title={title}>{title}</div>\n {isPrivate\n ? <div className=\"chat-header-subtitle\" title={privateSubtitle}>{privateSubtitle}</div>\n : <div className=\"chat-header-subtitle\">{subtitle === 'connected' ? 'En línea · tu espacio para conectar' : 'Tu espacio para conectar'}</div>}\n </div>\n </div>\n <div className=\"chat-header-actions\">\n <details ref={notificationRef} className=\"chat-text-settings chat-notification-settings\" onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault(); event.stopPropagation();\n notificationRef.current?.removeAttribute('open');\n notificationRef.current?.querySelector('summary')?.focus();\n }\n }}>\n <summary aria-label=\"Notificaciones de escritorio\" title=\"Notificaciones de escritorio\">{desktop.enabled && desktop.permission === 'granted' ? <Bell size={16} /> : <BellOff size={16} />}</summary>\n <div className=\"chat-notification-panel\" role=\"group\" aria-label=\"Ajustes de notificaciones\">\n <div className=\"chat-notification-heading\">\n <span className=\"chat-notification-icon\" aria-hidden=\"true\"><Bell size={18} /></span>\n <div><strong>Notificaciones</strong><span>Recibe avisos en tu escritorio</span></div>\n <span className={`chat-notification-status ${desktop.enabled && desktop.permission === 'granted' ? 'is-enabled' : ''}`}>{desktop.enabled && desktop.permission === 'granted' ? 'Activas' : 'Inactivas'}</span>\n </div>\n <button type=\"button\" className=\"chat-notification-toggle\" disabled={!desktop.supported || desktop.permission === 'denied'} aria-pressed={desktop.enabled && desktop.permission === 'granted'} onClick={() => { void toggleDesktopNotifications().then(() => setDesktop(desktopSettings())); }}>\n {desktop.enabled && desktop.permission === 'granted' ? <BellOff size={16} aria-hidden=\"true\" /> : <Bell size={16} aria-hidden=\"true\" />}\n {desktop.enabled && desktop.permission === 'granted' ? 'Desactivar notificaciones' : 'Activar notificaciones'}\n </button>\n <label className=\"chat-notification-preview\">\n <span className=\"chat-notification-preview-copy\"><strong>Mostrar vista previa</strong><small>Incluye el nombre y el mensaje. Los chats privados siempre se ocultan.</small></span>\n <input type=\"checkbox\" role=\"switch\" checked={desktop.previews} onChange={(event) => setDesktopPreviews(event.target.checked)} />\n </label>\n {(!desktop.supported || desktop.permission === 'denied') && <p className=\"chat-notification-notice\" role=\"status\">{desktop.supported ? 'Permiso bloqueado. Actívalo en los ajustes del navegador.' : 'Notificaciones no disponibles en este navegador.'}</p>}\n </div>\n </details>\n <details className=\"chat-text-settings\">\n <summary aria-label=\"Tamaño del texto del chat\" title=\"Tamaño del texto\">Aa</summary>\n <div className=\"chat-text-settings-panel\" role=\"group\" aria-label=\"Tamaño del texto\">\n <button type=\"button\" className=\"chat-btn\" disabled={textSize <= 13} onClick={() => onTextSizeChange(textSize - 1)} aria-label=\"Reducir texto\">A−</button>\n <output aria-live=\"polite\">{textSize}px</output>\n <button type=\"button\" className=\"chat-btn\" disabled={textSize >= 20} onClick={() => onTextSizeChange(textSize + 1)} aria-label=\"Aumentar texto\">A+</button>\n <button type=\"button\" className=\"chat-btn\" onClick={() => onTextSizeChange(14)} aria-label=\"Restablecer tamaño\" title=\"Restablecer tamaño\"><RotateCcw size={16} aria-hidden=\"true\" /></button>\n </div>\n </details>\n <button\n type=\"button\"\n className=\"chat-btn\"\n onClick={handleToggleSound}\n aria-label={soundEnabled ? 'Silenciar sonidos' : 'Activar sonidos'}\n aria-pressed={soundEnabled}\n title={soundEnabled ? 'Silenciar sonidos' : 'Activar sonidos'}\n >\n {soundEnabled ? <Volume2 size={16} /> : <VolumeX size={16} />}\n </button>\n {onDetach && <button type=\"button\" className=\"chat-btn\" onClick={onDetach} aria-label=\"Abrir en ventana independiente\" title=\"Abrir en ventana independiente\"><ExternalLink size={16} /></button>}\n {onInstall && <button type=\"button\" className=\"chat-btn\" onClick={onInstall} aria-label=\"Instalar LIRA Chat\" title=\"Instalar LIRA Chat\"><Download size={16} /></button>}\n {onMinimize && <button type=\"button\" className=\"chat-btn\" onClick={onMinimize} aria-label=\"Minimizar\" title=\"Minimizar\">\n <Minimize2 size={14} />\n </button>}\n {onMaximize && (isMaximized ? (\n <button type=\"button\" className=\"chat-btn\" onClick={onRestore} aria-label=\"Restaurar\" title=\"Restaurar\">\n <Maximize2 size={14} />\n </button>\n ) : (\n <button type=\"button\" className=\"chat-btn\" onClick={onMaximize} aria-label=\"Maximizar\" title=\"Maximizar\">\n <Maximize2 size={14} />\n </button>\n ))}\n {onClose && <button type=\"button\" className=\"chat-btn\" onClick={onClose} aria-label=\"Cerrar\" title=\"Cerrar\">\n <X size={14} />\n </button>}\n </div>\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { Hash, User } from 'lucide-react';\n\nconst PRESENCE_TEXT = { online: 'En línea', away: 'Ausente', busy: 'Ocupado' };\n\nexport default function ConversationItem({ conv, onSelect, selected }) {\n const isPerson = conv.type === 'private' || conv.type === 'user';\n const unread = conv.unread || 0;\n const typeClass = isPerson ? `conv-item--${conv.type}` : 'conv-item--group';\n const preview = conv.lastMessage || (isPerson ? conv.secondary || '' : 'Canal');\n const statusHidden = conv.statusText && conv.online;\n const presence = conv.online ? conv.presence || 'online' : null;\n const presenceText = presence ? PRESENCE_TEXT[presence] || PRESENCE_TEXT.online : '';\n\n return (\n <button\n type=\"button\"\n aria-pressed={selected === true}\n aria-label={`${isPerson ? `Conversación privada con ${conv.name}` : `Canal ${conv.name}`}${presenceText ? `, ${presenceText.toLocaleLowerCase()}` : ''}${unread > 0 ? `, ${unread} mensajes no leídos` : ''}`}\n className={`conv-item ${typeClass} ${conv.online ? `conv-item--online conv-item--presence-${presence}` : ''} ${selected === true ? 'conv-item--active' : ''} ${unread > 0 ? 'conv-item--unread' : ''}`}\n onClick={() => onSelect?.(conv)}\n >\n <div className=\"conv-avatar\" aria-hidden=\"true\">\n {isPerson ? (\n <span className=\"conv-avatar-private\">{conv.avatar || <User size={16} />}</span>\n ) : (\n <Hash size={16} className=\"conv-icon-hash\" />\n )}\n </div>\n <div className=\"conv-info\">\n <div className=\"conv-name\">\n <span className=\"conv-name-text\" title={conv.secondary || conv.name}>{conv.name}</span>\n {unread > 0 && <span className=\"conv-unread-badge\" aria-label={`${unread} mensajes no leídos`}>{unread > 99 ? '99+' : unread}</span>}\n </div>\n {conv.statusText ? (\n statusHidden ? <>\n <span className=\"sr-only\">{presenceText || conv.statusText}</span>\n {conv.secondary && <div className=\"conv-preview\">{conv.secondary}</div>}\n </> : <div className=\"conv-preview\">{conv.statusText}</div>\n ) : preview && <div className=\"conv-preview\">{preview}</div>}\n </div>\n <div className=\"conv-meta\">{conv.time || ''}</div>\n </button>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { MessageCircle } from 'lucide-react';\nimport ConversationItem from './ConversationItem';\n\nexport default function ConversationList({ conversations, onSelect, selectedId }) {\n if (!conversations || conversations.length === 0) {\n return (\n <div className=\"chat-empty\">\n <MessageCircle size={32} aria-hidden=\"true\" />\n <p>No hay conversaciones</p>\n </div>\n );\n }\n return (\n <div className=\"chat-conversation-list\">\n {conversations.map((conv) => (\n <ConversationItem\n key={conv.id}\n conv={conv}\n selected={selectedId === conv.id}\n onSelect={() => onSelect?.(conv)}\n />\n ))}\n </div>\n );\n}","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport { Check } from 'lucide-react';\n\nconst PRESENCE_LABELS = { online: 'En línea', away: 'Ausente', busy: 'Ocupado', invisible: 'Invisible' };\n\n// Own-status control shown from the user's avatar in the sidebar header.\nexport default function StatusMenu({ name, presence, onChange }) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef(null);\n const buttonRef = useRef(null);\n const status = presence?.status || 'online';\n const manual = presence?.manual || 'auto';\n const autoLabel = status === 'away' ? 'Ausente' : 'En línea';\n const options = [\n { value: 'auto', label: 'Automático', hint: autoLabel, dot: manual === 'auto' && status === 'away' ? 'away' : 'online' },\n { value: 'busy', label: 'Ocupado', dot: 'busy' },\n { value: 'invisible', label: 'Invisible', hint: 'Apareces desconectado', dot: 'invisible' },\n ];\n\n useEffect(() => {\n if (!open) return undefined;\n const closeOutside = (event) => { if (!rootRef.current?.contains(event.target)) setOpen(false); };\n document.addEventListener('pointerdown', closeOutside);\n rootRef.current?.querySelector('[aria-checked=\"true\"]')?.focus();\n return () => document.removeEventListener('pointerdown', closeOutside);\n }, [open]);\n\n const close = () => { setOpen(false); buttonRef.current?.focus(); };\n const onKeyDown = (event) => {\n if (event.key === 'Escape' && open) {\n event.preventDefault(); event.stopPropagation();\n close();\n return;\n }\n if (!open || !['ArrowDown', 'ArrowUp'].includes(event.key)) return;\n event.preventDefault();\n const items = [...rootRef.current.querySelectorAll('[role=\"menuitemradio\"]')];\n const index = items.indexOf(document.activeElement);\n items[(index + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length]?.focus();\n };\n const select = (value) => { onChange?.(value); close(); };\n const label = PRESENCE_LABELS[status] || PRESENCE_LABELS.online;\n\n return (\n <div ref={rootRef} className=\"chat-status-menu\" onKeyDown={onKeyDown}>\n <button ref={buttonRef} type=\"button\" className={`chat-own-avatar chat-own-avatar--${status}`}\n aria-haspopup=\"menu\" aria-expanded={open} aria-label={`Tu estado: ${label}. Cambiar estado`} title={`Tu estado: ${label}`}\n onClick={() => setOpen((value) => !value)}>\n <span aria-hidden=\"true\">{(name || '?').charAt(0).toUpperCase()}</span>\n </button>\n {open && <div className=\"chat-status-panel\" role=\"menu\" aria-label=\"Estado de presencia\">\n {options.map((option) => (\n <button key={option.value} type=\"button\" role=\"menuitemradio\" aria-checked={manual === option.value}\n className={`chat-status-option ${manual === option.value ? 'is-current' : ''}`} onClick={() => select(option.value)}>\n <span className={`chat-presence-dot chat-presence-dot--${option.dot}`} aria-hidden=\"true\" />\n <span className=\"chat-status-option-text\"><strong>{option.label}</strong>{option.hint && <small>{option.hint}</small>}</span>\n {manual === option.value && <Check size={14} aria-hidden=\"true\" />}\n </button>\n ))}\n </div>}\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useMemo, useState } from 'react';\nimport ConversationItem from './ConversationItem';\nimport ConversationList from './ConversationList';\nimport StatusMenu from './StatusMenu';\n\nconst userIdOf = (user) => String(user?.user_id ?? user?.id);\nconst displayName = (user, id) => user?.name || user?.username || `Usuario ${String(id ?? '').slice(0, 8)}`;\nconst PRESENCE_TEXT = { online: 'En línea', away: 'Ausente', busy: 'Ocupado' };\nconst secondaryOf = (user, name) => (user?.username && user.username !== name ? user.username : undefined);\n\nfunction buildConversations({ rooms = [], privateRooms = {}, users = [], onlineUsers = [], unreadCounts = {}, knownUsers = {}, presenceById = new Map() }) {\n const convs = [];\n \n // Add rooms (canales)\n rooms.forEach((room) => {\n const unread = unreadCounts[room.id] || 0;\n convs.push({\n id: room.id,\n type: 'group',\n name: room.name,\n avatar: null,\n unread,\n lastMessage: room.lastMessage,\n time: room.time,\n });\n });\n \n // Add private conversations from privateRooms map\n Object.entries(privateRooms).forEach(([userId, roomId]) => {\n if (convs.some(c => c.id === roomId)) return; // avoid duplicates\n const unread = unreadCounts[roomId] || 0;\n // Find user info from onlineUsers or users\n const user = knownUsers[userId] || [...users, ...onlineUsers].find(u => userIdOf(u) === String(userId));\n const name = displayName(user, userId);\n convs.push({\n id: roomId,\n type: 'private',\n name,\n secondary: secondaryOf(user, name),\n presence: presenceById.get(String(userId)) || null,\n online: presenceById.has(String(userId)),\n avatar: user ? name.charAt(0).toUpperCase() : null,\n unread,\n lastMessage: null,\n time: null,\n });\n });\n \n // Sort: unread first, then by last activity (simplified)\n convs.sort((a, b) => (b.unread || 0) - (a.unread || 0));\n return convs;\n}\n\nexport default function ChatSidebar({ \n rooms = [], \n users = [], \n onlineUsers = [],\n privateRooms = {},\n selectedId,\n onSelect,\n onSelectUser,\n onSearch,\n searchResults = [], searchStatus = 'idle', searchQuery = '', presenceStatus = 'idle',\n onCreateGroup,\n unreadCounts = {},\n knownUsers = {},\n currentUserId,\n currentUserIds = [],\n currentUserName,\n myPresence,\n onSetPresence,\n}) {\n const [query, setQuery] = useState(searchQuery);\n const [groupName, setGroupName] = useState('');\n const [creating, setCreating] = useState(false);\n useEffect(() => { onSearch?.(query); }, [query, onSearch, searchQuery]);\n const selfIds = new Set([...(currentUserIds || []), currentUserId].filter((id) => id != null).map(String));\n const isSelf = (user) => [user?.user_id, user?.id].some((id) => id != null && selfIds.has(String(id)));\n // Offline users are absent from onlineUsers; a missing status means plain online.\n const presenceById = useMemo(() => new Map(onlineUsers.map((user) => [userIdOf(user), user.status || 'online'])), [onlineUsers]);\n const peers = onlineUsers.filter((user) => !isSelf(user));\n const found = searchResults.filter((user) => !isSelf(user));\n const onlySelf = onlineUsers.length === 1 && isSelf(onlineUsers[0]);\n const renderUser = (user, connected) => {\n const id = userIdOf(user);\n const explicitOnline = user.is_online ?? user.online;\n const presence = presenceById.get(id) || (connected || explicitOnline === true ? user.status || 'online' : null);\n const online = presence != null;\n const label = online ? PRESENCE_TEXT[presence] || PRESENCE_TEXT.online : explicitOnline === false ? 'Desconectado' : 'Estado no disponible';\n const name = displayName(user, id);\n return <ConversationItem key={id} conv={{ id, type: 'user', name, secondary: secondaryOf(user, name), online, presence,\n avatar: name.charAt(0).toUpperCase(), statusText: label }}\n selected={String(privateRooms[id]) === String(selectedId) && selectedId != null}\n onSelect={() => onSelectUser?.(user)} />;\n };\n\n const conversations = useMemo(() => buildConversations({ rooms, privateRooms, users, onlineUsers, unreadCounts, knownUsers, presenceById }),\n [rooms, privateRooms, users, onlineUsers, unreadCounts, knownUsers, presenceById]);\n\n const matches = (item) => `${item.name || ''} ${item.secondary || ''}`.toLocaleLowerCase().includes(query.toLocaleLowerCase());\n\n const handleSelect = (conv) => {\n if (conv.noRoom) {\n onSelectUser?.({ user_id: conv.id });\n return;\n }\n onSelect?.(conv.id);\n };\n\n return (\n <aside className=\"chat-sidebar\" aria-label=\"Conversaciones\">\n <div className=\"chat-sidebar-header\">\n {onSetPresence && <StatusMenu name={currentUserName} presence={myPresence} onChange={onSetPresence} />}\n <div className=\"chat-sidebar-title\">Conversaciones</div>\n <button type=\"button\" className=\"chat-btn\" title=\"Crear grupo\" aria-label=\"Crear grupo\" onClick={() => setCreating(!creating)}>+</button>\n </div>\n {creating && <form className=\"chat-group-form\" onSubmit={(event) => { event.preventDefault(); if (groupName.trim()) { onCreateGroup?.(groupName.trim()); setGroupName(''); setCreating(false); } }}>\n <label className=\"sr-only\" htmlFor=\"chat-group-name\">Nombre del grupo</label>\n <input id=\"chat-group-name\" value={groupName} onChange={(event) => setGroupName(event.target.value)} placeholder=\"Nombre del grupo\" required maxLength={100} />\n <button type=\"submit\" disabled={!groupName.trim()}>Crear</button>\n </form>}\n <div className=\"chat-sidebar-search\"><input aria-label=\"Buscar conversaciones y usuarios\" type=\"search\" placeholder=\"Buscar...\" value={query} onChange={(event) => { setQuery(event.target.value); onSearch?.(event.target.value); }} /></div>\n <div className=\"chat-sidebar-content\">\n <ConversationList conversations={conversations.filter(matches)} onSelect={handleSelect} selectedId={selectedId} />\n <section className=\"chat-user-section\" aria-label=\"Usuarios conectados\">\n <h3>Usuarios conectados</h3>\n {peers.map((user) => renderUser(user, true))}\n {!peers.length && <p className=\"chat-user-status\" role=\"status\">{presenceStatus === 'loading' ? 'Consultando usuarios…'\n : presenceStatus === 'error' ? 'El servidor no respondió a la consulta de usuarios.'\n : onlySelf ? 'El servidor solo devolvió tu usuario. No envió otros usuarios conectados.'\n : presenceStatus === 'ready' ? 'El servidor no devolvió otros usuarios conectados.' : 'Esperando lista de usuarios…'}</p>}\n </section>\n {query.trim() && <section className=\"chat-user-section\" aria-label=\"Usuarios encontrados\">\n <h3>Usuarios encontrados</h3>\n {found.map((user) => renderUser(user, false))}\n <p className=\"chat-user-status\" role=\"status\">{searchStatus === 'loading' ? 'Buscando usuarios…'\n : searchStatus === 'error' ? 'No se pudo completar la búsqueda. Comprueba tu conexión.'\n : !found.length ? 'No se encontraron otros usuarios.' : ''}</p>\n </section>}\n </div>\n </aside>\n );\n}","import { MessageCircle } from 'lucide-react';\n\nexport default function ChatEmptyState() {\n return (\n <div className=\"chat-empty-state\">\n <MessageCircle size={40} aria-hidden=\"true\" />\n <h3>Selecciona una conversación</h3>\n <p>Elige un canal o chat privado para empezar a conversar.</p>\n </div>\n );\n}\n","// Add only real, approved bundled assets here. No placeholder catalog.\nexport const customEmojis = [];\n","// Custom catalog is provider-scoped: never mutate the global Unicode index.\nexport const CUSTOM_EMOJI_MAX_BYTES = 256 * 1024;\nexport const CUSTOM_EMOJI_LIMIT = 100;\nexport const CUSTOM_EMOJI_NAME = /^[a-z0-9_+-]{1,32}$/;\nconst rasterData = /^data:image\\/(png|gif|jpeg|webp);base64,[a-z0-9+/]+=*$/i;\nexport function isCustomEmojiUrl(value) {\n if (typeof value !== 'string' || value.length > 360000 || /[\\u0000-\\u0020\\\\]/.test(value)) return false;\n if (rasterData.test(value)) return true;\n if (/^\\/(?!\\/)/.test(value) || /^\\.\\.?\\//.test(value)) return true;\n try {\n const url = new URL(value);\n if (url.protocol === 'blob:') {\n if (url.pathname.startsWith('null/')) return true;\n const origin = new URL(url.pathname);\n return ['https:', 'http:'].includes(origin.protocol) && !origin.username && !origin.password;\n }\n return ['https:', 'http:'].includes(url.protocol) && !url.username && !url.password;\n } catch { return false; }\n}\nexport function normalizeCustomEmojis(input) {\n if (!Array.isArray(input)) return [];\n const names = new Set();\n return input.slice(0, CUSTOM_EMOJI_LIMIT).flatMap((item) => {\n if (!item || typeof item.shortcode !== 'string' || !CUSTOM_EMOJI_NAME.test(item.shortcode) || names.has(item.shortcode) || !isCustomEmojiUrl(item.url)) return [];\n names.add(item.shortcode);\n return [{ shortcode: item.shortcode, url: item.url, label: String(item.label || item.shortcode).slice(0, 100),\n emoji: `:${item.shortcode}:`, shortcodes: [item.shortcode], source: 'custom', category: 'custom' }];\n });\n}\nexport function searchCustomEmojis(records, query) {\n const folded = (value) => String(value).normalize('NFD').replace(/\\p{M}/gu, '').toLowerCase();\n const q = folded(query).replace(/^:|:$/g, '').trim();\n return records.filter((item) => folded(`${item.shortcode} ${item.label}`).includes(q));\n}\n","import { useContext, useMemo } from 'react';\nimport { ChatContext } from '../../provider/ChatContext.js';\nimport { customEmojis } from './customEmojis.js';\nimport { normalizeCustomEmojis } from './customEmojiCatalog.js';\nexport function useCustomEmojis() {\n const context = useContext(ChatContext);\n const catalog = context?.config?.media?.emoji?.custom;\n return useMemo(() => normalizeCustomEmojis(catalog ?? customEmojis), [catalog]);\n}\n","/* eslint-disable react/prop-types */\nimport { useState } from 'react';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nfunction InlineEmoji({ item }) {\n const [failed, setFailed] = useState(false);\n return failed ? `:${item.shortcode}:` : <img className=\"chat-inline-emoji\" src={item.url} alt={`:${item.shortcode}:`} title={item.label} onError={() => setFailed(true)} />;\n}\nexport default function MessageText({ text }) {\n const customEmojis = useCustomEmojis();\n return String(text).split(/(:[a-z0-9_+-]+:)/g).map((part, index) => {\n const item = customEmojis.find((emoji) => `:${emoji.shortcode}:` === part);\n return item ? <InlineEmoji key={`${index}-${item.url}`} item={item} /> : part;\n });\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Download, File, FileText, FileSpreadsheet, FileArchive, X, Play, Pause, Mic, AlertCircle } from 'lucide-react';\nimport { isStickerAttachment, stickerTitle } from '../../core/extras/messageExtras';\n\nconst safeUrl = (value) => {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n return ['https:', 'blob:'].includes(url.protocol) && !url.username && !url.password ? url.href : undefined;\n } catch { return undefined; }\n};\n\nconst fileSize = (size) => Number.isFinite(size) && size >= 0\n ? (size < 1024 * 1024 ? `${Math.ceil(size / 1024)} KB` : `${(size / (1024 * 1024)).toFixed(1)} MB`)\n : '';\n\nconst clock = (seconds) => {\n if (!Number.isFinite(seconds)) return '0:00';\n return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, '0')}`;\n};\n\nfunction VoicePlayer({ url, onError }) {\n const audioRef = useRef(null);\n const [playing, setPlaying] = useState(false);\n const [position, setPosition] = useState(0);\n const [duration, setDuration] = useState(0);\n const [playError, setPlayError] = useState('');\n const updateDuration = () => {\n const audio = audioRef.current;\n if (!audio) return;\n const value = Number.isFinite(audio.duration) ? audio.duration\n : audio.buffered.length ? audio.buffered.end(audio.buffered.length - 1) : 0;\n if (value > 0) setDuration(value);\n };\n return <div className=\"chat-audio-player\">\n <audio ref={audioRef} src={url} preload=\"metadata\" onError={onError}\n onLoadedMetadata={updateDuration} onDurationChange={updateDuration} onProgress={updateDuration} onLoadedData={updateDuration}\n onTimeUpdate={() => setPosition(audioRef.current.currentTime)}\n onPlay={() => setPlaying(true)} onPause={() => setPlaying(false)} onEnded={() => { setPlaying(false); updateDuration(); }} />\n <button type=\"button\" className=\"chat-audio-toggle\" aria-label={playing ? 'Pausar audio' : 'Reproducir audio'} onClick={async () => {\n if (playing) audioRef.current.pause();\n else { try { setPlayError(''); await audioRef.current.play(); } catch { setPlayError('No se pudo reproducir. Descarga el audio para escucharlo.'); } }\n }}>{playing ? <Pause size={19} /> : <Play size={19} />}</button>\n <div className=\"chat-audio-track\">\n <span className=\"chat-audio-title\"><Mic size={13} /> Mensaje de voz</span>\n <input type=\"range\" min=\"0\" max={duration || 1} step=\"0.1\" value={Math.min(position, duration || 1)} disabled={!duration}\n aria-label=\"Posición del audio\" aria-valuetext={`${clock(position)} de ${clock(duration)}`}\n onChange={(event) => { audioRef.current.currentTime = Number(event.target.value); setPosition(Number(event.target.value)); }} />\n <span className=\"chat-audio-time\">{clock(position)}{duration > 0 ? ` / ${clock(duration)}` : ''}</span>\n {playError && <small role=\"status\">{playError}</small>}\n </div>\n </div>;\n}\n\nfunction AttachmentCard({ item, onRemove, history, onExpand }) {\n const [failed, setFailed] = useState(false);\n const url = safeUrl(item.preview) || safeUrl(item.url);\n const mime = typeof item.type === 'string' ? item.type.toLowerCase() : '';\n const kind = item.kind || mime.split('/')[0];\n const sticker = isStickerAttachment(item);\n const name = sticker ? stickerTitle(item) : (item.name || 'Archivo adjunto');\n const visual = kind === 'image' || kind === 'gif';\n const available = Boolean(url) && !failed;\n const extension = name.includes('.') ? name.split('.').pop().slice(0, 8).toUpperCase() : 'ARCHIVO';\n const Icon = /zip|compressed|archive/.test(mime) ? FileArchive : /sheet|excel|csv/.test(mime) ? FileSpreadsheet : /pdf|text|word|document/.test(mime) ? FileText : File;\n const cardType = !available ? 'unavailable' : visual ? 'visual' : kind === 'audio' ? 'audio' : kind === 'video' ? 'video' : 'file';\n if (sticker && history) {\n return <div className={`chat-media-card chat-attachment--sticker chat-media-card--${available ? 'visual' : 'unavailable'}`}>\n {available ? <button type=\"button\" className=\"chat-media-image\" aria-label={`Ampliar sticker ${name}`} onClick={() => onExpand({ url, name })}>\n <img className=\"chat-sticker-image\" src={url} alt={name} loading=\"lazy\" onError={() => setFailed(true)} />\n <span className=\"sr-only ui-sr-only\">Sticker</span>\n </button> : <>\n <div className=\"chat-file-icon\"><AlertCircle size={24} /></div>\n <div className=\"chat-media-card-meta\">\n <span className=\"chat-file-name\" title={name}>{name}</span>\n <small>Archivo no disponible en esta ventana</small>\n </div>\n </>}\n </div>;\n }\n return <div className={`chat-media-card chat-media-card--${cardType}`}>\n {available && visual ? <button type=\"button\" className=\"chat-media-image\" aria-label={`Ampliar ${name}`} onClick={() => onExpand({ url, name })}>\n <img src={url} alt={name} loading=\"lazy\" onError={() => setFailed(true)} />\n {kind === 'gif' && <span className=\"chat-gif-label\">{sticker ? 'Sticker' : 'GIF'}</span>}\n </button> : available && kind === 'video' ? <video className=\"chat-attachment-video\" src={url} controls preload=\"metadata\" aria-label={name} onError={() => setFailed(true)} />\n : available && kind === 'audio' ? <VoicePlayer url={url} onError={() => setFailed(true)} />\n : <div className=\"chat-file-icon\">{available ? <Icon size={25} /> : <AlertCircle size={24} />}</div>}\n <div className=\"chat-media-card-meta\">\n <span className=\"chat-file-name\" title={name}>{history && kind === 'audio' ? 'Audio' : name}</span>\n <small>{!available ? 'Archivo no disponible en esta ventana' : [!visual && kind !== 'audio' && kind !== 'video' ? extension : '', item.size > 0 ? fileSize(item.size) : ''].filter(Boolean).join(' · ')}</small>\n </div>\n {available && <a className=\"chat-file-download\" href={url} download={name} target=\"_blank\" rel=\"noopener noreferrer\" title=\"Descargar archivo\" aria-label={`Descargar ${name}`}><Download size={17} /></a>}\n {onRemove && <button type=\"button\" className=\"chat-attachment-remove\" aria-label={`Quitar ${name}`} onClick={onRemove}><X size={14} /></button>}\n </div>;\n}\n\nexport default function MediaPreview({ items = [], onRemove, history = false }) {\n const [activeImage, setActiveImage] = useState(null);\n const closeRef = useRef(null);\n\n useEffect(() => {\n if (!activeImage) return undefined;\n const previousFocus = document.activeElement;\n closeRef.current?.focus();\n const onKeyDown = (event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopImmediatePropagation();\n setActiveImage(null);\n }\n if (event.key === 'Tab') {\n event.preventDefault();\n closeRef.current?.focus();\n }\n };\n document.addEventListener('keydown', onKeyDown, true);\n return () => {\n document.removeEventListener('keydown', onKeyDown, true);\n if (previousFocus?.isConnected) previousFocus.focus();\n };\n }, [activeImage]);\n\n if (!Array.isArray(items) || !items.length) return null;\n\n return <>\n <div className={`chat-media-grid ${history ? 'chat-media-grid--history' : 'chat-media-grid--draft'}`}>\n {items.map((item, index) => item && typeof item === 'object' ?\n <AttachmentCard key={`${item.id || index}:${item.url || item.preview || ''}`} item={item} history={history}\n onRemove={onRemove ? () => onRemove(index) : undefined} onExpand={setActiveImage} /> : null)}\n </div>\n {activeImage && createPortal(<div className=\"mc-chat-portal chat-media-viewer\" role=\"dialog\" aria-modal=\"true\" aria-label={activeImage.name} onClick={(event) => { event.stopPropagation(); setActiveImage(null); }}>\n <div className=\"chat-media-viewer-content\" onClick={(event) => event.stopPropagation()}>\n <button ref={closeRef} type=\"button\" aria-label=\"Cerrar imagen\" onClick={() => setActiveImage(null)}><X aria-hidden=\"true\" /></button>\n <img src={activeImage.url} alt={activeImage.name} />\n </div>\n </div>, document.body)}\n </>;\n}\n","const VIDEO_ID = /^[A-Za-z0-9_-]{11}$/;\nconst HOSTS = new Set(['youtube.com', 'www.youtube.com', 'm.youtube.com', 'music.youtube.com', 'youtube-nocookie.com', 'www.youtube-nocookie.com']);\nfunction seconds(value) {\n if (!value) return 0;\n if (/^\\d+$/.test(value)) return Math.min(Number(value), 604800);\n const parts = /^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/.exec(value);\n return parts ? Math.min(Number(parts[1] || 0) * 3600 + Number(parts[2] || 0) * 60 + Number(parts[3] || 0), 604800) : 0;\n}\nexport function parseYouTubeUrl(value) {\n if (typeof value !== 'string' || /[\\s\\\\]/.test(value)) return null;\n try {\n const url = new URL(/^[a-z][a-z\\d+.-]*:/i.test(value) ? value : `https://${value}`);\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password || url.port) return null;\n const host = url.hostname.toLowerCase();\n const parts = url.pathname.split('/').filter(Boolean);\n let id;\n if (host === 'youtu.be' || host === 'www.youtu.be') id = parts.length === 1 ? parts[0] : null;\n else if (HOSTS.has(host)) {\n if (url.pathname === '/watch') id = url.searchParams.get('v');\n else if (['shorts', 'embed', 'live'].includes(parts[0]) && parts.length === 2) id = parts[1];\n }\n if (!VIDEO_ID.test(id ?? '')) return null;\n const start = seconds(url.searchParams.get('start') || url.searchParams.get('t') || new URLSearchParams(url.hash.slice(1)).get('t'));\n const suffix = start ? `&start=${start}` : '';\n return { id, start, watchUrl: `https://www.youtube.com/watch?v=${id}${start ? `&t=${start}s` : ''}`,\n embedUrl: `https://www.youtube-nocookie.com/embed/${id}?playsinline=1${suffix}` };\n } catch { return null; }\n}\n/** At most one player per message; never embed arbitrary user-provided HTML or hosts. */\nexport function findYouTubeVideo(text) {\n if (typeof text !== 'string') return null;\n const candidates = text.matchAll(/(?:^|[\\s(<])((?:https?:\\/\\/|www\\.|(?:youtube\\.com|youtu\\.be)\\/)[^\\s<>\"']+)/gi);\n for (const [, candidate] of candidates) {\n const video = parseYouTubeUrl(candidate.replace(/[).,!?;:\\]}]+$/, ''));\n if (video) return video;\n }\n return null;\n}\n","import { useContext, useMemo } from 'react';\nimport { ChatContext } from '../../provider/ChatContext.js';\nimport { findYouTubeVideo } from '../../media/youtube/youtubeLinks.js';\nimport '../styles/YouTubePreview.css';\n\nexport default function YouTubePreview({ text }) {\n const context = useContext(ChatContext);\n const video = useMemo(() => findYouTubeVideo(text), [text]);\n if (!video || context?.config?.features === false || context?.config?.features?.youtube === false) return null;\n return <div className=\"chat-youtube-preview\">\n <iframe key={`${video.id}:${video.start}`} src={video.embedUrl} title={`Video de YouTube (${video.id})`}\n loading=\"lazy\" referrerPolicy=\"strict-origin-when-cross-origin\"\n allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen\" allowFullScreen />\n <a href={video.watchUrl} target=\"_blank\" rel=\"noopener noreferrer\">Abrir en YouTube ↗</a>\n </div>;\n}\n","import { customEmojis } from './customEmojis';\n\n// emojibase-data (~1.4 MB of JSON) is loaded on demand with dynamic import() so it lands in its own\n// chunks instead of the main bundle. Until it arrives the sync API below answers from the custom\n// emojis and the legacy EMOJI_SHORTCUTS only; subscribeEmojiData/useEmojiDataReady notify when ready.\nconst loadSources = () => Promise.all([\n import('emojibase-data/en/compact.json'),\n import('emojibase-data/es/compact.json'),\n import('emojibase-data/en/shortcodes/github.json'),\n import('emojibase-data/en/shortcodes/emojibase.json'),\n import('emojibase-data/en/shortcodes/iamcal.json'),\n import('emojibase-data/es/messages.json'),\n]).then((modules) => modules.map((mod) => mod.default ?? mod));\n\n// Historical LIRA shortcuts are compatibility aliases, not a second emoji catalog.\nexport const EMOJI_SHORTCUTS = {\n // Smileys & Emotion\n grin: '😀',\n smile: '😄',\n smiley: '😃',\n grinning: '😀',\n joy: '😂',\n rofl: '🤣',\n laugh: '😂',\n lol: '😂',\n sweat_smile: '😅',\n sweat: '😅',\n blush: '😊',\n innocent: '😇',\n angel: '😇',\n wink: '😉',\n relieved: '😌',\n heart_eyes: '😍',\n kissing_heart: '😘',\n kissing: '😗',\n kissing_smiling_eyes: '😙',\n kissing_closed_eyes: '😚',\n yum: '😋',\n stuck_out_tongue: '😛',\n stuck_out_tongue_winking_eye: '😜',\n stuck_out_tongue_closed_eyes: '😝',\n zany_face: '🤪',\n face_with_raised_eyebrow: '🤨',\n monocle_face: '🧐',\n nerd_face: '🤓',\n sunglasses: '😎',\n disguised_face: '🥸',\n star_struck: '🤩',\n partying_face: '🥳',\n smirk: '😏',\n unamused: '😒',\n disappointed: '😞',\n pensive: '😔',\n worried: '😟',\n confused: '😕',\n slightly_frowning_face: '🙁',\n frowning_face: '☹️',\n open_mouth: '😮',\n hushed: '😯',\n astonished: '😲',\n flushed: '😳',\n fearful: '😨',\n cold_sweat: '😰',\n disappointed_relieved: '😥',\n cry: '😢',\n sob: '😭',\n scream: '😱',\n confounded: '😖',\n persevere: '😣',\n weary: '😩',\n tired_face: '😫',\n angry: '😠',\n rage: '😡',\n face_with_symbols_on_mouth: '🤬',\n mask: '😷',\n face_with_thermometer: '🤒',\n face_with_head_bandage: '🤕',\n nauseated_face: '🤢',\n vomiting_face: '🤮',\n sneezing_face: '🤧',\n hot_face: '🥵',\n cold_face: '🥶',\n woozy_face: '🥴',\n dizzy_face: '😵',\n exploding_head: '🤯',\n cowboy_hat_face: '🤠',\n clown_face: '🤡',\n lying_face: '🤥',\n shushing_face: '🤫',\n thinking_face: '🤔',\n zipper_mouth_face: '🤐',\n face_with_raised_eyebrow: '🤨',\n neutral_face: '😐',\n expressionless: '😑',\n no_mouth: '😶',\n smirking_face: '😏',\n unamused_face: '😒',\n rolling_eyes: '🙄',\n grimacing_face: '😬',\n lying_face: '🤥',\n \n // Hearts\n heart: '❤️',\n red_heart: '❤️',\n orange_heart: '🧡',\n yellow_heart: '💛',\n green_heart: '💚',\n blue_heart: '💙',\n purple_heart: '💜',\n brown_heart: '🤎',\n black_heart: '🖤',\n white_heart: '🤍',\n broken_heart: '💔',\n heart_exclamation: '❣️',\n two_hearts: '💕',\n revolving_hearts: '💞',\n heartbeat: '💓',\n sparkling_heart: '💖',\n growing_heart: '💗',\n cupid: '💘',\n gift_heart: '💝',\n heart_decoration: '💟',\n \n // Hands & Gestures\n thumbsup: '👍',\n thumbs_down: '👎',\n clap: '👏',\n pray: '🙏',\n handshake: '🤝',\n fist: '👊',\n left_facing_fist: '🤛',\n right_facing_fist: '🤜',\n punch: '👊',\n wave: '👋',\n raised_hand: '✋',\n vulcan_salute: '🖖',\n ok_hand: '👌',\n pinched_fingers: '🤌',\n pinching_hand: '🤏',\n victory_hand: '✌️',\n crossed_fingers: '🤞',\n love_you_gesture: '🤟',\n sign_of_the_horns: '🤘',\n call_me_hand: '🤙',\n backhand_index_pointing_left: '👈',\n backhand_index_pointing_right: '👉',\n backhand_index_pointing_up: '👆',\n middle_finger: '🖕',\n backhand_index_pointing_down: '👇',\n index_pointing_up: '☝️',\n raised_back_of_hand: '🤚',\n palm_down_hand: '🫳',\n palm_up_hand: '🫴',\n writing_hand: '✍️',\n nail_care: '💅',\n selfie: '🤳',\n flexed_biceps: '💪',\n mechanical_arm: '🦾',\n mechanical_leg: '🦿',\n \n // Common Objects & Symbols\n fire: '🔥',\n star: '⭐',\n star2: '🌟',\n sparkles: '✨',\n dizzy: '💫',\n boom: '💥',\n collision: '💥',\n anger: '💢',\n sweat_drops: '💦',\n dash: '💨',\n hole: '🕳️',\n bomb: '💣',\n speech_balloon: '💬',\n thought_balloon: '💭',\n zzz: '💤',\n \n // Misc\n check: '✅',\n white_check_mark: '✅',\n heavy_check_mark: '✔️',\n x: '❌',\n negative_squared_cross_mark: '❎',\n '100': '💯',\n hundred: '💯',\n ok: '🆗',\n new: '🆕',\n cool: '🆒',\n free: '🆓',\n vs: '🆚',\n copyright: '©️',\n registered: '®️',\n tm: '™️',\n \n // Activities\n soccer: '⚽',\n basketball: '🏀',\n football: '🏈',\n baseball: '⚾',\n tennis: '🎾',\n volleyball: '🏐',\n rugby_football: '🏉',\n pool_8ball: '🎱',\n ping_pong: '🏓',\n badminton: '🏸',\n goal_net: '🥅',\n golf: '⛳',\n fishing_pole_and_fish: '🎣',\n running: '🏃',\n running_shirt_with_sash: '🏃‍♂️',\n dancer: '💃',\n man_dancing: '🕺',\n dancer_woman: '💃',\n dancer_man: '🕺',\n levitate: '🕴️',\n \n // Food & Drink\n pizza: '🍕',\n hamburger: '🍔',\n fries: '🍟',\n hotdog: '🌭',\n sandwich: '🥪',\n taco: '🌮',\n burrito: '🌯',\n stuffed_flatbread: '🥙',\n falafel: '🧆',\n egg: '🥚',\n cooking: '🍳',\n shallow_pan_of_food: '🥘',\n pot_of_food: '🍲',\n bowl_with_spoon: '🥣',\n green_salad: '🥗',\n popcorn: '🍿',\n butter: '🧈',\n salt: '🧂',\n canned_food: '🥫',\n bento: '🍱',\n rice_cracker: '🍘',\n rice_ball: '🍙',\n rice: '🍚',\n curry: '🍛',\n ramen: '🍜',\n spaghetti: '🍝',\n sweet_potato: '🍠',\n oden: '🍢',\n sushi: '🍣',\n fried_shrimp: '🍤',\n fish_cake: '🍥',\n moon_cake: '🥮',\n dango: '🍡',\n dumpling: '🥟',\n fortune_cookie: '🥠',\n takeout_box: '🥡',\n crab: '🦀',\n lobster: '🦞',\n shrimp: '🍤',\n squid: '🦑',\n oyster: '🦪',\n icecream: '🍦',\n shaved_ice: '🍧',\n ice_cream: '🍨',\n doughnut: '🍩',\n cookie: '🍪',\n birthday: '🎂',\n cake: '🍰',\n cupcake: '🧁',\n pie: '🥧',\n chocolate_bar: '🍫',\n candy: '🍬',\n lollipop: '🍭',\n custard: '🍮',\n honey_pot: '🍯',\n baby_bottle: '🍼',\n milk_glass: '🥛',\n coffee: '☕',\n tea: '🍵',\n sake: '🍶',\n bottle_with_popping_cork: '🍾',\n wine_glass: '🍷',\n cocktail_glass: '🍸',\n tropical_drink: '🍹',\n beer: '🍺',\n beer_mug: '🍻',\n clinking_glasses: '🥂',\n tumbler_glass: '🥃',\n cup_with_straw: '🥤',\n beverage_box: '🧃',\n mate: '🧉',\n ice_cube: '🧊',\n \n // Animals\n dog: '🐶',\n cat: '🐱',\n mouse: '🐭',\n hamster: '🐹',\n rabbit: '🐰',\n fox_face: '🦊',\n bear: '🐻',\n panda_face: '🐼',\n koala: '🐨',\n tiger: '🐯',\n lion: '🦁',\n cow: '🐮',\n pig: '🐷',\n pig_nose: '🐽',\n frog: '🐸',\n monkey_face: '🐵',\n see_no_evil: '🙈',\n hear_no_evil: '🙉',\n speak_no_evil: '🙊',\n monkey: '🐒',\n chicken: '🐔',\n penguin: '🐧',\n bird: '🐦',\n baby_chick: '🐤',\n hatching_chick: '🐣',\n hatched_chick: '🐥',\n duck: '🦆',\n eagle: '🦅',\n owl: '🦉',\n bat: '🦇',\n wolf: '🐺',\n boar: '🐗',\n horse: '🐴',\n unicorn: '🦄',\n bee: '🐝',\n bug: '🐛',\n butterfly: '🦋',\n snail: '🐌',\n lady_beetle: '🐞',\n ant: '🐜',\n mosquito: '🦟',\n microbe: '🦠',\n \n // Weather & Nature\n sunny: '☀️',\n cloud: '☁️',\n cloud_with_lightning: '⛈️',\n cloud_with_rain: '🌧️',\n cloud_with_snow: '🌨️',\n snowflake: '❄️',\n snowman: '☃️',\n comet: '☄️',\n umbrella: '☂️',\n umbrella_with_rain_drops: '☔',\n rainbow: '🌈',\n sun_behind_cloud: '🌤️',\n sun_behind_rain_cloud: '🌦️',\n lightning: '⚡',\n fire: '🔥',\n droplet: '💧',\n ocean: '🌊',\n \n // Miscellaneous\n music: '🎵',\n notes: '🎶',\n microphone: '🎤',\n headphones: '🎧',\n musical_score: '🎼',\n musical_keyboard: '🎹',\n drum: '🥁',\n saxophone: '🎷',\n trumpet: '🎺',\n guitar: '🎸',\n violin: '🎻',\n game_die: '🎲',\n dart: '🎯',\n video_game: '🎮',\n joystick: '🕹️',\n slot_machine: '🎰',\n direct_hit: '🎯',\n trophy: '🏆',\n medal: '🏅',\n sports_medal: '🏅',\n first_place_medal: '🥇',\n second_place_medal: '🥈',\n third_place_medal: '🥉',\n reminder_ribbon: '🎗️',\n rosette: '🏵️',\n ticket: '🎫',\n tickets: '🎟️',\n circus_tent: '🎪',\n performing_arts: '🎭',\n art: '🎨',\n paintbrush: '🖌️',\n crayon: '🖍️',\n pencil: '✏️',\n pen: '🖊️',\n fountain_pen: '🖋️',\n brush: '🖌️',\n ruler: '📏',\n pencil2: '✏️',\n black_nib: '✒️',\n memo: '📝',\n briefcase: '💼',\n file_folder: '📁',\n open_file_folder: '📂',\n page_with_curl: '📃',\n page_facing_up: '📄',\n calendar: '📅',\n calendar2: '📆',\n card_index: '📇',\n chart_with_upwards_trend: '📈',\n chart_with_downwards_trend: '📉',\n bar_chart: '📊',\n clipboard: '📋',\n pushpin: '📌',\n round_pushpin: '📍',\n paperclip: '📎',\n linked_paperclips: '🖇️',\n straight_ruler: '📏',\n triangular_ruler: '📐',\n scissors: '✂️',\n card_file_box: '🗃️',\n file_cabinet: '🗄️',\n wastebasket: '🗑️',\n lock: '🔒',\n unlock: '🔓',\n lock_with_ink_pen: '🔏',\n closed_lock_with_key: '🔐',\n key: '🔑',\n old_key: '🗝️',\n hammer: '🔨',\n axe: '🪓',\n pick: '⛏️',\n hammer_and_pick: '⚒️',\n hammer_and_wrench: '🛠️',\n dagger: '🗡️',\n crossed_swords: '⚔️',\n gun: '🔫',\n bow_and_arrow: '🏹',\n shield: '🛡️',\n carpentry_saw: '🪚',\n wrench: '🔧',\n nut_and_bolt: '🔩',\n gear: '⚙️',\n clamp: '🗜️',\n balance_scale: '⚖️',\n probe: '🔍',\n mag: '🔍',\n mag_right: '🔎',\n flashlight: '🔦',\n candle: '🕯️',\n light_bulb: '💡',\n electric_light_bulb: '💡',\n electric_plug: '🔌',\n battery: '🔋',\n computer: '💻',\n desktop_computer: '🖥️',\n printer: '🖨️',\n keyboard: '⌨️',\n mouse_three_button: '🖱️',\n trackball: '🖲️',\n minidisc: '💽',\n floppy_disk: '💾',\n cd: '💿',\n dvd: '📀',\n abacus: '🧮',\n movie_camera: '🎥',\n film_frames: '🎞️',\n film_projector: '📽️',\n clapper: '🎬',\n tv: '📺',\n camera: '📷',\n camera_with_flash: '📸',\n video_camera: '📹',\n vhs: '📼',\n phone: '📞',\n telephone: '☎️',\n pager: '📟',\n fax: '📠',\n email: '📧',\n mailbox: '📫',\n mailbox_with_mail: '📬',\n mailbox_with_no_mail: '📭',\n package: '📦',\n inbox_tray: '📥',\n outbox_tray: '📤',\n envelope: '✉️',\n incoming_envelope: '📨',\n envelope_with_arrow: '📩',\n outbox_tray: '📤',\n inbox_tray: '📥',\n postbox: '📮',\n mailbox_closed: '📪',\n mailbox: '📫',\n \n // Travel & Places\n car: '🚗',\n taxi: '🚕',\n blue_car: '🚙',\n bus: '🚌',\n trolleybus: '🚎',\n racing_car: '🏎️',\n police_car: '🚓',\n ambulance: '🚑',\n fire_engine: '🚒',\n minibus: '🚐',\n truck: '🚚',\n articulated_lorry: '🚛',\n tractor: '🚜',\n racing_motorcycle: '🏍️',\n motorcycle: '🛵',\n motor_scooter: '🛵',\n kick_scooter: '🛴',\n bike: '🚲',\n motorway: '🛣️',\n railway_track: '🛤️',\n steam_locomotive: '🚂',\n railway_car: '🚃',\n high_speed_train: '🚄',\n bullet_train_side: '🚅',\n bullet_train_front: '🚅',\n train2: '🚆',\n metro: '🚇',\n light_rail: '🚈',\n station: '🚉',\n tram: '🚊',\n monorail: '🚝',\n mountain_railway: '🚞',\n train: '🚋',\n busstop: '🚏',\n motor_boat: '🛥️',\n ship: '🚢',\n rowboat: '🚣',\n speedboat: '🚤',\n ferry: '⛴️',\n sailboat: '⛵',\n boat: '🛥️',\n anchor: '⚓',\n rocket: '🚀',\n flying_saucer: '🛸',\n helicopter: '🚁',\n small_airplane: '🛩️',\n airplane: '✈️',\n airplane_departure: '🛫',\n airplane_arrival: '🛬',\n seat: '💺',\n satellite: '🛰️',\n bellhop_bell: '🛎️',\n luggage: '🧳',\n hourglass: '⏳',\n hourglass_flowing_sand: '⏳',\n watch: '⌚',\n alarm_clock: '⏰',\n stopwatch: '⏱️',\n timer_clock: '⏲️',\n mantelpiece_clock: '🕰️',\n clock12: '🕛',\n clock1: '🕐',\n clock2: '🕑',\n clock3: '🕒',\n clock4: '🕓',\n clock5: '🕔',\n clock6: '🕕',\n clock7: '🕖',\n clock8: '🕗',\n clock9: '🕘',\n clock10: '🕙',\n clock11: '🕚',\n clock1230: '🕧',\n clock130: '🕜',\n clock230: '🕝',\n clock330: '🕞',\n clock430: '🕟',\n clock530: '🕠',\n clock630: '🕡',\n clock730: '🕢',\n clock830: '🕣',\n clock930: '🕤',\n clock1030: '🕥',\n clock1130: '🕦',\n new_moon: '🌑',\n waxing_crescent_moon: '🌒',\n first_quarter_moon: '🌓',\n waxing_gibbous_moon: '🌔',\n full_moon: '🌕',\n waning_gibbous_moon: '🌖',\n last_quarter_moon: '🌗',\n waning_crescent_moon: '🌘',\n crescent_moon: '🌙',\n new_moon_with_face: '🌚',\n first_quarter_moon_with_face: '🌛',\n last_quarter_moon_with_face: '🌜',\n thermometer: '🌡️',\n sun: '☀️',\n full_moon_with_face: '🌝',\n sun_with_face: '🌞',\n ringed_planet: '🪐',\n star: '⭐',\n star2: '🌟',\n stars: '🌟',\n milky_way: '🌌',\n cloud: '☁️',\n cloud_with_lightning_and_rain: '⛈️',\n sun_behind_small_cloud: '🌤️',\n sun_behind_large_cloud: '🌥️',\n sun_behind_rain_cloud: '🌦️',\n cloud_with_rain: '🌧️',\n cloud_with_snow: '🌨️',\n cloud_with_lightning: '🌩️',\n tornado: '🌪️',\n fog: '🌫️',\n wind_face: '🌬️',\n cyclone: '🌀',\n rainbow: '🌈',\n closed_umbrella: '🌂',\n open_umbrella: '☂️',\n umbrella: '☔',\n parasol_on_ground: '⛱️',\n zap: '⚡',\n snowflake: '❄️',\n snowman_with_snow: '☃️',\n snowman: '☃️',\n comet: '☄️',\n fire: '🔥',\n droplet: '💧',\n sweat_drops: '💦',\n ocean: '🌊',\n \n // Flags\n flag_us: '🇺🇸',\n flag_gb: '🇬🇧',\n flag_uk: '🇬🇧',\n flag_mx: '🇲🇽',\n flag_ca: '🇨🇦',\n flag_es: '🇪🇸',\n flag_fr: '🇫🇷',\n flag_de: '🇩🇪',\n flag_it: '🇮🇹',\n flag_jp: '🇯🇵',\n flag_kr: '🇰🇷',\n flag_cn: '🇨🇳',\n flag_in: '🇮🇳',\n flag_br: '🇧🇷',\n flag_ar: '🇦🇷',\n flag_au: '🇦🇺',\n flag_za: '🇿🇦',\n flag_ru: '🇷🇺',\n flag_sa: '🇸🇦',\n flag_ae: '🇦🇪',\n flag_il: '🇮🇱',\n flag_tr: '🇹🇷',\n flag_eg: '🇪🇬',\n flag_ng: '🇳🇬',\n flag_ke: '🇰🇪',\n flag_id: '🇮🇩',\n flag_ph: '🇵🇭',\n flag_th: '🇹🇭',\n flag_vn: '🇻🇳',\n flag_my: '🇲🇾',\n flag_sg: '🇸🇬',\n};\n\n// Curated Spanish aliases: everyday words that should land on the \"obvious\" emoji first.\nconst SPANISH_ALIASES = {\n '❤️': ['corazon', 'amor', 'te quiero'],\n '😂': ['risa', 'jaja', 'jajaja', 'llorar de risa'],\n '🤣': ['carcajada', 'muerto de risa'],\n '😀': ['feliz', 'contento'],\n '😊': ['sonrisa', 'sonrojado'],\n '😍': ['enamorado', 'me encanta'],\n '😘': ['beso'],\n '😉': ['guino'],\n '😎': ['genial', 'lentes de sol'],\n '😢': ['triste'],\n '😭': ['llorar', 'llanto'],\n '😡': ['enojado', 'furioso'],\n '😱': ['susto', 'miedo'],\n '🤔': ['pensando', 'pensar', 'hmm'],\n '🙄': ['ojos en blanco'],\n '😴': ['dormir', 'sueno'],\n '🔥': ['fuego', 'candela'],\n '👍': ['pulgar', 'pulgar arriba', 'like', 'bien'],\n '👎': ['pulgar abajo', 'dislike', 'mal'],\n '👏': ['aplausos', 'aplaudir'],\n '🙏': ['gracias', 'por favor', 'rezar'],\n '👋': ['hola', 'adios', 'saludo'],\n '💪': ['fuerza', 'musculo'],\n '🤝': ['trato', 'acuerdo'],\n '👌': ['perfecto'],\n '🎉': ['fiesta', 'celebrar', 'felicidades'],\n '🎂': ['cumpleanos', 'pastel'],\n '🎁': ['regalo'],\n '💯': ['cien'],\n '✅': ['listo', 'hecho'],\n '❌': ['error', 'cancelar'],\n '⭐': ['estrella'],\n '✨': ['brillo', 'destellos'],\n '💩': ['caca'],\n '👀': ['mirar', 'ojos'],\n '🚀': ['cohete'],\n '💰': ['dinero', 'plata'],\n};\n\nexport const normalizeEmojiQuery = (value) => String(value ?? '').normalize('NFD')\n .replace(/\\p{M}/gu, '').toLowerCase().replace(/:/g, '').replace(/_/g, ' ')\n .replace(/\\s+/g, ' ').trim();\n\nconst TONE_RE = /[\\u{1F3FB}-\\u{1F3FF}]/gu;\nconst identity = (value) => String(value).replace(/️/g, '');\nconst baseIdentity = (value) => identity(value).replace(TONE_RE, '');\nconst asList = (value) => (Array.isArray(value) ? value : value ? [value] : []);\nconst capitalize = (value) => (value ? value.charAt(0).toUpperCase() + value.slice(1) : value);\nconst compact = (value) => value.replace(/ /g, '');\nconst COMPONENT_GROUP = 2;\n\nexport const SKIN_TONES = [\n { tone: 0, label: 'Predeterminado', swatch: '✋' },\n { tone: 1, label: 'Claro', swatch: '✋🏻' },\n { tone: 2, label: 'Medio claro', swatch: '✋🏼' },\n { tone: 3, label: 'Medio', swatch: '✋🏽' },\n { tone: 4, label: 'Medio oscuro', swatch: '✋🏾' },\n { tone: 5, label: 'Oscuro', swatch: '✋🏿' },\n];\n\nconst buildCategories = (messages) => [['all', 'Todos'], ...messages.groups\n .filter((group) => group.order !== COMPONENT_GROUP)\n .map((group) => [String(group.order), capitalize(group.message)])];\n\n// Live binding: only 'all' until emojibase-data loads (see loadEmojiData).\nexport let emojiCategories = [['all', 'Todos']];\nexport function getEmojiCategories() { return emojiCategories; }\n\nconst legacyByEmoji = new Map();\nfor (const [alias, emoji] of Object.entries(EMOJI_SHORTCUTS)) {\n const key = identity(emoji);\n if (!legacyByEmoji.has(key)) legacyByEmoji.set(key, []);\n legacyByEmoji.get(key).push(alias);\n}\nconst curatedByEmoji = new Map(Object.entries(SPANISH_ALIASES).map(([emoji, list]) => [identity(emoji), list]));\n\n// Only skins where every modifier is the same tone (1F3FB..1F3FF → 1..5).\nconst toneOfHex = (hexcode) => {\n const tones = hexcode.split('-').filter((part) => /^1F3F[B-F]$/.test(part));\n if (!tones.length || tones.some((tone) => tone !== tones[0])) return 0;\n return parseInt(tones[0].slice(-1), 16) - 10;\n};\nconst buildSkins = (skins) => {\n const byTone = new Map();\n for (const skin of skins || []) {\n const tone = toneOfHex(skin.hexcode);\n if (tone && !byTone.has(tone)) byTone.set(tone, { tone, emoji: skin.unicode });\n }\n return byTone.size ? [...byTone.values()].sort((a, b) => a.tone - b.tone) : undefined;\n};\n\n// Built once when emojibase-data loads. Index contains BASE emojis only; skins hang off each record.\nfunction buildUnicodeIndex({ english, spanish, githubShortcodes, emojibaseShortcodes, iamcalShortcodes }) {\n const spanishByHex = new Map(spanish.map((item) => [item.hexcode, item]));\n return english\n .filter((item) => item.group != null && item.group !== COMPONENT_GROUP)\n .map((item) => {\n const localized = spanishByHex.get(item.hexcode);\n const key = identity(item.unicode);\n const legacy = legacyByEmoji.get(key) || [];\n const primary = [...legacy, ...asList(githubShortcodes[item.hexcode])];\n const secondary = [...asList(emojibaseShortcodes[item.hexcode]), ...asList(iamcalShortcodes[item.hexcode])];\n const curated = curatedByEmoji.get(key) || [];\n const shortcodes = [...new Set([...primary, ...secondary, ...curated.map((alias) => alias.replace(/ /g, '_'))])];\n const shortcode = shortcodes[0] || item.label.replace(/[^a-z0-9]+/gi, '_').replace(/^_|_$/g, '').toLowerCase();\n if (!shortcodes.length) shortcodes.push(shortcode);\n const labelEs = localized?.label || item.label;\n const keywords = [...new Set([...(localized?.tags || []), ...(item.tags || [])].map(normalizeEmojiQuery).filter(Boolean))];\n return {\n emoji: item.unicode,\n hexcode: item.hexcode,\n shortcode,\n shortcodes,\n label: capitalize(labelEs),\n labelEn: item.label,\n source: 'unicode',\n category: String(item.group),\n keywords,\n skins: buildSkins(item.skins),\n order: item.order ?? 0,\n terms: [...new Set([...shortcodes, labelEs, item.label, ...keywords].map(normalizeEmojiQuery).filter(Boolean))],\n // Primary aliases win resolve conflicts over secondary emojibase/iamcal names.\n _primary: [...primary, ...curated],\n };\n })\n .sort((a, b) => a.order - b.order);\n}\n\nconst customIndex = customEmojis.map((item, position) => ({\n ...item,\n emoji: `:${item.shortcode}:`,\n shortcodes: [item.shortcode, ...(item.shortcodes || [])],\n label: capitalize(item.label || item.shortcode),\n labelEn: item.label || item.shortcode,\n source: 'custom',\n category: 'custom',\n keywords: (item.keywords || []).map(normalizeEmojiQuery).filter(Boolean),\n skins: undefined,\n order: 100000 + position,\n terms: [...new Set([item.shortcode, item.label, ...(item.keywords || [])].filter(Boolean).map(normalizeEmojiQuery))],\n}));\n\nconst words = (value) => value.split(' ').filter(Boolean);\nconst setOnce = (map, key, value) => { if (key && !map.has(key)) map.set(key, value); };\n\nfunction buildState(unicodeIndex) {\n // Strip internal helper fields from public records.\n const primaryAliases = new Map();\n for (const record of unicodeIndex) {\n primaryAliases.set(record, record._primary.map(normalizeEmojiQuery));\n delete record._primary;\n }\n\n const index = [...unicodeIndex, ...customIndex];\n\n // Precomputed normalized search data (parallel to `index`).\n const searchData = index.map((record) => {\n const aliases = [...new Set(record.shortcodes.map(normalizeEmojiQuery).filter(Boolean))];\n const labels = [...new Set([record.label, record.labelEn].filter(Boolean).map(normalizeEmojiQuery))];\n return {\n record,\n aliases,\n aliasCompact: aliases.map(compact),\n aliasWords: aliases.flatMap((alias) => words(alias).map((word) => [word, alias.length])),\n labels,\n labelWords: labels.flatMap((label) => words(label).map((word) => [word, label.length])),\n keywords: record.keywords,\n keywordWords: record.keywords.flatMap((keyword) => words(keyword).map((word) => [word, keyword.length])),\n terms: record.terms,\n };\n });\n\n // Lookup maps.\n const byEmoji = new Map();\n const aliasMap = new Map();\n const labelMap = new Map();\n const termMap = new Map();\n for (const record of unicodeIndex) {\n setOnce(byEmoji, identity(record.emoji), record);\n for (const skin of record.skins || []) setOnce(byEmoji, identity(skin.emoji), record);\n for (const alias of primaryAliases.get(record)) setOnce(aliasMap, alias, record);\n }\n for (const data of searchData) {\n if (data.record.source !== 'unicode') continue;\n for (const alias of data.aliases) { setOnce(aliasMap, alias, data.record); setOnce(aliasMap, compact(alias), data.record); }\n for (const label of data.labels) setOnce(labelMap, label, data.record);\n for (const term of data.terms) setOnce(termMap, term, data.record);\n }\n // Fallback lookup for toned sequences not listed explicitly (e.g. mixed tones).\n for (const record of unicodeIndex) setOnce(byEmoji, baseIdentity(record.emoji), record);\n return { index, searchData, byEmoji, aliasMap, labelMap, termMap };\n}\n\nconst customByCode = new Map(customIndex.map((record) => [normalizeEmojiQuery(record.shortcode), record]));\n\n// Lazy loading state. `state` starts with custom emojis only and is swapped atomically on load.\nlet state = buildState([]);\nlet loaded = false;\nlet loading = null;\nconst listeners = new Set();\n\nexport function isEmojiDataLoaded() { return loaded; }\n\nexport function subscribeEmojiData(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n}\n\n// Loads emojibase-data once (cached promise). Resolves true when ready, false if loading failed\n// (a later call retries).\nexport function loadEmojiData() {\n if (loaded) return Promise.resolve(true);\n if (!loading) {\n loading = loadSources().then(([english, spanish, githubShortcodes, emojibaseShortcodes, iamcalShortcodes, messages]) => {\n state = buildState(buildUnicodeIndex({ english, spanish, githubShortcodes, emojibaseShortcodes, iamcalShortcodes }));\n emojiCategories = buildCategories(messages);\n loaded = true;\n for (const listener of [...listeners]) {\n try { listener(); } catch (error) { console.error('[chat] emoji data listener failed', error); }\n }\n return true;\n }).catch((error) => {\n loading = null;\n console.warn('[chat] could not load emojibase-data', error);\n return false;\n });\n }\n return loading;\n}\n\nconst ensureEmojiData = () => { if (!loaded && !loading) loadEmojiData(); };\n\n// Tiers: 0 exact alias/label · 1 alias prefix · 2 label/word prefix · 3 keyword prefix · 4 substring.\n// Inside a tier the shortest matching term wins.\nconst TIER = 10000;\nconst NO_MATCH = Infinity;\nfunction scoreWord(data, q) {\n if (data.aliases.includes(q) || data.aliasCompact.includes(q) || data.labels.includes(q)) return q.length;\n let best = NO_MATCH;\n for (let i = 0; i < data.aliases.length; i += 1) {\n if (data.aliases[i].startsWith(q) || data.aliasCompact[i].startsWith(q)) best = Math.min(best, TIER + data.aliases[i].length);\n }\n if (best !== NO_MATCH) return best;\n for (const label of data.labels) if (label.startsWith(q)) best = Math.min(best, 2 * TIER + label.length);\n for (const [word, length] of data.labelWords) if (word.startsWith(q)) best = Math.min(best, 2 * TIER + length);\n for (const [word, length] of data.aliasWords) if (word.startsWith(q)) best = Math.min(best, 2 * TIER + length);\n if (best !== NO_MATCH) return best;\n for (const keyword of data.keywords) if (keyword.startsWith(q)) best = Math.min(best, 3 * TIER + keyword.length);\n for (const [word, length] of data.keywordWords) if (word.startsWith(q)) best = Math.min(best, 3 * TIER + length);\n if (best !== NO_MATCH) return best;\n for (const term of data.terms) if (term.includes(q)) best = Math.min(best, 4 * TIER + term.length);\n return best;\n}\nfunction scoreQuery(data, q, parts) {\n let score = scoreWord(data, q);\n if (parts.length > 1 && score >= TIER) {\n let worst = 0;\n for (const part of parts) {\n worst = Math.max(worst, scoreWord(data, part));\n if (worst === NO_MATCH) break;\n }\n score = Math.min(score, worst);\n }\n return score;\n}\n\nexport function getAllEmojiShortcodes() { ensureEmojiData(); return state.index; }\n\nexport function searchEmojiShortcodes(query, { limit = 10, source, category } = {}) {\n ensureEmojiData();\n const normalized = normalizeEmojiQuery(query);\n const raw = identity(String(query ?? '').trim());\n const parts = words(normalized);\n const results = [];\n for (const data of state.searchData) {\n const { record } = data;\n if (source && record.source !== source) continue;\n if (category && category !== 'all' && record.category !== category) continue;\n let score;\n if (!normalized) score = 0;\n else if (raw && (identity(record.emoji) === raw || record.skins?.some((skin) => identity(skin.emoji) === raw))) score = 0;\n else score = scoreQuery(data, normalized, parts);\n if (score !== NO_MATCH) results.push({ record, score });\n }\n results.sort((a, b) => a.score - b.score || a.record.order - b.record.order);\n return results.slice(0, limit).map(({ record }) => record);\n}\n\nexport function getEmojisByCategory(category) {\n ensureEmojiData();\n if (!category || category === 'all') return state.index;\n return state.index.filter((record) => record.category === category);\n}\n\nexport function getEmojiRecord(emoji) {\n if (emoji == null) return null;\n ensureEmojiData();\n const value = String(emoji).trim();\n if (/^:[^:\\s]+:$/.test(value)) {\n const code = normalizeEmojiQuery(value);\n return customByCode.get(code) || state.aliasMap.get(code) || null;\n }\n return state.byEmoji.get(identity(value)) || state.byEmoji.get(baseIdentity(value)) || null;\n}\n\nexport function applySkinTone(itemOrEmoji, tone) {\n const record = typeof itemOrEmoji === 'string'\n ? getEmojiRecord(itemOrEmoji)\n : (itemOrEmoji?.skins ? itemOrEmoji : getEmojiRecord(itemOrEmoji?.emoji));\n const fallback = typeof itemOrEmoji === 'string' ? itemOrEmoji : itemOrEmoji?.emoji ?? null;\n if (!record) return fallback;\n const level = Number(tone) || 0;\n if (!level || !record.skins) return record.emoji;\n return record.skins.find((skin) => skin.tone === level)?.emoji || record.emoji;\n}\n\n// Resolve only completed tokens. Partial words stay editable in autocomplete.\nexport function resolveEmojiShortcode(shortcode) {\n const alias = String(shortcode).toLowerCase();\n if (Object.prototype.hasOwnProperty.call(EMOJI_SHORTCUTS, alias)) return EMOJI_SHORTCUTS[alias];\n const query = normalizeEmojiQuery(shortcode);\n if (!query) return null;\n ensureEmojiData();\n const { aliasMap, labelMap, termMap } = state;\n return (aliasMap.get(query) || aliasMap.get(compact(query)) || labelMap.get(query) || termMap.get(query))?.emoji || null;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n// Local-only emoji preferences (no backend, no cross-device sync).\nexport const MAX_RECENT_EMOJIS = 32;\nexport const MAX_FAVORITE_EMOJIS = 60;\nconst STORAGE_KEY = 'lira-emoji-preferences:v1';\nconst LEGACY_RECENTS_KEY = 'lira-chat-recent-emojis';\nconst MAX_EMOJI_LENGTH = 64;\nconst hasWindow = typeof window !== 'undefined';\n\n// C0/C1 control characters (ZWJ / variation selectors are allowed).\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARS = /[\\u0000-\\u001F\\u007F-\\u009F]/;\n\n/** Unicode emoji (optionally skin-toned) or custom shortcode like ':party_parrot:'. */\nfunction sanitizeEmoji(value) {\n if (typeof value !== 'string') return null;\n if (!value || value.length > MAX_EMOJI_LENGTH || CONTROL_CHARS.test(value)) return null;\n return value;\n}\n\nfunction sanitizeSkinTone(value) {\n return Number.isInteger(value) && value >= 0 && value <= 5 ? value : 0;\n}\n\n// Sanitize + dedupe (first occurrence wins) + cap.\nfunction cleanList(list, max) {\n if (!Array.isArray(list)) return [];\n const seen = new Set();\n const out = [];\n for (const raw of list) {\n const emoji = sanitizeEmoji(raw);\n if (!emoji || seen.has(emoji)) continue;\n seen.add(emoji);\n out.push(emoji);\n if (out.length >= max) break;\n }\n return out;\n}\n\nconst EMPTY = { recents: [], favorites: [], skinTone: 0 };\n\nfunction parse(data) {\n return {\n recents: cleanList(data?.recents, MAX_RECENT_EMOJIS),\n favorites: cleanList(data?.favorites, MAX_FAVORITE_EMOJIS),\n skinTone: sanitizeSkinTone(data?.skinTone),\n };\n}\n\nfunction readStorage() {\n if (!hasWindow) return { ...EMPTY };\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return { ...EMPTY };\n return parse(JSON.parse(raw));\n } catch {\n return { ...EMPTY };\n }\n}\n\n// Private mode / quota errors are ignored: state stays in memory.\nfunction writeStorage({ recents, favorites, skinTone }) {\n if (!hasWindow) return;\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ recents, favorites, skinTone }));\n } catch {\n /* keep in memory */\n }\n}\n\n/**\n * One-time migration from the legacy recents key (array or { recents }).\n * Returns true when the current storage key was written.\n */\nfunction migrateLegacy() {\n if (!hasWindow) return false;\n let wrote = false;\n try {\n const legacy = window.localStorage.getItem(LEGACY_RECENTS_KEY);\n if (legacy == null) return false;\n if (!window.localStorage.getItem(STORAGE_KEY)) {\n let data = null;\n try {\n data = JSON.parse(legacy);\n } catch {\n data = null;\n }\n const recents = cleanList(Array.isArray(data) ? data : data?.recents, MAX_RECENT_EMOJIS);\n writeStorage({ ...EMPTY, recents });\n wrote = true;\n }\n window.localStorage.removeItem(LEGACY_RECENTS_KEY);\n } catch {\n /* ignore */\n }\n return wrote;\n}\n\nexport function createEmojiPreferencesStore() {\n const store = createStore((set, get) => {\n // Persist after every local mutation.\n const commit = (next) => {\n set(next);\n writeStorage(get());\n };\n\n return {\n ...readStorage(),\n\n isFavorite: (emoji) => {\n const key = sanitizeEmoji(emoji);\n return key ? get().favorites.includes(key) : false;\n },\n\n toggleFavorite: (raw) => {\n const emoji = sanitizeEmoji(raw);\n if (!emoji) return;\n const { favorites } = get();\n if (favorites.includes(emoji)) {\n commit({ favorites: favorites.filter((item) => item !== emoji) });\n return;\n }\n commit({ favorites: [emoji, ...favorites].slice(0, MAX_FAVORITE_EMOJIS) });\n },\n\n addRecent: (raw) => {\n const emoji = sanitizeEmoji(raw);\n if (!emoji) return;\n const rest = get().recents.filter((item) => item !== emoji);\n commit({ recents: [emoji, ...rest].slice(0, MAX_RECENT_EMOJIS) });\n },\n\n setSkinTone: (tone) => {\n if (!Number.isInteger(tone) || tone < 0 || tone > 5) return;\n if (get().skinTone === tone) return;\n commit({ skinTone: tone });\n },\n\n clearRecents: () => commit({ recents: [] }),\n };\n });\n\n // Cross-tab sync: another tab wrote (or storage was cleared) -> re-read.\n // Explicit opt-in (no import-time side effects). Ref-counted: the listener is\n // registered once and removed when every caller has called its stop().\n let syncRefs = 0;\n let migrated = false;\n const onStorage = (event) => {\n if (event.key === STORAGE_KEY || event.key === null) store.setState(readStorage());\n };\n store.startSync = () => {\n if (!hasWindow) return () => {};\n if (!migrated) {\n migrated = true;\n if (migrateLegacy()) store.setState(readStorage());\n }\n if (typeof window.addEventListener !== 'function') return () => {};\n if (syncRefs === 0) window.addEventListener('storage', onStorage);\n syncRefs += 1;\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n syncRefs -= 1;\n if (syncRefs === 0) window.removeEventListener('storage', onStorage);\n };\n };\n return store;\n}\n\nconst emojiPreferencesStore = createEmojiPreferencesStore();\n/** Backward-compatible singleton hook; called without selector it returns the full state. */\nexport const useEmojiPreferences = Object.assign((selector) => useStore(emojiPreferencesStore, selector), {\n getState: emojiPreferencesStore.getState,\n setState: emojiPreferencesStore.setState,\n subscribe: emojiPreferencesStore.subscribe,\n});\n\nexport function startEmojiPreferencesSync(store = emojiPreferencesStore) {\n return (store === useEmojiPreferences ? emojiPreferencesStore : store).startSync();\n}\n","import { useEffect, useSyncExternalStore } from 'react';\nimport { isEmojiDataLoaded, loadEmojiData, subscribeEmojiData } from './emojiShortcodes';\n\n// True once emojibase-data has loaded; mounting the hook starts the (cached) load. Components use the\n// value as a memo/effect dependency so they recompute when the full catalog arrives.\nexport function useEmojiDataReady() {\n const ready = useSyncExternalStore(subscribeEmojiData, isEmojiDataLoaded, isEmojiDataLoaded);\n useEffect(() => { if (!ready) loadEmojiData(); }, [ready]);\n return ready;\n}\n","/* eslint-disable react/prop-types */\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Car, Clock, Flag, Hand, Heart, Lightbulb, PawPrint, Puzzle, Smile, Sparkles, Star, Trophy, Utensils, X } from 'lucide-react';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nimport { searchCustomEmojis } from '../../media/emoji/customEmojiCatalog';\nimport {\n SKIN_TONES, applySkinTone, emojiCategories, getEmojiRecord, getEmojisByCategory, searchEmojiShortcodes,\n} from '../../media/emoji/emojiShortcodes';\nimport { useEmojiPreferences } from '../../media/emoji/emojiPreferences';\nimport { useEmojiDataReady } from '../../media/emoji/useEmojiData';\nimport MessageText from './MessageText';\nimport '../styles/EmojiPicker.css';\n\nconst categoryIcons = { recent: Clock, favorites: Star, 0: Smile, 1: Hand, 2: Puzzle, 3: PawPrint, 4: Utensils, 5: Car, 6: Trophy, 7: Lightbulb, 8: Heart, 9: Flag, custom: Sparkles };\nconst CELL_SIZE = 40;\nconst ESTIMATED_COLUMNS = 9;\nconst LONG_PRESS_MS = 500;\n\n// Resolve a stored string (recent/favorite) back to a record for labels and preview.\nfunction resolveRecord(value, customRecords) {\n const custom = customRecords.find((item) => item.emoji === value);\n if (custom) return custom;\n const record = getEmojiRecord(value);\n return record || { emoji: value, shortcode: '', label: value, source: 'unicode' };\n}\n\nconst EmojiCell = memo(function EmojiCell({ record, value, favorite, disabled, onPick, onToggleFavorite, onPreview }) {\n const timer = useRef(null);\n const longPressed = useRef(false);\n const clear = () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } };\n useEffect(() => clear, []);\n return <button type=\"button\" role=\"option\" aria-selected=\"false\"\n className={`chat-emoji-cell${favorite ? ' chat-emoji-cell--fav' : ''}`}\n data-value={value} title={record.label} aria-label={record.label} disabled={disabled}\n onMouseDown={(event) => event.preventDefault()}\n onMouseEnter={() => onPreview(record, value)} onFocus={() => onPreview(record, value)}\n onContextMenu={(event) => { event.preventDefault(); if (!disabled) onToggleFavorite(record); }}\n onTouchStart={() => {\n longPressed.current = false; clear();\n timer.current = setTimeout(() => { longPressed.current = true; timer.current = null; if (!disabled) onToggleFavorite(record); }, LONG_PRESS_MS);\n }}\n onTouchMove={clear} onTouchEnd={clear} onTouchCancel={clear}\n onClick={(event) => {\n if (longPressed.current) { event.preventDefault(); longPressed.current = false; return; }\n onPick(value);\n }}>\n <MessageText text={value} />\n </button>;\n});\n\nfunction EmojiSection({ id, title, items, lazy, rootRef, children, ...cellProps }) {\n const ref = useRef(null);\n const [visible, setVisible] = useState(!lazy);\n useEffect(() => {\n if (visible || !ref.current) return undefined;\n if (typeof IntersectionObserver === 'undefined') { setVisible(true); return undefined; }\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) { setVisible(true); observer.disconnect(); }\n }, { root: rootRef.current, rootMargin: '400px 0px' });\n observer.observe(ref.current);\n return () => observer.disconnect();\n }, [visible, rootRef]);\n const minHeight = visible ? undefined : Math.ceil(items.length / ESTIMATED_COLUMNS) * CELL_SIZE;\n return <section ref={ref} className=\"chat-emoji-section\" data-section={id} aria-labelledby={`chat-emoji-sec-${id}`}>\n <h3 id={`chat-emoji-sec-${id}`} className=\"chat-emoji-section-title\">{title}</h3>\n <div className=\"chat-emoji-grid chat-emoji-grid--modern\" role=\"listbox\" aria-label={title} style={minHeight ? { minHeight } : undefined}>\n {visible && items.map(({ record, value }) => <EmojiCell key={value} record={record} value={value}\n favorite={cellProps.favoriteSet.has(record.emoji)} disabled={cellProps.disabled}\n onPick={cellProps.onPick} onToggleFavorite={cellProps.onToggleFavorite} onPreview={cellProps.onPreview} />)}\n </div>\n {children}\n </section>;\n}\n\nexport default function EmojiPicker({ onSelect, isOpen, onClose, disabled }) {\n const customRecords = useCustomEmojis();\n const recents = useEmojiPreferences((state) => state.recents);\n const favorites = useEmojiPreferences((state) => state.favorites);\n const skinTone = useEmojiPreferences((state) => state.skinTone);\n const addRecent = useEmojiPreferences((state) => state.addRecent);\n const toggleFavorite = useEmojiPreferences((state) => state.toggleFavorite);\n const setSkinTone = useEmojiPreferences((state) => state.setSkinTone);\n const emojiReady = useEmojiDataReady(); // catalog loads lazily; recompute sections when it lands\n\n const [query, setQuery] = useState('');\n const [toneOpen, setToneOpen] = useState(false);\n const [activeSection, setActiveSection] = useState(null);\n const [preview, setPreview] = useState(null);\n const bodyRef = useRef(null);\n const searchRef = useRef(null);\n const scrollFrame = useRef(0);\n\n const favoriteSet = useMemo(() => new Set(favorites || []), [favorites]);\n const toValue = useCallback((record) => (record.source === 'custom' ? record.emoji : applySkinTone(record, skinTone)), [skinTone]);\n const trimmed = query.trim();\n\n const sections = useMemo(() => {\n const wrap = (records) => {\n const seen = new Set();\n return records.map((record) => ({ record, value: toValue(record) }))\n .filter(({ value }) => (seen.has(value) ? false : seen.add(value)));\n };\n if (trimmed) {\n return [{ id: 'results', title: 'Resultados', items: wrap([...searchCustomEmojis(customRecords, query), ...searchEmojiShortcodes(query, { limit: 120 })].slice(0, 120)), lazy: false }];\n }\n const list = [];\n if (recents?.length) {\n const seen = new Set();\n list.push({ id: 'recent', title: 'Recientes', lazy: false,\n items: recents.filter((value) => (seen.has(value) ? false : seen.add(value))).map((value) => ({ record: resolveRecord(value, customRecords), value })) });\n }\n if (favorites?.length) list.push({ id: 'favorites', title: 'Favoritos', lazy: false, items: wrap(favorites.map((value) => resolveRecord(value, customRecords))) });\n emojiCategories.filter(([id]) => id !== 'all').forEach(([id, label], index) => {\n const records = getEmojisByCategory(id) || [];\n if (records.length) list.push({ id, title: label, items: wrap(records), lazy: index > 0 });\n });\n if (customRecords.length) list.push({ id: 'custom', title: 'Personalizados', items: wrap(customRecords), lazy: true });\n return list;\n }, [trimmed, query, recents, favorites, toValue, emojiReady, customRecords]);\n\n const firstItem = sections.find((section) => section.items.length)?.items[0] || null;\n const shown = preview || (firstItem && { record: firstItem.record, value: firstItem.value });\n\n const onPick = useCallback((value) => { onSelect(value); addRecent(value); }, [onSelect, addRecent]);\n const onToggleFavorite = useCallback((record) => toggleFavorite(record.emoji), [toggleFavorite]);\n const onPreview = useCallback((record, value) => setPreview({ record, value }), []);\n\n // Active tab follows scroll position.\n const updateActive = useCallback(() => {\n const body = bodyRef.current;\n if (!body) return;\n const nodes = [...body.querySelectorAll('[data-section]')];\n const top = body.getBoundingClientRect().top;\n let current = nodes[0]?.dataset.section || null;\n for (const node of nodes) { if (node.getBoundingClientRect().top - top <= 8) current = node.dataset.section; else break; }\n setActiveSection(current);\n }, []);\n useEffect(() => {\n if (!isOpen) return undefined;\n updateActive();\n return () => cancelAnimationFrame(scrollFrame.current);\n }, [isOpen, sections, updateActive]);\n useEffect(() => { if (!isOpen) { setQuery(''); setToneOpen(false); setPreview(null); } }, [isOpen]);\n\n const scrollToSection = (id) => {\n const body = bodyRef.current;\n const node = body?.querySelector(`[data-section=\"${id}\"]`);\n if (!node) return;\n body.scrollTo({ top: node.offsetTop - body.firstElementChild.offsetTop, behavior: 'auto' });\n setActiveSection(id);\n };\n\n const focusCell = (cell) => { if (cell) { cell.focus(); cell.scrollIntoView({ block: 'nearest' }); } };\n const columnsOf = (grid) => {\n const cells = [...grid.querySelectorAll('.chat-emoji-cell')];\n if (!cells.length) return 1;\n const top = cells[0].offsetTop;\n return Math.max(1, cells.filter((cell) => cell.offsetTop === top).length);\n };\n\n const onBodyKeyDown = (event) => {\n const cell = event.target.closest?.('.chat-emoji-cell');\n if (!cell) return;\n const body = bodyRef.current;\n const grids = [...body.querySelectorAll('.chat-emoji-grid')].filter((grid) => grid.querySelector('.chat-emoji-cell'));\n const all = [...body.querySelectorAll('.chat-emoji-cell')];\n const grid = cell.closest('.chat-emoji-grid');\n const gridIndex = grids.indexOf(grid);\n const cells = [...grid.querySelectorAll('.chat-emoji-cell')];\n const index = cells.indexOf(cell);\n const cols = columnsOf(grid);\n let target = null;\n switch (event.key) {\n case 'ArrowRight': target = all[all.indexOf(cell) + 1]; break;\n case 'ArrowLeft': target = all[all.indexOf(cell) - 1]; break;\n case 'ArrowDown': {\n if (index + cols < cells.length) target = cells[index + cols];\n else if (Math.floor(index / cols) < Math.floor((cells.length - 1) / cols)) target = cells[cells.length - 1];\n else if (grids[gridIndex + 1]) {\n const next = [...grids[gridIndex + 1].querySelectorAll('.chat-emoji-cell')];\n target = next[Math.min(index % cols, next.length - 1)];\n }\n break;\n }\n case 'ArrowUp': {\n if (index - cols >= 0) target = cells[index - cols];\n else if (grids[gridIndex - 1]) {\n const prev = [...grids[gridIndex - 1].querySelectorAll('.chat-emoji-cell')];\n const prevCols = columnsOf(grids[gridIndex - 1]);\n const lastRowStart = Math.floor((prev.length - 1) / prevCols) * prevCols;\n target = prev[Math.min(lastRowStart + (index % cols), prev.length - 1)];\n } else { event.preventDefault(); searchRef.current?.focus(); return; }\n break;\n }\n case 'PageDown': target = grids[gridIndex + 1]?.querySelector('.chat-emoji-cell'); break;\n case 'PageUp': target = (index > 0 ? grid : grids[gridIndex - 1])?.querySelector('.chat-emoji-cell'); break;\n case 'Home': target = all[0]; break;\n case 'End': target = all[all.length - 1]; break;\n case 'Enter': case ' ': event.preventDefault(); if (!cell.disabled) cell.click(); return;\n default: return;\n }\n event.preventDefault();\n focusCell(target);\n };\n\n if (!isOpen) return null;\n const currentTone = SKIN_TONES.find((item) => item.tone === skinTone) || SKIN_TONES[0];\n const navTabs = [\n ...(recents?.length ? [['recent', 'Recientes']] : []),\n ...(favorites?.length ? [['favorites', 'Favoritos']] : []),\n ...emojiCategories.filter(([id]) => id !== 'all' && (getEmojisByCategory(id) || []).length),\n ...(customRecords.length ? [['custom', 'Personalizados']] : []),\n ];\n const previewFav = shown ? favoriteSet.has(shown.record.emoji) : false;\n const previewCode = shown?.record.shortcode ? `:${shown.record.shortcode}:` : '';\n\n return <div className=\"chat-emoji-picker chat-emoji-picker--modern\" role=\"dialog\" aria-label=\"Seleccionar emoji\" onKeyDown={(event) => {\n if (event.key !== 'Escape') return;\n event.preventDefault(); event.stopPropagation();\n if (toneOpen) setToneOpen(false); else onClose();\n }}>\n <div className=\"chat-emoji-top\">\n <input ref={searchRef} className=\"chat-emoji-search\" type=\"search\" autoFocus\n aria-label=\"Buscar emoji en español o inglés\" placeholder=\"Buscar emoji (español o inglés)…\"\n value={query} onChange={(event) => { setQuery(event.target.value); setPreview(null); bodyRef.current?.scrollTo({ top: 0 }); }}\n onKeyDown={(event) => {\n if (event.key !== 'ArrowDown') return;\n event.preventDefault();\n focusCell(bodyRef.current?.querySelector('.chat-emoji-cell'));\n }} />\n <div className=\"chat-emoji-tone\">\n <button type=\"button\" className=\"chat-emoji-tone-btn\" aria-haspopup=\"menu\" aria-expanded={toneOpen}\n aria-label={`Tono de piel: ${currentTone?.label || ''}`} title=\"Tono de piel\" onClick={() => setToneOpen((open) => !open)}>\n <span className=\"chat-emoji-tone-swatch\" style={{ background: currentTone?.swatch }} aria-hidden=\"true\" />\n </button>\n {toneOpen && <div className=\"chat-emoji-tone-menu\" role=\"menu\" aria-label=\"Tono de piel\">\n {SKIN_TONES.map((item) => <button key={String(item.tone)} type=\"button\" role=\"menuitemradio\"\n className=\"chat-emoji-tone-option\" aria-checked={item.tone === skinTone} aria-label={item.label} title={item.label}\n onClick={() => { setSkinTone(item.tone); setToneOpen(false); }}>\n <span className=\"chat-emoji-tone-swatch\" style={{ background: item.swatch }} aria-hidden=\"true\" />\n </button>)}\n </div>}\n </div>\n <button type=\"button\" className=\"chat-btn\" aria-label=\"Cerrar emojis\" onClick={onClose}><X size={16} /></button>\n </div>\n {!trimmed && <div className=\"chat-emoji-nav\" role=\"tablist\" aria-label=\"Categorías de emojis\">\n {navTabs.map(([id, label]) => { const Icon = categoryIcons[id] || Smile; return <button key={id} type=\"button\" role=\"tab\"\n className=\"chat-emoji-nav-btn\" title={label} aria-label={label} aria-selected={activeSection === id}\n onClick={() => scrollToSection(id)}><Icon size={16} aria-hidden=\"true\" /></button>; })}\n </div>}\n <div ref={bodyRef} className=\"chat-emoji-body\" onKeyDown={onBodyKeyDown} onScroll={() => {\n cancelAnimationFrame(scrollFrame.current);\n scrollFrame.current = requestAnimationFrame(updateActive);\n }}>\n {sections.map((section) => (section.id === 'results' && !section.items.length\n ? <p key=\"empty\" className=\"chat-emoji-empty\" role=\"status\">No se encontraron emojis</p>\n : <EmojiSection key={`${section.id}-${trimmed ? 'q' : 'b'}`} {...section} rootRef={bodyRef}\n favoriteSet={favoriteSet} disabled={disabled} onPick={onPick} onToggleFavorite={onToggleFavorite} onPreview={onPreview} />))}\n </div>\n <div className=\"chat-emoji-preview\" aria-live=\"polite\">\n {shown && <>\n <span className=\"chat-emoji-preview-emoji\" aria-hidden=\"true\"><MessageText text={shown.value} /></span>\n <span className=\"chat-emoji-preview-info\">\n <span className=\"chat-emoji-preview-name\">{shown.record.label}</span>\n {previewCode && <span className=\"chat-emoji-preview-code\">{previewCode}</span>}\n </span>\n <button type=\"button\" className=\"chat-emoji-fav-btn\" aria-pressed={previewFav}\n aria-label={previewFav ? 'Quitar de favoritos' : 'Agregar a favoritos'} title={previewFav ? 'Quitar de favoritos' : 'Agregar a favoritos'}\n onClick={() => toggleFavorite(shown.record.emoji)}>\n <Star size={16} aria-hidden=\"true\" fill={previewFav ? 'currentColor' : 'none'} />\n </button>\n </>}\n </div>\n </div>;\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport { Plus } from 'lucide-react';\nimport EmojiPicker from './EmojiPicker';\nimport MessageText from './MessageText';\n\nconst QUICK_REACTIONS = [\n ['👍', 'Me gusta'],\n ['❤️', 'Me encanta'],\n ['😂', 'Me divierte'],\n ['😮', 'Me asombra'],\n ['😢', 'Me entristece'],\n ['🙏', 'Gracias'],\n];\n\nexport default function ReactionPicker({ onSelect, onClose, align = 'start' }) {\n const [full, setFull] = useState(false);\n const rootRef = useRef(null);\n const quickRef = useRef(null);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n\n useEffect(() => {\n quickRef.current?.querySelector('.chat-reaction-picker__option')?.focus();\n }, []);\n\n useEffect(() => {\n const handlePointerDown = (event) => {\n if (rootRef.current && rootRef.current.contains(event.target)) return;\n onCloseRef.current?.();\n };\n document.addEventListener('pointerdown', handlePointerDown);\n return () => document.removeEventListener('pointerdown', handlePointerDown);\n }, []);\n\n const choose = (emoji) => { if (emoji) onSelect(emoji); };\n\n return <div ref={rootRef} className={`chat-reaction-picker chat-reaction-picker--${align}${full ? ' chat-reaction-picker--full' : ''}`} role=\"dialog\" aria-label=\"Reaccionar\" onKeyDown={(event) => {\n if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); onClose(); }\n }}>\n {full\n ? <EmojiPicker isOpen onSelect={choose} onClose={onClose} />\n : <div ref={quickRef} className=\"chat-reaction-picker__quick\" role=\"group\" aria-label=\"Reacciones rápidas\" onKeyDown={(event) => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return;\n const buttons = [...event.currentTarget.querySelectorAll('button')];\n const current = buttons.indexOf(document.activeElement);\n if (current < 0 || !buttons.length) return;\n event.preventDefault(); event.stopPropagation();\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? buttons.length - 1\n : (current + (event.key === 'ArrowRight' ? 1 : -1) + buttons.length) % buttons.length;\n buttons[next].focus();\n }}>\n {QUICK_REACTIONS.map(([emoji, label]) => <button key={emoji} type=\"button\" className=\"chat-reaction-picker__option\" title={label} aria-label={label}\n onMouseDown={(event) => event.preventDefault()} onClick={() => choose(emoji)}><MessageText text={emoji} /></button>)}\n <button type=\"button\" className=\"chat-reaction-picker__more\" title=\"Más emojis\" aria-label=\"Más emojis\" onClick={() => setFull(true)}><Plus size={16} aria-hidden=\"true\" /></button>\n </div>}\n </div>;\n}\n","import { createContext, useContext } from 'react';\n\n// ownIds: ids (string|number) that identify the current user.\n// resolveName(userId): display name for a user id, or null if unknown.\nexport const ChatPeopleContext = createContext({ ownIds: [], resolveName: () => null });\n\nexport const useChatPeople = () => useContext(ChatPeopleContext);\n","/* eslint-disable react/prop-types */\nimport { memo, useEffect, useRef, useState } from 'react';\nimport MessageText from './MessageText';\nimport { useChatPeople } from '../chatPeopleContext';\n\nconst MAX_NAMES = 10;\nconst BUMP_MS = 300;\n\nconst prefersReducedMotion = () => typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n\nfunction ReactionBar({ reactions = [], onToggle, disabled }) {\n const { ownIds: ownIdList, resolveName } = useChatPeople();\n const [bumped, setBumped] = useState(() => new Set());\n const prevCounts = useRef(null);\n const timers = useRef({});\n\n useEffect(() => {\n const next = {};\n const grown = [];\n for (const { emoji, count } of reactions) {\n next[emoji] = count;\n if (prevCounts.current && count > (prevCounts.current[emoji] ?? 0)) grown.push(emoji);\n }\n prevCounts.current = next;\n if (!grown.length || prefersReducedMotion()) return;\n setBumped((prev) => new Set([...prev, ...grown]));\n for (const emoji of grown) {\n clearTimeout(timers.current[emoji]);\n timers.current[emoji] = setTimeout(() => {\n delete timers.current[emoji];\n setBumped((prev) => {\n if (!prev.has(emoji)) return prev;\n const copy = new Set(prev);\n copy.delete(emoji);\n return copy;\n });\n }, BUMP_MS);\n }\n }, [reactions]);\n\n useEffect(() => () => Object.values(timers.current).forEach(clearTimeout), []);\n\n if (!reactions.length) return null;\n\n const ownIds = new Set((ownIdList || []).map(String));\n const nameOf = (id) => {\n const key = String(id);\n if (ownIds.has(key)) return 'Tú';\n return resolveName?.(key) || 'Usuario';\n };\n const titleFor = (userIds = []) => {\n const names = userIds.slice(0, MAX_NAMES).map(nameOf);\n const rest = userIds.length - names.length;\n return rest > 0 ? `${names.join(', ')} y ${rest} más` : names.join(', ');\n };\n\n return <div className=\"chat-reaction-bar\" role=\"group\" aria-label=\"Reacciones\">\n {reactions.map(({ emoji, count, mine, userIds }) => <button\n key={emoji}\n type=\"button\"\n className={`chat-reaction-chip${mine ? ' chat-reaction-chip--mine' : ''}${bumped.has(emoji) ? ' chat-reaction-chip--bump' : ''}`}\n aria-pressed={!!mine}\n aria-label={`${emoji} ${count} ${count === 1 ? 'reacción' : 'reacciones'}${mine ? ', incluida la tuya. Pulsa para quitarla' : '. Pulsa para reaccionar'}`}\n title={titleFor(userIds) || undefined}\n disabled={disabled}\n onClick={() => onToggle?.(emoji)}\n ><span className=\"chat-reaction-chip__emoji\"><MessageText text={emoji} /></span><span className=\"chat-reaction-chip__count\">{count}</span></button>)}\n </div>;\n}\n\nexport default memo(ReactionBar);\n","/* eslint-disable react/prop-types */\nimport { useRef, useState } from 'react';\nimport { Copy, Check, Reply, SmilePlus, Pencil } from 'lucide-react';\nimport { decodeEffect, effectMessageText } from '../../effects/protocol.js';\nimport { EffectCard } from '../../effects/ChatEffects.jsx';\nimport MessageText from './MessageText';\nimport MediaPreview from './MediaPreview';\nimport YouTubePreview from './YouTubePreview.jsx';\nimport ReactionPicker from './ReactionPicker';\nimport ReactionBar from './ReactionBar';\nimport { isStickerAttachment } from '../../core/extras/messageExtras';\nexport default function MessageBubble({ message, isMine, senderName, timestamp, onCopy, onReply, onJumpQuote, onReact, onEdit, isEditing }) {\n const [quoteUnavailable, setQuoteUnavailable] = useState(false);\n const [copyState, setCopyState] = useState('');\n const [pickerOpen, setPickerOpen] = useState(false);\n const reactBtnRef = useRef(null);\n const text = message.message ?? message.text ?? '';\n const quote = /^> ([^\\n]{1,240})\\n\\n/.exec(text);\n const body = quote ? text.slice(quote[0].length) : text;\n const effect = decodeEffect(body);\n const attachments = Array.isArray(message.attachments) ? message.attachments : message.attachment ? [message.attachment] : [];\n const date = timestamp == null ? null : new Date(timestamp);\n const validDate = date && Number.isFinite(date.getTime());\n const isSticker = !text.trim() && attachments.length > 0 && attachments.every(isStickerAttachment);\n const hasReactions = Boolean(message.reactionGroups?.length);\n const closePicker = () => { setPickerOpen(false); reactBtnRef.current?.focus(); };\n const bubbleClass = ['message-bubble', isMine ? 'message-bubble--mine' : 'message-bubble--other', attachments.length && 'message-bubble--media', !text && attachments.length && 'message-bubble--media-only', isEditing && 'message-bubble--editing', isSticker && 'message-bubble--sticker', hasReactions && 'message-bubble--has-reactions', pickerOpen && 'message-bubble--picker-open'].filter(Boolean).join(' ');\n return <div className={`message-row ${isMine ? 'message-row--mine' : ''}`}>\n {!isMine && senderName && <span className=\"message-avatar\" aria-hidden=\"true\">{senderName.charAt(0).toUpperCase()}</span>}\n <div className={bubbleClass}>\n {!isMine && senderName && <div className=\"message-sender\">{senderName}</div>}\n {quote && <blockquote className=\"chat-message-quote\" aria-label=\"Cita de texto\"><button type=\"button\" className=\"chat-quote-link\" title=\"Buscar cita de texto en los mensajes disponibles\" onClick={() => setQuoteUnavailable(!onJumpQuote?.(quote[1]))}><MessageText text={quote[1]} /></button>{quoteUnavailable && <small role=\"status\">Original no disponible o cita ambigua</small>}</blockquote>}\n {effect ? <EffectCard effect={effect} /> : body && <div className=\"message-content\"><MessageText text={body} /></div>}\n {!effect && <YouTubePreview text={body} />}\n <MediaPreview items={attachments} history />\n <ReactionBar reactions={message.reactionGroups} onToggle={(emoji) => onReact?.(message, emoji)} disabled={!onReact} />\n {message.localOnly && <small className=\"message-meta\">Solo en este dispositivo · pendiente de envío</small>}\n <div className=\"message-actions\">\n {onReact && <button ref={reactBtnRef} type=\"button\" className=\"message-action-btn\" aria-label=\"Reaccionar al mensaje\" title=\"Reaccionar\" aria-haspopup=\"dialog\" aria-expanded={pickerOpen} onClick={() => setPickerOpen((v) => !v)}><SmilePlus size={14} /></button>}\n {onEdit && !effect && <button type=\"button\" className=\"message-action-btn\" aria-label=\"Editar mensaje\" title=\"Editar (↑)\" onClick={() => onEdit()}><Pencil size={13} /></button>}\n {onReply && <button type=\"button\" className=\"message-action-btn\" aria-label=\"Responder al mensaje\" title=\"Responder\" onClick={() => onReply(message)}><Reply size={14} /></button>}\n {text && <button type=\"button\" className=\"message-action-btn\" aria-label={copyState === 'ok' ? 'Mensaje copiado' : 'Copiar mensaje'} title={copyState === 'ok' ? 'Copiado' : 'Copiar mensaje'} onClick={async () => {\n try {\n if (onCopy) await onCopy(effectMessageText(text));\n else await navigator.clipboard.writeText(effectMessageText(text));\n setCopyState('ok');\n } catch { setCopyState('error'); }\n }}>{copyState === 'ok' ? <Check size={13} /> : <Copy size={13} />}</button>}\n </div>\n {pickerOpen && onReact && <div className=\"message-reaction-popover\"><ReactionPicker align={isMine ? 'end' : 'start'} onClose={closePicker} onSelect={(emoji) => { onReact(message, emoji); closePicker(); }} /></div>}\n <div className=\"message-footer\">\n {validDate && <time className=\"message-meta\" dateTime={date.toISOString()} title={`${date.toLocaleString()}${isMine && !message.localOnly ? ' · Aceptado por el servidor' : ''}`}>{date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</time>}\n {message.edited && <span className=\"message-edited\" title={message.editedAt ? `Editado ${new Date(message.editedAt).toLocaleString()}` : 'Editado'}>editado</span>}\n {copyState && <span className=\"message-copy-status\" role=\"status\">{copyState === 'ok' ? 'Copiado' : 'No se pudo copiar'}</span>}\n </div>\n </div>\n </div>;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n// UI-only state of the persistent game panel, keyed by game key.\nexport function createGamePanelStore() {\n return createStore((set) => ({\n panels: {},\n setMinimized: (key, minimized) => set((state) => ({ panels: { ...state.panels, [key]: { ...state.panels[key], minimized: Boolean(minimized) } } })),\n dismiss: (key) => set((state) => ({ panels: { ...state.panels, [key]: { ...state.panels[key], minimized: false, dismissed: true } } })),\n reset: () => set({ panels: {} }),\n }));\n}\n\n// Backward-compatible singleton: hook plus getState/setState/subscribe.\nexport const gamePanelStore = createGamePanelStore();\nexport const useGamePanelStore = (selector) => useStore(gamePanelStore, selector);\nObject.assign(useGamePanelStore, {\n getState: gamePanelStore.getState,\n setState: gamePanelStore.setState,\n subscribe: gamePanelStore.subscribe,\n});\n\nexport default useGamePanelStore;\n","/* eslint-disable react/prop-types */\nimport { memo } from 'react';\nimport { ArrowDown, ChevronDown, X } from 'lucide-react';\nimport { getGameStatus, isTerminalGame, sameUser } from '../shared/gameStatus';\nimport './games.css';\n\nfunction SyncControls({ sync, connected, onResync, onAdoptOffer }) {\n if (sync?.status === 'requesting') return <div className=\"chat-game-sync\" role=\"status\">Sincronizando partida…</div>;\n return <div className=\"chat-game-sync\" role=\"alert\">\n {sync?.message && <span>{sync.message}</span>}\n {sync?.status === 'incompatible' && sync.offer && onAdoptOffer && <button type=\"button\" className=\"chat-game-action chat-game-action--primary\" disabled={!connected} onClick={onAdoptOffer}>Usar estado del anfitrión</button>}\n {onResync && <button type=\"button\" className=\"chat-game-action\" disabled={!connected} onClick={onResync}>Reintentar sincronización</button>}\n </div>;\n}\n\nfunction GameCard({ game, currentUserId, onAccept, onDecline, onMove, onClose, onRetry, onDropSettled, onMinimize, onDismiss, onResync, onAdoptOffer, soundControls, variant, connected = true }) {\n const isHost = sameUser(currentUserId, game.hostId);\n const isGuest = sameUser(currentUserId, game.guestId);\n const isParticipant = isHost || isGuest;\n const myTurn = game.status === 'active' && sameUser(currentUserId, game.turnId);\n const controlsDisabled = !connected || game.pending || Boolean(game.pendingEvent);\n const canMove = myTurn && !controlsDisabled && !game.error;\n const terminal = isTerminalGame(game);\n const board = game.board || Array.from({ length: 6 }, () => Array(7).fill(null));\n const status = getGameStatus(game, currentUserId);\n\n return (\n <section className={`chat-game-card${myTurn ? ' chat-game-card--my-turn' : ''}${variant ? ` chat-game-card--${variant}` : ''}`} aria-label=\"Partida de Conecta 4\">\n <header className=\"chat-game-header\">\n <div className=\"chat-game-heading\">\n <span className=\"chat-game-eyebrow\">MINIJUEGOS · 2 JUGADORES</span>\n <h3>Conecta 4 <span aria-hidden=\"true\">●●●●</span></h3>\n </div>\n {soundControls}\n {onMinimize && <button className=\"chat-game-close\" type=\"button\" aria-label=\"Minimizar tablero\" title=\"Minimizar tablero\" onClick={onMinimize}><ChevronDown size={16} aria-hidden=\"true\" /></button>}\n {isParticipant && !terminal && (\n <button className=\"chat-game-close\" type=\"button\" aria-label=\"Finalizar partida para ambos jugadores\" title=\"Finalizar partida para ambos\" onClick={onClose} disabled={!connected}><X size={16} aria-hidden=\"true\" /></button>\n )}\n {onDismiss && <button className=\"chat-game-close\" type=\"button\" aria-label=\"Cerrar tablero y volver al chat\" title=\"Cerrar tablero\" onClick={onDismiss}><X size={16} aria-hidden=\"true\" /></button>}\n </header>\n <p className=\"chat-game-status\" role=\"status\">{!connected && !terminal ? 'Sin conexión · esperando reconexión' : game.pending ? 'Sincronizando…' : status}</p>\n <div className=\"chat-game-players\" aria-label=\"Colores de los jugadores\">\n <span><i className=\"chat-game-dot chat-game-dot--host\" />{isHost ? 'Tú' : 'Rival'}<small>Azul</small></span>\n <span><i className=\"chat-game-dot chat-game-dot--guest\" />{isGuest ? 'Tú' : 'Rival'}<small>Violeta</small></span>\n </div>\n <div className=\"chat-game-board-wrap\">\n <div className=\"chat-game-columns\" aria-label=\"Selecciona una columna\">\n {Array.from({ length: 7 }, (_, column) => (\n <button type=\"button\" key={column} aria-label={`Lanzar ficha en columna ${column + 1}`} disabled={!canMove || board[0][column] != null} onClick={() => onMove?.(column)}><ArrowDown size={16} strokeWidth={2} aria-hidden=\"true\" /><span className=\"chat-game-column-number\">{column + 1}</span></button>\n ))}\n </div>\n <div className=\"chat-game-board\" role=\"img\" aria-label={`Tablero de Conecta 4, ${game.ply || 0} fichas colocadas. ${status}. ${board.map((row, index) => `Fila ${index + 1} de arriba abajo: ${row.map(cell => cell == null ? 'vacía' : sameUser(cell, game.hostId) ? 'azul' : 'violeta').join(', ')}`).join('. ')}`}>\n {board.flatMap((row, rowIndex) => row.map((cell, column) => {\n const occupied = cell != null;\n const owner = occupied ? (sameUser(cell, game.hostId) ? 'host' : 'guest') : '';\n const latest = game.lastMove?.row === rowIndex && game.lastMove?.column === column;\n const winning = game.winningCells?.some(([row, col]) => row === rowIndex && col === column);\n return <div className={`chat-game-cell${winning ? ' chat-game-cell--winning' : ''}`} key={`${rowIndex}-${column}`}>\n {occupied && <span key={latest ? game.lastMove.eventId : 'settled'} className={`chat-game-piece chat-game-piece--${owner}${latest ? ' chat-game-piece--new' : ''}`} style={latest ? { '--game-drop-distance': `${-(rowIndex + 1) * 105}%` } : undefined}\n onAnimationEnd={latest ? () => onDropSettled?.(game.lastMove.eventId) : undefined} />}\n </div>;\n }))}\n </div>\n </div>\n {game.status === 'invited' && isGuest && <div className=\"chat-game-actions\">\n <button type=\"button\" className=\"chat-game-action chat-game-action--primary\" disabled={controlsDisabled} onClick={onAccept}>Aceptar partida</button>\n <button type=\"button\" className=\"chat-game-action\" disabled={controlsDisabled} onClick={onDecline}>Rechazar</button>\n </div>}\n {game.status === 'conflict' && isParticipant && <SyncControls sync={game.sync} connected={connected} onResync={onResync} onAdoptOffer={onAdoptOffer} />}\n {game.error && <div className=\"chat-game-error\" role=\"alert\"><span>{game.error}</span>{onRetry && <button type=\"button\" className=\"chat-game-action\" disabled={!connected || game.pending} onClick={onRetry}>Reintentar</button>}</div>}\n <footer className=\"chat-game-footer\">{terminal ? 'Puedes seguir conversando o invitar a otra partida.' : 'Conecta cuatro fichas. El chat sigue disponible.'}</footer>\n </section>\n );\n}\n\nexport default memo(GameCard);\n","/* eslint-disable react/prop-types */\nimport { Component, lazy, memo, Suspense, useEffect } from 'react';\nimport { useChatConnectionStatus } from '../../core/connection/connectionStore';\nimport useChatGames from './useChatGames';\nimport GameCard from '../connect4/GameCard';\nimport GameSoundControls from './GameSoundControls';\nimport { connect4Sounds, settleConnect4Drop } from '../connect4/connect4Sounds';\nimport { isBattleshipGame, isTanksGame } from './gameStatus';\n\n// Lazy game cards (and three.js behind them) stay out of the main bundle.\n// React caches a rejected lazy(); a retry needs a fresh one to actually reload the chunk.\nconst LAZY_CARDS = {\n racing_live: { title: 'Carreras LIVE 🏎️', load: () => lazy(() => import('../racing-live/RacingLiveGameCard.jsx')) },\n battleship: { title: 'Batalla Naval', load: () => lazy(() => import('../battleship/BattleshipGameCard')) },\n tanks_live: { title: 'Tanques LIVE 3D', load: () => lazy(() => import('../tanks-live/TanksLiveGameCard.jsx')) },\n tanks: { title: 'Tanques de guerra', load: () => lazy(() => import('../tanks/TanksGameCard.jsx')) },\n};\nconst lazyCards = {};\nconst lazyCard = (type) => { lazyCards[type] ??= LAZY_CARDS[type].load(); return lazyCards[type]; };\n\nfunction LazyCardFallback({ title }) {\n return <section className=\"chat-game-card\" aria-busy=\"true\" aria-label={`Partida de ${title}`}>\n <p className=\"chat-game-status\" role=\"status\">Cargando {title}…</p>\n </section>;\n}\n\n// Keeps a failed game chunk load from reaching the global ErrorBoundary.\nclass LazyCardErrorBoundary extends Component {\n state = { failed: false };\n\n static getDerivedStateFromError() { return { failed: true }; }\n\n render() {\n if (!this.state.failed) return this.props.children;\n const { type } = this.props;\n return <section className=\"chat-game-card\" aria-label={`Partida de ${LAZY_CARDS[type].title}`}>\n <p className=\"chat-game-status\" role=\"alert\">No se pudo cargar {LAZY_CARDS[type].title}.</p>\n <button type=\"button\" className=\"chat-btn\" onClick={() => { lazyCards[type] = LAZY_CARDS[type].load(); this.setState({ failed: false }); }}>Reintentar</button>\n </section>;\n }\n}\n\nfunction ConnectedGameCard({ gameKey, currentUserId, variant = 'panel', onMinimize, onDismiss, suspended = false }) {\n const game = useChatGames((state) => state.games[gameKey]);\n const connected = useChatConnectionStatus() === 'connected';\n const type = game?.game === 'racing_live' ? 'racing_live' : game?.game === 'tanks_live' ? 'tanks_live' : isBattleshipGame(game) ? 'battleship' : isTanksGame(game) ? 'tanks' : game ? 'connect4' : null;\n useEffect(() => { if (type === 'connect4') connect4Sounds.preload(); }, [type]);\n if (!game) return null;\n if (type !== 'connect4') {\n const Card = lazyCard(type);\n return <LazyCardErrorBoundary key={type} type={type}>\n <Suspense fallback={<LazyCardFallback title={LAZY_CARDS[type].title} />}>\n <Card suspended={suspended} gameKey={gameKey} currentUserId={currentUserId} variant={variant} onMinimize={onMinimize} onDismiss={onDismiss} />\n </Suspense>\n </LazyCardErrorBoundary>;\n }\n // The store owns delivery errors; handlers must not leak rejected promises.\n const act = (type, data) => { void useChatGames.getState().act(gameKey, type, data).catch(() => {}); };\n const run = (name) => () => { void Promise.resolve(useChatGames.getState()[name]?.(gameKey)).catch(() => {}); };\n return <GameCard game={game} currentUserId={currentUserId} connected={connected}\n onAccept={() => act('game_accept')} onDecline={() => act('game_decline')}\n onMove={(column) => act('game_move', { column })} onClose={() => act('game_end')}\n onDropSettled={settleConnect4Drop} variant={variant} onMinimize={onMinimize} onDismiss={onDismiss}\n soundControls={variant === 'panel' ? <GameSoundControls manager={connect4Sounds} /> : undefined}\n onResync={run('requestResync')} onAdoptOffer={run('adoptResyncOffer')}\n onRetry={game.pendingEvent ? () => { void useChatGames.getState().retry(gameKey).catch(() => {}); } : undefined} />;\n}\n\nexport default memo(ConnectedGameCard);\n","/* eslint-disable react/prop-types */\nimport { Gamepad2 } from 'lucide-react';\nimport useChatGames from './useChatGames';\nimport useGamePanelStore from './useGamePanelStore';\nimport ConnectedGameCard from './ConnectedGameCard';\nimport { getGameTitle, getShortGameStatus } from './gameStatus';\n\n// The panel owns the interactive board; the timeline only links to it.\nexport default function GameTimelineEntry({ gameKey, currentUserId, inPanel }) {\n const game = useChatGames((state) => state.games[gameKey]);\n if (!game) return null;\n if (!inPanel) return <ConnectedGameCard gameKey={gameKey} currentUserId={currentUserId} variant=\"history\" />;\n return (\n <button type=\"button\" className=\"chat-game-placeholder\" onClick={() => useGamePanelStore.getState().setMinimized(gameKey, false)}>\n <Gamepad2 size={15} aria-hidden=\"true\" />\n <span>Partida de {getGameTitle(game)} · {getShortGameStatus(game, currentUserId)}</span>\n <strong>Ver tablero</strong>\n </button>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport dayjs from 'dayjs';\nimport { effectMessageText } from '../../effects/protocol.js';\nimport MessageBubble from './MessageBubble';\nimport GameTimelineEntry from '../../games/shared/GameTimelineEntry';\nimport { messageId } from '../../core/extras/messageExtras';\nimport { MessageCircle, Paperclip, Mic, Sparkles, ArrowDown } from 'lucide-react';\n\nconst validTime = (value) => value != null && value !== '' && dayjs(value).isValid();\nexport default function MessageList({ messages = [], currentUserId, onCopy, onReply, panelGameKey, onReact, onEditMessage, editingId }) {\n const scrollRef = useRef(null);\n const nearBottom = useRef(true);\n const [hasNew, setHasNew] = useState(false);\n const scrollToBottom = () => { const node = scrollRef.current; if (node) node.scrollTop = node.scrollHeight; nearBottom.current = true; setHasNew(false); };\n const prevLength = useRef(messages.length);\n useEffect(() => {\n const node = scrollRef.current;\n // Only growth counts as \"new\"; reactions/edits on old messages must not flag it.\n const grew = messages.length > prevLength.current; prevLength.current = messages.length;\n if (node && nearBottom.current) node.scrollTop = node.scrollHeight;\n else if (node && grew) setHasNew(true);\n }, [messages]);\n useEffect(() => {\n if (editingId == null) return;\n const id = String(editingId);\n const node = scrollRef.current?.querySelector(`[data-chat-message-id=\"${typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(id) : id.replace(/[\"\\\\]/g, '\\\\$&')}\"]`);\n node?.scrollIntoView({ block: 'nearest', behavior: 'auto' });\n }, [editingId]);\n // Keep the latest messages in view when the game panel opens or grows.\n useEffect(() => {\n const node = scrollRef.current;\n if (!node || typeof ResizeObserver === 'undefined') return undefined;\n const observer = new ResizeObserver(() => { if (nearBottom.current) node.scrollTop = node.scrollHeight; });\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n const keys = new Map();\n return <div className=\"chat-messages-area\">\n <div className=\"chat-messages\" ref={scrollRef} role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\" aria-label=\"Mensajes\" onLoadCapture={() => { const node = scrollRef.current; if (node && nearBottom.current) node.scrollTop = node.scrollHeight; }} onScroll={() => { const node = scrollRef.current; nearBottom.current = node.scrollHeight - node.scrollTop - node.clientHeight < 80; if (nearBottom.current) setHasNew(false); }}>\n {!messages.length && <div className=\"chat-conversation-welcome\"><div className=\"chat-welcome-icon\"><MessageCircle size={30} /></div><span className=\"chat-eyebrow\">ESTE ES TU ESPACIO</span><h3>Una buena conversación empieza aquí</h3><p>Comparte una idea, suelta un archivo o dale voz a tu mensaje.</p><div className=\"chat-welcome-features\"><span><Paperclip size={14} /> Archivos y media</span><span><Mic size={14} /> Notas de voz</span><span><Sparkles size={14} /> GIFs y emojis</span></div></div>}\n {messages.map((msg, index) => {\n const previous = messages[index - 1];\n const timed = validTime(msg.timestamp);\n const previousTimed = previous && validTime(previous.timestamp);\n const sameDay = timed && previousTimed && dayjs(msg.timestamp).isSame(dayjs(previous.timestamp), 'day');\n const gap = sameDay ? dayjs(msg.timestamp).diff(dayjs(previous.timestamp), 'minute', true) : Infinity;\n const grouped = previous && previous.user_id != null && msg.user_id != null && String(previous.user_id) === String(msg.user_id) && !previous.gameKey && !msg.gameKey && sameDay && gap >= 0 && gap <= 5;\n const base = String(msg.id ?? msg.message_id ?? `${msg.room_id}:${msg.user_id}:${msg.timestamp ?? ''}:${msg.message ?? ''}`);\n const occurrence = keys.get(base) || 0;\n keys.set(base, occurrence + 1);\n const id = messageId(msg);\n const isMine = Boolean(msg.localOnly) || (msg.user_id != null && currentUserId != null && String(msg.user_id) === String(currentUserId));\n const body = msg.message ?? msg.text;\n return <div key={`${base}:${occurrence}`} data-chat-message-index={index} data-chat-message-id={id ?? undefined} tabIndex={-1} className={`message-group ${grouped ? 'message-group--continued' : ''}`}>\n {timed && !sameDay && <div className=\"message-date-divider\"><span>{dayjs(msg.timestamp).format('DD MMM YYYY')}</span></div>}\n {msg.gameKey ? <GameTimelineEntry gameKey={msg.gameKey} currentUserId={currentUserId} inPanel={String(msg.gameKey) === String(panelGameKey)} /> : <MessageBubble message={msg} isMine={isMine} onReact={msg.localOnly || !id ? undefined : onReact} onEdit={isMine && !msg.localOnly && id && typeof body === 'string' && body.trim() && onEditMessage ? () => onEditMessage(msg) : undefined} isEditing={editingId != null && id === String(editingId)} senderName={!grouped ? msg.username : undefined} timestamp={timed ? msg.timestamp : undefined} onCopy={onCopy} onReply={onReply} onJumpQuote={(quote) => {\n const matches = messages.map((item, i) => ({ item, i })).filter(({ item }) => `${String(item.username || 'Usuario').replace(/[\\r\\n]/g, ' ').slice(0, 50)}: ${String(effectMessageText(item.message || item.text || '[Archivo adjunto]')).replace(/\\s+/g, ' ').slice(0, 180)}` === quote);\n if (matches.length !== 1) return false;\n const node = scrollRef.current?.querySelector(`[data-chat-message-index=\"${matches[0].i}\"]`);\n node?.scrollIntoView({ block: 'center', behavior: 'auto' }); node?.focus({ preventScroll: true });\n return Boolean(node);\n }} />}\n </div>;\n })}\n </div>\n {hasNew && <button type=\"button\" className=\"chat-new-messages\" onClick={scrollToBottom}>Ver mensajes nuevos <ArrowDown size={14} aria-hidden=\"true\" style={{ verticalAlign: 'middle' }} /></button>}\n </div>;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nconst LIMIT_SECONDS = 120;\n\nexport default function useVoiceRecorder(onRecorded) {\n const [status, setStatus] = useState('idle');\n const [seconds, setSeconds] = useState(0);\n const [error, setError] = useState('');\n const sessionRef = useRef(null);\n const mountedRef = useRef(true);\n const callbackRef = useRef(onRecorded);\n callbackRef.current = onRecorded;\n\n const release = useCallback((session) => {\n clearInterval(session?.timer);\n session?.stream?.getTracks().forEach((track) => track.stop());\n }, []);\n\n const finish = useCallback((cancelled = false) => {\n const session = sessionRef.current;\n if (!session) return;\n session.cancelled = cancelled;\n clearInterval(session.timer);\n if (session.recorder?.state === 'recording') {\n session.recorder.stop();\n release(session);\n } else {\n release(session);\n sessionRef.current = null;\n if (mountedRef.current) setStatus('idle');\n }\n }, [release]);\n\n const start = useCallback(async () => {\n if (sessionRef.current) return;\n setError('');\n if (!navigator.mediaDevices?.getUserMedia || typeof MediaRecorder === 'undefined') {\n setError('Este navegador no permite grabar audio. Puedes adjuntar un archivo de audio.');\n return;\n }\n const session = { cancelled: false, chunks: [], stream: null, recorder: null, timer: null };\n sessionRef.current = session;\n setStatus('requesting');\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n session.stream = stream;\n if (!mountedRef.current || session.cancelled || sessionRef.current !== session) {\n release(session);\n return;\n }\n const mimeType = ['audio/webm;codecs=opus', 'audio/ogg;codecs=opus', 'audio/mp4'].find((type) => MediaRecorder.isTypeSupported(type));\n const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);\n session.recorder = recorder;\n recorder.ondataavailable = (event) => { if (event.data.size) session.chunks.push(event.data); };\n recorder.onstop = () => {\n release(session);\n const isCurrent = sessionRef.current === session;\n if (isCurrent) sessionRef.current = null;\n if (!mountedRef.current || (!isCurrent && sessionRef.current)) return;\n setStatus('idle');\n if (session.cancelled) return;\n const type = recorder.mimeType || session.chunks[0]?.type || 'audio/webm';\n const blob = new Blob(session.chunks, { type });\n if (!blob.size) { setError('La grabación está vacía. Inténtalo de nuevo.'); return; }\n const extension = type.includes('mp4') ? 'm4a' : type.includes('ogg') ? 'ogg' : 'webm';\n callbackRef.current?.(new File([blob], `Nota de voz ${Date.now()}.${extension}`, { type }));\n };\n recorder.onerror = () => {\n session.cancelled = true;\n release(session);\n if (sessionRef.current === session) sessionRef.current = null;\n if (mountedRef.current) { setStatus('idle'); setError('No se pudo completar la grabación.'); }\n };\n recorder.start(250);\n session.startedAt = Date.now();\n setSeconds(0);\n setStatus('recording');\n session.timer = setInterval(() => {\n const elapsed = Math.floor((Date.now() - session.startedAt) / 1000);\n if (mountedRef.current) setSeconds(Math.min(elapsed, LIMIT_SECONDS));\n if (elapsed >= LIMIT_SECONDS) finish();\n }, 250);\n } catch (failure) {\n release(session);\n if (sessionRef.current === session) sessionRef.current = null;\n if (!mountedRef.current || session.cancelled) return;\n setStatus('idle');\n setError(failure.name === 'NotAllowedError' ? 'Permite el acceso al micrófono para grabar una nota de voz.' : 'No se pudo acceder al micrófono. Comprueba que esté disponible.');\n }\n }, [finish, release]);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n finish(true);\n };\n }, [finish]);\n\n return { status, seconds, error, start, stop: () => finish(), cancel: () => finish(true) };\n}\n","/**\n * GIF query expansion for Spanish / LatAm (Dominican) chat users.\n * Pure module: no React, no DOM, no network.\n *\n * expandGifQuery(\"cuánta bendición\") →\n * variants: original + alternative searches (es/en) to fan out against KLIPY,\n * intentTerms: words expected in good results' title/tags (re-ranking boost),\n * avoidTerms: generic noise (sports) to demote unless the query asks for it.\n */\n\nconst MAX_VARIANTS = 4;\n\nconst STOPWORDS = new Set([\n 'el', 'la', 'los', 'las', 'lo', 'un', 'una', 'unos', 'unas', 'de', 'del', 'al',\n 'y', 'e', 'o', 'u', 'a', 'en', 'con', 'por', 'para', 'mi', 'mis', 'su', 'sus',\n 'the', 'an', 'of', 'to', 'and', 'or', 'in', 'on', 'for', 'my', 'is',\n]);\n\nconst SPORTS_TERMS = new Set([\n 'futbol', 'soccer', 'football', 'gol', 'golazo', 'goal', 'messi', 'ronaldo', 'cr7',\n 'nba', 'nfl', 'mlb', 'fifa', 'mundial', 'beisbol', 'baseball', 'pelota', 'basket',\n 'baloncesto', 'basketball', 'lebron', 'deporte', 'deportes', 'sports', 'partido',\n 'jugador', 'player', 'licey', 'aguilas', 'escogido', 'champions', 'liga',\n]);\n\nconst AVOID_TERMS = [\n 'football', 'soccer', 'futbol', 'nba', 'nfl', 'mlb', 'goal', 'fifa', 'player',\n 'sports', 'basketball', 'match', 'team', 'jersey',\n];\n\n/**\n * Phrase / expression lexicon. `k` = trigger keys (normalized), `q` = alternative\n * queries in priority order (\"en:\" prefix → English), `i` = intent terms,\n * `re` = optional regex over the normalized text, `sports` = sports intent.\n */\nconst PHRASE_RULES = [\n { k: ['cuanta bendicion', 'cuanta bendicion meme'], q: ['cuanta bendicion meme', 'en:blessed meme', 'en:so blessed arms open'], i: ['cuanta bendicion', 'bendicion', 'blessed', 'bless', 'grateful', 'meme'] },\n { k: ['que bendicion', 'bendicion', 'bendiciones', 'bendecido', 'bendecida', 'blessed'], q: ['que bendicion', 'en:blessed happy', 'en:thank god happy'], i: ['bendicion', 'blessed', 'grateful', 'thank god', 'happy'] },\n { k: ['vida', 'asi es la vida', 'la vida'], q: ['vida meme', 'en:life meme', 'asi es la vida'], i: ['vida', 'life', 'asi es la vida', 'meme'] },\n { k: ['excelente', 'excellent'], q: ['en:excellent mr burns', 'en:mr burns excellent', 'excelente'], i: ['excellent', 'excelente', 'burns', 'mr burns', 'simpsons'] },\n { k: ['senor burns', 'sr burns', 'mr burns', 'montgomery', 'montgomery burns'], q: ['en:mr burns', 'en:montgomery burns', 'en:simpsons burns'], i: ['burns', 'mr burns', 'montgomery', 'simpsons'] },\n { k: ['no puede ser', 'no lo puedo creer', 'no me digas'], q: ['no puede ser', 'en:shocked reaction', 'en:surprised omg'], i: ['shocked', 'surprised', 'omg', 'no puede ser', 'wow'] },\n { k: ['diablo', 'diablo loco', 'diache', 'diantre'], q: ['diablo meme dominicano', 'en:dominican meme', 'diablo meme'], i: ['diablo', 'dominicano', 'dominican', 'meme', 'republica dominicana'] },\n { k: ['ya tu sabes', 'ya tu sabe', 'ya tu sabe lo que hay', 'pa que tu lo sepa'], q: ['ya tu sabes', 'en:you know meme', 'en:latino meme'], i: ['ya tu sabes', 'you know', 'wink', 'latino', 'meme'] },\n { k: ['jaja', 'jeje', 'jiji', 'jsjs', 'lol', 'lmao', 'xd'], re: /^(?:[jh][aeiou]){2,}[jh]?$|^(?:js)+j?$/, q: ['jajaja', 'en:laughing', 'en:lol funny'], i: ['laugh', 'laughing', 'lol', 'funny', 'jaja', 'risa'] },\n { k: ['que risa', 'me muero de risa', 'muerto de risa', 'me parto', 'risa'], q: ['que risa', 'en:laughing hard', 'en:dying laughing'], i: ['laugh', 'laughing', 'funny', 'risa', 'lol'] },\n { k: ['ay no', 'ay dios', 'ay dios mio', 'dios mio', 'oh no'], q: ['ay no', 'en:oh no', 'en:oh my god'], i: ['oh no', 'omg', 'ay no', 'dios mio', 'worried'] },\n { k: ['que pena', 'que verguenza', 'verguenza', 'cringe'], q: ['que pena', 'en:embarrassed', 'en:awkward cringe'], i: ['embarrassed', 'awkward', 'cringe', 'pena', 'verguenza'] },\n { k: ['tranquilo', 'tranquila', 'tranqui', 'calma', 'relax', 'calmate'], q: ['tranquilo', 'en:calm down', 'en:relax chill'], i: ['calm', 'relax', 'chill', 'tranquilo'] },\n { k: ['dale', 'dale pues', 'dale ahi'], q: ['dale', 'en:lets go', 'en:ok deal'], i: ['dale', 'lets go', 'ok', 'deal'] },\n { k: ['klk', 'que lo que', 'q lo q', 'que lo ke', 'klk mi loco', 'que hay'], q: ['klk', 'que lo que dominicano', 'en:whats up'], i: ['klk', 'que lo que', 'whats up', 'sup', 'hey', 'dominicano'] },\n { k: ['vamo arriba', 'vamos arriba', 'pa arriba', 'vamos', 'vamo', 'lets go'], q: ['vamo arriba', 'en:lets go hype', 'en:lets go'], i: ['lets go', 'hype', 'vamos', 'arriba', 'motivation'] },\n { k: ['wepa', 'epa', 'yupi', 'yay', 'eso'], q: ['wepa', 'en:yay celebration', 'en:excited happy dance'], i: ['wepa', 'yay', 'celebrate', 'excited', 'happy'] },\n { k: ['uff', 'ouf', 'uy', 'fiu'], q: ['uff', 'en:phew relief', 'en:exhausted sigh'], i: ['phew', 'sigh', 'relief', 'uff'] },\n { k: ['mano', 'manito', 'pana', 'mi pana', 'hermano', 'bro', 'compai', 'socio'], q: ['pana meme', 'en:bro hug', 'en:best friends'], i: ['bro', 'friend', 'friends', 'pana', 'hermano', 'brother'] },\n { k: ['tigre', 'tiguere', 'tiguerazo', 'tiguerito'], q: ['tiguere dominicano', 'en:cool guy swag', 'en:smooth'], i: ['tiguere', 'tigre', 'swag', 'cool', 'smooth'] },\n { k: ['que chulo', 'chulo', 'chula', 'que lindo', 'que linda', 'lindo', 'linda', 'que bello', 'cute'], q: ['que lindo', 'en:cute', 'en:aww adorable'], i: ['cute', 'aww', 'adorable', 'lindo', 'chulo'] },\n { k: ['que vaina', 'vaina', 'que es la vaina', 'que cosa', 'que es eso'], q: ['que vaina', 'en:confused what', 'en:what reaction'], i: ['confused', 'what', 'que vaina', 'huh'] },\n { k: ['que loco', 'loco', 'loca', 'locura', 'crazy'], q: ['que loco', 'en:crazy', 'en:crazy reaction'], i: ['crazy', 'loco', 'insane'] },\n { k: ['aplausos', 'aplauso', 'bravo', 'clap'], q: ['aplausos', 'en:applause', 'en:clapping bravo'], i: ['applause', 'clapping', 'clap', 'bravo', 'aplausos'] },\n { k: ['felicidades', 'felicitaciones', 'enhorabuena', 'congrats'], q: ['felicidades', 'en:congratulations', 'en:congrats celebration'], i: ['congratulations', 'congrats', 'felicidades', 'celebrate'] },\n { k: ['gracias', 'muchas gracias', 'mil gracias', 'grax', 'thanks'], q: ['gracias', 'en:thank you', 'en:thanks grateful'], i: ['thank you', 'thanks', 'gracias', 'grateful'] },\n { k: ['buenos dias', 'buen dia', 'good morning'], q: ['buenos dias', 'en:good morning', 'en:good morning coffee'], i: ['good morning', 'buenos dias', 'morning'] },\n { k: ['buenas tardes'], q: ['buenas tardes', 'en:good afternoon'], i: ['good afternoon', 'buenas tardes'] },\n { k: ['buenas noches', 'dulces suenos', 'good night'], q: ['buenas noches', 'en:good night', 'en:sleepy good night'], i: ['good night', 'buenas noches', 'night', 'sleep'] },\n { k: ['feliz cumpleanos', 'feliz cumple', 'cumpleanos', 'cumple', 'happy birthday'], q: ['feliz cumpleanos', 'en:happy birthday', 'en:birthday cake party'], i: ['birthday', 'happy birthday', 'cumpleanos', 'cake', 'party'] },\n { k: ['te amo', 'te quiero', 'te adoro', 'amor', 'mi amor', 'i love you'], q: ['te amo', 'en:i love you', 'en:love hearts'], i: ['love', 'i love you', 'te amo', 'hearts', 'heart'] },\n { k: ['triste', 'tristeza', 'que triste', 'depre', 'sad'], q: ['triste', 'en:sad', 'en:sad crying'], i: ['sad', 'triste', 'crying', 'depressed'] },\n { k: ['llorando', 'llorar', 'lloro', 'a llorar'], q: ['llorando', 'en:crying', 'en:crying sobbing'], i: ['crying', 'cry', 'sobbing', 'tears', 'llorando'] },\n { k: ['enojado', 'enojada', 'molesto', 'molesta', 'enfadado', 'enfadada', 'furioso', 'furiosa', 'rabia', 'angry'], q: ['enojado', 'en:angry', 'en:mad furious'], i: ['angry', 'mad', 'furious', 'rage', 'enojado'] },\n { k: ['sorprendido', 'sorprendida', 'sorpresa', 'wow', 'guau', 'omg'], q: ['sorprendido', 'en:surprised', 'en:wow shocked'], i: ['surprised', 'wow', 'shocked', 'omg', 'sorpresa'] },\n { k: ['facepalm', 'que bruto', 'que bruta', 'que tonto', 'en serio', 'smh'], q: ['en:facepalm', 'en:smh', 'que bruto'], i: ['facepalm', 'smh', 'disappointed', 'really'] },\n { k: ['ok', 'okey', 'okay', 'vale', 'esta bien', 'de acuerdo', 'perfecto'], q: ['ok', 'en:okay thumbs up', 'en:ok approved'], i: ['ok', 'okay', 'thumbs up', 'approved', 'perfect'] },\n { k: ['si', 'claro', 'claro que si', 'obvio', 'por supuesto', 'yes'], q: ['si', 'en:yes', 'en:yes nodding'], i: ['yes', 'si', 'nodding', 'of course'] },\n { k: ['no', 'nop', 'nope', 'para nada', 'jamas', 'nunca'], q: ['no', 'en:no nope', 'en:no way'], i: ['no', 'nope', 'no way', 'never'] },\n { k: ['no se', 'ni idea', 'quien sabe'], q: ['no se', 'en:i dont know shrug', 'en:shrug'], i: ['shrug', 'i dont know', 'no se', 'idk'] },\n { k: ['adios', 'chao', 'chau', 'bye', 'nos vemos', 'hasta luego'], q: ['adios', 'en:bye bye', 'en:goodbye wave'], i: ['bye', 'goodbye', 'adios', 'wave'] },\n { k: ['hola', 'holi', 'saludos', 'hey', 'hello', 'hi'], q: ['hola', 'en:hello', 'en:hi wave'], i: ['hello', 'hi', 'hola', 'wave', 'hey'] },\n { k: ['fiesta', 'party', 'parranda', 'rumba', 'juidero', 'janguear'], q: ['fiesta', 'en:party', 'en:party celebration'], i: ['party', 'fiesta', 'celebration', 'celebrate'] },\n { k: ['bailar', 'baile', 'bailando', 'a bailar', 'dance'], q: ['bailando', 'en:dancing', 'en:dance party'], i: ['dance', 'dancing', 'baile', 'bailando'] },\n { k: ['bachata', 'merengue', 'dembow', 'salsa'], q: ['bachata merengue', 'en:dominican dance', 'en:latin dance'], i: ['bachata', 'merengue', 'dembow', 'latin', 'dance', 'dominican'] },\n { k: ['cansado', 'cansada', 'agotado', 'agotada', 'no puedo mas', 'tired'], q: ['cansado', 'en:tired', 'en:exhausted'], i: ['tired', 'exhausted', 'cansado', 'sleepy'] },\n { k: ['tengo sueno', 'sueno', 'dormir', 'a dormir', 'zzz', 'sleepy'], q: ['tengo sueno', 'en:sleepy', 'en:sleeping'], i: ['sleepy', 'sleep', 'sleeping', 'sueno', 'tired'] },\n { k: ['hambre', 'tengo hambre', 'a comer', 'comida', 'hungry'], q: ['tengo hambre', 'en:hungry', 'en:food eating'], i: ['hungry', 'food', 'eating', 'hambre', 'comida'] },\n { k: ['dinero', 'cuarto', 'cuartos', 'chavos', 'plata', 'pesos', 'quincena', 'pago', 'money'], q: ['dinero', 'en:money', 'en:money rain rich'], i: ['money', 'cash', 'rich', 'dinero', 'payday'] },\n { k: ['trabajo', 'trabajando', 'a trabajar', 'chamba', 'oficina', 'work'], q: ['trabajo', 'en:working', 'en:office work'], i: ['work', 'working', 'office', 'trabajo', 'job'] },\n { k: ['lunes', 'monday'], q: ['lunes', 'en:monday', 'en:monday mood'], i: ['monday', 'lunes', 'mood'] },\n { k: ['viernes', 'por fin viernes', 'al fin viernes', 'friday'], q: ['viernes', 'en:friday', 'en:its friday'], i: ['friday', 'viernes', 'weekend', 'tgif'] },\n { k: ['fin de semana', 'finde', 'weekend'], q: ['fin de semana', 'en:weekend', 'en:weekend vibes'], i: ['weekend', 'fin de semana', 'relax'] },\n { k: ['cafe', 'cafecito', 'un cafe', 'coffee'], q: ['cafe', 'en:coffee', 'en:coffee morning'], i: ['coffee', 'cafe', 'morning'] },\n { k: ['calor', 'que calor', 'hot'], q: ['que calor', 'en:hot sweating', 'en:so hot'], i: ['hot', 'heat', 'sweating', 'calor'] },\n { k: ['frio', 'que frio', 'cold'], q: ['que frio', 'en:cold freezing', 'en:so cold'], i: ['cold', 'freezing', 'frio'] },\n { k: ['pensando', 'hmm', 'mmm', 'dejame pensar', 'thinking'], q: ['pensando', 'en:thinking', 'en:hmm thinking'], i: ['thinking', 'hmm', 'think', 'pensando'] },\n { k: ['miedo', 'que miedo', 'susto', 'asustado', 'asustada', 'scared'], q: ['que miedo', 'en:scared', 'en:scared terrified'], i: ['scared', 'fear', 'terrified', 'miedo'] },\n { k: ['nervioso', 'nerviosa', 'nervios', 'nervous'], q: ['nervioso', 'en:nervous', 'en:nervous sweating'], i: ['nervous', 'anxious', 'nervioso'] },\n { k: ['aburrido', 'aburrida', 'que aburrido', 'bored'], q: ['aburrido', 'en:bored', 'en:so bored'], i: ['bored', 'boring', 'aburrido'] },\n { k: ['feliz', 'contento', 'contenta', 'alegre', 'happy'], q: ['feliz', 'en:happy', 'en:happy dance'], i: ['happy', 'joy', 'feliz', 'smile'] },\n { k: ['emocionado', 'emocionada', 'que emocion', 'excited'], q: ['emocionado', 'en:excited', 'en:so excited'], i: ['excited', 'hype', 'emocionado'] },\n { k: ['que bueno', 'buenisimo', 'genial', 'chevere', 'nitido', 'brutal', 'tremendo'], q: ['que bueno', 'en:great awesome', 'en:awesome thumbs up'], i: ['great', 'awesome', 'cool', 'genial', 'nice'] },\n { k: ['esperando', 'apurate', 'te espero', 'waiting'], q: ['esperando', 'en:waiting', 'en:hurry up waiting'], i: ['waiting', 'wait', 'hurry', 'esperando'] },\n { k: ['chisme', 'bochinche', 'cuentame', 'el chisme', 'tea'], q: ['chisme', 'en:gossip', 'en:sipping tea'], i: ['gossip', 'tea', 'chisme', 'bochinche', 'drama'] },\n { k: ['mentira', 'mentiroso', 'mentirosa', 'eso es mentira', 'liar'], q: ['mentira', 'en:liar', 'en:lie lying'], i: ['liar', 'lie', 'lying', 'mentira'] },\n { k: ['suerte', 'buena suerte', 'exito', 'exitos', 'good luck'], q: ['buena suerte', 'en:good luck', 'en:fingers crossed'], i: ['good luck', 'luck', 'suerte', 'fingers crossed'] },\n { k: ['lo siento', 'perdon', 'perdoname', 'disculpa', 'disculpame', 'sorry'], q: ['lo siento', 'en:sorry', 'en:sorry apology'], i: ['sorry', 'apology', 'perdon', 'lo siento'] },\n { k: ['besos', 'beso', 'muack', 'mua', 'kiss'], q: ['besos', 'en:kiss', 'en:kisses love'], i: ['kiss', 'kisses', 'beso', 'love'] },\n { k: ['abrazo', 'abrazos', 'hug'], q: ['abrazo', 'en:hug', 'en:big hug'], i: ['hug', 'hugs', 'abrazo'] },\n { k: ['callate', 'silencio', 'shh'], q: ['callate', 'en:shh quiet', 'en:shut up'], i: ['shh', 'quiet', 'silence', 'callate'] },\n { k: ['dominicano', 'dominicana', 'rd', 'republica dominicana', 'quisqueya', 'dominican'], q: ['dominicano meme', 'en:dominican republic', 'en:dominican flag'], i: ['dominicano', 'dominican', 'republica dominicana', 'rd', 'quisqueya'] },\n { k: ['gol', 'golazo', 'goal'], q: ['golazo', 'en:goal celebration', 'en:soccer goal'], i: ['goal', 'gol', 'golazo', 'soccer', 'futbol'], sports: true },\n];\n\n/** Word lexicon es→en used to build an English variant when no phrase rule matches. */\nconst WORDS = {\n triste: 'sad', feliz: 'happy', contento: 'happy', alegre: 'happy', enojado: 'angry', molesto: 'annoyed',\n furioso: 'furious', cansado: 'tired', aburrido: 'bored', asustado: 'scared', miedo: 'scared',\n sorprendido: 'surprised', confundido: 'confused', nervioso: 'nervous', celoso: 'jealous',\n orgulloso: 'proud', emocionado: 'excited', enamorado: 'in love', avergonzado: 'embarrassed',\n loco: 'crazy', gracioso: 'funny', chistoso: 'funny', lindo: 'cute', bonito: 'pretty', feo: 'ugly',\n bueno: 'good', malo: 'bad', mejor: 'best', peor: 'worst', rapido: 'fast', lento: 'slow',\n flojo: 'lazy', vago: 'lazy', rico: 'rich', pobre: 'broke', borracho: 'drunk', enfermo: 'sick',\n hambre: 'hungry', sueno: 'sleepy', calor: 'hot', frio: 'cold', amor: 'love', corazon: 'heart',\n beso: 'kiss', abrazo: 'hug', risa: 'laugh', llorar: 'cry', reir: 'laugh', gritar: 'scream',\n bailar: 'dance', baile: 'dance', cantar: 'sing', comer: 'eat', beber: 'drink', dormir: 'sleep',\n correr: 'run', esperar: 'wait', pensar: 'think', ganar: 'win', perder: 'lose', saludo: 'hello',\n perro: 'dog', gato: 'cat', pollo: 'chicken', mono: 'monkey', pajaro: 'bird', bebe: 'baby',\n nino: 'kid', mama: 'mom', papa: 'dad', abuela: 'grandma', amigo: 'friend', novio: 'boyfriend',\n novia: 'girlfriend', jefe: 'boss', escuela: 'school', examen: 'exam', tarea: 'homework',\n comida: 'food', cerveza: 'beer', vino: 'wine', agua: 'water', pizza: 'pizza', playa: 'beach',\n lluvia: 'rain', sol: 'sun', casa: 'home', carro: 'car', dinero: 'money', trabajo: 'work',\n fiesta: 'party', musica: 'music', navidad: 'christmas', verano: 'summer', invierno: 'winter',\n lunes: 'monday', viernes: 'friday', domingo: 'sunday', cafe: 'coffee', vida: 'life',\n bendicion: 'blessed', exito: 'success', sorpresa: 'surprise', regalo: 'gift', pastel: 'cake',\n bizcocho: 'cake', telefono: 'phone', mensaje: 'message', gracias: 'thank you', hola: 'hello',\n adios: 'bye', si: 'yes', no: 'no', fuego: 'fire', diablo: 'devil', angel: 'angel',\n};\n\nconst EN_WORDS = new Set(Object.values(WORDS).flatMap((v) => v.split(' ')).concat(\n ['meme', 'reaction', 'funny', 'lol', 'omg', 'wow', 'yes', 'ok', 'okay', 'what', 'why', 'love', 'you', 'i', 'me'],\n));\n\n/**\n * Lowercase, trim, strip accents/diacritics, emoji and punctuation, collapse spaces.\n * @param {string} text\n * @returns {string} e.g. \"¡Cuánta Bendición!\" → \"cuanta bendicion\"\n */\nexport function normalizeQuery(text) {\n return String(text ?? '')\n .toLowerCase()\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .replace(/[\\p{Extended_Pictographic}\\u{1F1E6}-\\u{1F1FF}\\u{1F3FB}-\\u{1F3FF}‍️⃣]/gu, ' ')\n .replace(/[^\\p{L}\\p{N}\\s]/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/**\n * Normalized tokens without (a small set of) stopwords. Falls back to all tokens\n * if everything was a stopword.\n * @param {string} text\n * @returns {string[]}\n */\nexport function tokenize(text) {\n const all = normalizeQuery(text).split(' ').filter(Boolean);\n const kept = all.filter((t) => !STOPWORDS.has(t));\n return kept.length ? kept : all;\n}\n\n/** Collapse repeated letters (\"ufff\" → \"uf\", \"siii\" → \"si\") for fuzzy matching. */\nconst squash = (s) => s.replace(/(.)\\1+/g, '$1');\n\n/** Levenshtein distance with early exit when it exceeds `max`. */\nfunction lev(a, b, max = 1) {\n if (Math.abs(a.length - b.length) > max) return max + 1;\n let prev = Array.from({ length: b.length + 1 }, (_, j) => j);\n for (let i = 1; i <= a.length; i++) {\n const cur = [i];\n let rowMin = i;\n for (let j = 1; j <= b.length; j++) {\n cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));\n rowMin = Math.min(rowMin, cur[j]);\n }\n if (rowMin > max) return max + 1;\n prev = cur;\n }\n return prev[b.length];\n}\n\nconst COMPILED_RULES = PHRASE_RULES.map((r) => ({ ...r, sk: r.k.map((k) => squash(normalizeQuery(k))) }));\n\n/**\n * Best phrase rule for a normalized query: exact > whole-word contains > typing prefix > 1-typo.\n * @returns {{ rule: object, exact: boolean } | null}\n */\nfunction findRule(normalized) {\n const s = squash(normalized);\n const padded = ` ${s} `;\n let best = null;\n let bestScore = 0;\n for (const rule of COMPILED_RULES) {\n if (rule.re?.test(normalized)) {\n if (1000 > bestScore) { best = rule; bestScore = 1000; }\n continue;\n }\n for (const k of rule.sk) {\n let score = 0;\n if (s === k) score = 1000 + k.length;\n else if ((k.length > 3 || k.includes(' ')) && padded.includes(` ${k} `)) score = 500 + k.length;\n else if (s.length >= 4 && k.startsWith(s)) score = 300 + s.length;\n else if (s.length >= 5 && k.length >= 5 && lev(s, k) <= 1) score = 200 + k.length;\n if (score > bestScore) { best = rule; bestScore = score; }\n }\n }\n return best ? { rule: best, exact: bestScore >= 1000 } : null;\n}\n\n/** Translate one token via WORDS, tolerating plural / feminine forms. */\nfunction translateWord(t) {\n if (WORDS[t]) return WORDS[t];\n const base = t.endsWith('es') ? t.slice(0, -2) : t.endsWith('s') ? t.slice(0, -1) : t;\n if (WORDS[base]) return WORDS[base];\n if (base.endsWith('a') && WORDS[`${base.slice(0, -1)}o`]) return WORDS[`${base.slice(0, -1)}o`];\n return null;\n}\n\nconst uniq = (arr) => [...new Set(arr.filter(Boolean))];\n\n/**\n * Expand a chat GIF query into weighted search variants + re-ranking hints.\n * @param {string} query\n * @returns {{\n * original: string, normalized: string,\n * variants: Array<{ q: string, weight: number, lang: 'es'|'en', reason: string }>,\n * intentTerms: string[], avoidTerms: string[], isPhrase: boolean\n * }}\n */\nexport function expandGifQuery(query) {\n const original = String(query ?? '').trim();\n const normalized = normalizeQuery(original);\n const tokens = tokenize(original);\n const empty = { original, normalized, variants: [], intentTerms: [], avoidTerms: [], isPhrase: false };\n if (!normalized) return empty;\n\n const isEnglish = tokens.every((t) => EN_WORDS.has(t));\n const translated = tokens.map(translateWord);\n const known = translated.filter(Boolean).length;\n const enPhrase = !isEnglish && known && known * 2 >= tokens.length\n ? tokens.map((t, idx) => translated[idx] || t).join(' ')\n : null;\n\n const variants = [];\n const seen = new Set();\n const push = (q, weight, lang, reason) => {\n const key = normalizeQuery(q);\n if (!key || seen.has(key) || variants.length >= MAX_VARIANTS) return;\n seen.add(key);\n variants.push({ q, weight, lang, reason });\n };\n\n push(original, 1, isEnglish ? 'en' : 'es', 'original');\n\n const match = findRule(normalized);\n let intent = [];\n let sports = tokens.some((t) => SPORTS_TERMS.has(t));\n\n if (match) {\n const { rule, exact } = match;\n const factor = exact ? 1 : 0.9;\n rule.q.forEach((entry, idx) => {\n const en = entry.startsWith('en:');\n push(en ? entry.slice(3) : entry, +((0.9 - idx * 0.1) * factor).toFixed(2), en ? 'en' : 'es', exact ? 'phrase-rule' : 'phrase-rule-partial');\n });\n intent = rule.i.map(normalizeQuery);\n sports = sports || !!rule.sports;\n } else {\n const hasMeme = tokens.includes('meme');\n if (!hasMeme) push(`${normalized} meme`, 0.8, isEnglish ? 'en' : 'es', tokens.length > 1 ? 'phrase-meme' : 'word-meme');\n if (enPhrase) push(enPhrase, 0.6, 'en', 'translation');\n if (enPhrase && !hasMeme) push(`${enPhrase} reaction`, 0.5, 'en', 'translation-reaction');\n }\n\n const intentTerms = uniq([...intent, ...tokens, ...translated, ...(enPhrase ? [enPhrase] : [])])\n .filter((t) => t !== 'meme' || intent.includes('meme'))\n .slice(0, 24);\n\n return {\n original,\n normalized,\n variants,\n intentTerms,\n avoidTerms: sports ? [] : AVOID_TERMS.slice(),\n isPhrase: tokens.length > 1 || !!match,\n };\n}\n\nexport default expandGifQuery;\n","/**\n * Ranking de relevancia para resultados de GIF de KLIPY.\n * Módulo puro: sin React, DOM ni red.\n */\nimport { normalizeQuery, tokenize } from './gifQueryExpansion.js';\n\nconst RANK_DECAY = 0.08;\nconst TITLE_PHRASE = 1.2;\nconst TAG_PHRASE = 0.9;\nconst TITLE_TOKEN = 0.6;\nconst TAG_TOKEN = 0.4;\nconst PARTIAL_PHRASE = 0.25;\nconst AVOID_PENALTY = 0.8;\nconst EMPTY_PENALTY = 0.15;\nconst PROTECT_TOP = 4; // top-N del query original que no se deben enterrar\nconst PROTECT_SLACK = 2; // posiciones que pueden bajar como máximo\n\n/** Normaliza texto libre (incluye separadores tipo slug). */\nconst norm = (s) => normalizeQuery(String(s || '').replace(/[-_]+/g, ' ')) || '';\n\n/** Clave de deduplicación. */\nconst keyOf = (item) => item?.id ?? item?.url ?? item?.slug;\n\n/**\n * Precalcula términos normalizados (una vez por llamada).\n * @param {string[]} intentTerms\n * @param {string[]} avoidTerms\n */\nfunction prepareTerms(intentTerms = [], avoidTerms = []) {\n const prep = (list) => {\n const seen = new Set();\n const out = [];\n for (const t of list || []) {\n const n = norm(t);\n if (!n || seen.has(n)) continue;\n seen.add(n);\n const tokens = tokenize(n);\n out.push({ text: n, padded: ` ${n} `, tokens, phrase: tokens.length > 1 });\n }\n return out;\n };\n return { intent: prep(intentTerms), avoid: prep(avoidTerms) };\n}\n\n/** Prepara el texto indexable del item. */\nfunction prepareItem(item) {\n const title = norm(item?.title);\n const tags = Array.isArray(item?.tags) ? item.tags.map(norm).filter(Boolean) : [];\n const tagText = tags.join(' ');\n return {\n title,\n titlePadded: ` ${title} `,\n tagsPadded: tags.map((t) => ` ${t} `),\n titleTokens: new Set(tokenize(title)),\n tagTokens: new Set(tokenize(tagText)),\n all: ` ${title} ${tagText} `,\n empty: !title && !tags.length,\n };\n}\n\n/** Bonus de intención + flag de coincidencia. */\nfunction intentMatch(doc, intent) {\n let bonus = 0;\n let matched = false;\n for (const term of intent) {\n if (term.phrase) {\n if (doc.titlePadded.includes(term.padded)) {\n bonus += TITLE_PHRASE;\n matched = true;\n } else if (doc.tagsPadded.some((t) => t.includes(term.padded))) {\n bonus += TAG_PHRASE;\n matched = true;\n } else {\n let hits = 0;\n for (const tk of term.tokens) if (doc.titleTokens.has(tk) || doc.tagTokens.has(tk)) hits++;\n if (hits) bonus += PARTIAL_PHRASE * (hits / term.tokens.length);\n if (hits === term.tokens.length) matched = true;\n }\n } else if (doc.titleTokens.has(term.text)) {\n bonus += TITLE_TOKEN;\n matched = true;\n } else if (doc.tagTokens.has(term.text)) {\n bonus += TAG_TOKEN;\n matched = true;\n }\n }\n return { bonus, matched };\n}\n\n/** Score interno con términos ya preparados. */\nfunction scoreWith(item, terms, variantWeight = 1, rank = 0) {\n const doc = prepareItem(item);\n const prior = (1 / (1 + Math.max(0, rank) * RANK_DECAY)) * variantWeight;\n if (doc.empty) return { score: prior - EMPTY_PENALTY, matched: false };\n const { bonus, matched } = intentMatch(doc, terms.intent);\n let score = prior + bonus;\n if (!matched && terms.avoid.some((a) => doc.all.includes(a.padded))) score -= AVOID_PENALTY;\n return { score, matched };\n}\n\n/**\n * Puntúa un GIF según orden de KLIPY, peso de variante e intención.\n * @param {object} item GIF `{ id, title, tags, ... }`\n * @param {{ intentTerms?: string[], avoidTerms?: string[], variantWeight?: number, rank?: number }} opts\n * @returns {number}\n */\nexport function scoreGif(item, { intentTerms = [], avoidTerms = [], variantWeight = 1, rank = 0 } = {}) {\n return scoreWith(item, prepareTerms(intentTerms, avoidTerms), variantWeight, rank).score;\n}\n\n/**\n * Fusiona resultados de varias variantes, deduplica por id y ordena por score.\n * Los primeros resultados del query original (índice 0) que coinciden con la\n * intención no bajan más de PROTECT_SLACK posiciones respecto a su rank original.\n * @param {{ variant?: { weight?: number }, items: object[] }[]} groups\n * @param {{ intentTerms?: string[], avoidTerms?: string[] }} expansion\n * @returns {object[]}\n */\nexport function rankGifs(groups, expansion = {}) {\n const terms = prepareTerms(expansion?.intentTerms, expansion?.avoidTerms);\n const noIntent = terms.intent.length === 0;\n const best = new Map();\n let seq = 0;\n\n (groups || []).forEach((group, gi) => {\n const weight = group?.variant?.weight ?? 1;\n (group?.items || []).forEach((item, rank) => {\n const key = keyOf(item);\n if (key == null) return;\n const { score, matched } = scoreWith(item, terms, weight, rank);\n const prev = best.get(key);\n const protectedRank = gi === 0 && rank < PROTECT_TOP && (matched || noIntent) ? rank : -1;\n if (!prev) {\n best.set(key, { item, score, order: seq++, protectedRank });\n } else {\n if (score > prev.score) {\n prev.score = score;\n prev.item = item;\n }\n if (protectedRank >= 0 && prev.protectedRank < 0) prev.protectedRank = protectedRank;\n }\n });\n });\n\n const sorted = [...best.values()].sort((a, b) => b.score - a.score || a.order - b.order);\n\n const pinned = sorted.filter((e) => e.protectedRank >= 0).sort((a, b) => a.protectedRank - b.protectedRank);\n for (const entry of pinned) {\n const idx = sorted.indexOf(entry);\n const maxIdx = entry.protectedRank + PROTECT_SLACK;\n if (idx > maxIdx) {\n sorted.splice(idx, 1);\n sorted.splice(maxIdx, 0, entry);\n }\n }\n\n return sorted.map((e) => e.item);\n}\n\n/**\n * ¿Hay al menos `min` resultados que coinciden con la intención?\n * @param {object[]} items\n * @param {{ intentTerms?: string[] }} expansion\n * @param {{ min?: number }} [opts]\n * @returns {boolean}\n */\nexport function hasGoodResults(items, expansion, { min = 6 } = {}) {\n const list = items || [];\n const terms = prepareTerms(expansion?.intentTerms, []);\n if (!terms.intent.length) return list.length >= min;\n let count = 0;\n for (const item of list) {\n if (intentMatch(prepareItem(item), terms.intent).matched && ++count >= min) return true;\n }\n return false;\n}\n\n/**\n * Añade a `previous` los items de `next` cuyo id aún no está (scroll infinito).\n * @param {object[]} previous\n * @param {object[]} next\n * @returns {object[]}\n */\nexport function interleaveFresh(previous = [], next = []) {\n const seen = new Set((previous || []).map(keyOf));\n const out = [...(previous || [])];\n for (const item of next || []) {\n const key = keyOf(item);\n if (key == null || seen.has(key)) continue;\n seen.add(key);\n out.push(item);\n }\n return out;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\nimport { isTrustedKlipyUrl } from '../klipy/klipy.js';\n\n// Local-only GIF favorites/recents (no backend, no cross-device sync).\nexport const MAX_RECENTS = 40;\nexport const MAX_FAVORITES = 200;\nconst STORAGE_KEY = 'lira-gif-library:v1';\nconst hasWindow = typeof window !== 'undefined';\n\n/** Only credential-free https URLs on KLIPY media hosts are accepted. */\nfunction safeUrl(value) {\n if (typeof value !== 'string' || value.length > 2048) return null;\n if (!isTrustedKlipyUrl(value)) return null;\n try {\n const url = new URL(value);\n return url.port ? null : url.href;\n } catch {\n return null;\n }\n}\n\nconst text = (value, max = 256) => (typeof value === 'string' ? value.slice(0, max) : '');\nconst dimension = (value) => (Number.isFinite(value) && value > 0 ? Math.round(value) : 0);\n\n/** Strip to the stored shape; returns null for invalid items. */\nexport function sanitizeItem(item, savedAt) {\n if (!item || typeof item !== 'object') return null;\n const { id } = item;\n if (!((typeof id === 'string' && id) || (typeof id === 'number' && Number.isFinite(id)))) return null;\n const url = safeUrl(item.url);\n const preview = safeUrl(item.preview);\n if (!url || !preview) return null;\n const time = savedAt ?? item.savedAt;\n return {\n id: String(id).slice(0, 128),\n slug: text(item.slug),\n title: text(item.title),\n preview,\n url,\n width: dimension(item.width),\n height: dimension(item.height),\n savedAt: Number.isFinite(time) && time >= 0 ? time : 0,\n };\n}\n\n// Sanitize + dedupe by id (first occurrence wins) + cap.\nfunction cleanList(list, max) {\n if (!Array.isArray(list)) return [];\n const seen = new Set();\n const out = [];\n for (const raw of list) {\n const item = sanitizeItem(raw);\n if (!item || seen.has(item.id)) continue;\n seen.add(item.id);\n out.push(item);\n if (out.length >= max) break;\n }\n return out;\n}\n\nfunction readStorage() {\n const empty = { favorites: [], recents: [] };\n if (!hasWindow) return empty;\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return empty;\n const data = JSON.parse(raw);\n return {\n favorites: cleanList(data?.favorites, MAX_FAVORITES),\n recents: cleanList(data?.recents, MAX_RECENTS),\n };\n } catch {\n return empty;\n }\n}\n\n// Private mode / quota errors are ignored: state stays in memory.\nfunction writeStorage({ favorites, recents }) {\n if (!hasWindow) return;\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ favorites, recents }));\n } catch {\n /* keep in memory */\n }\n}\n\nconst idOf = (value) => (value == null ? '' : String(value));\n\nexport function createGifLibraryStore() {\n const store = createStore((set, get) => {\n // Persist after every local mutation.\n const commit = (next) => {\n set(next);\n const { favorites, recents } = get();\n writeStorage({ favorites, recents });\n };\n\n return {\n ...readStorage(),\n\n isFavorite: (id) => {\n const key = idOf(id);\n return get().favorites.some((item) => item.id === key);\n },\n\n toggleFavorite: (raw) => {\n const key = idOf(raw?.id);\n const { favorites } = get();\n if (favorites.some((item) => item.id === key)) {\n commit({ favorites: favorites.filter((item) => item.id !== key) });\n return;\n }\n const item = sanitizeItem(raw, Date.now());\n if (!item) return;\n commit({ favorites: [item, ...favorites].slice(0, MAX_FAVORITES) });\n },\n\n addRecent: (raw) => {\n const item = sanitizeItem(raw, Date.now());\n if (!item) return;\n const rest = get().recents.filter((entry) => entry.id !== item.id);\n commit({ recents: [item, ...rest].slice(0, MAX_RECENTS) });\n },\n\n removeRecent: (id) => {\n const key = idOf(id);\n commit({ recents: get().recents.filter((item) => item.id !== key) });\n },\n\n clearRecents: () => commit({ recents: [] }),\n };\n });\n\n // Cross-tab sync: another tab wrote (or storage was cleared) → re-read.\n // Explicit opt-in (no import-time side effects). Ref-counted: the listener is\n // registered once and removed when every caller has called its stop().\n let syncRefs = 0;\n const onStorage = (event) => {\n if (event.key === STORAGE_KEY || event.key === null) store.setState(readStorage());\n };\n store.startSync = () => {\n if (!hasWindow || typeof window.addEventListener !== 'function') return () => {};\n if (syncRefs === 0) {\n window.addEventListener('storage', onStorage);\n store.setState(readStorage());\n }\n syncRefs += 1;\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n syncRefs -= 1;\n if (syncRefs === 0) window.removeEventListener('storage', onStorage);\n };\n };\n return store;\n}\n\nconst gifLibraryStore = createGifLibraryStore();\n/** Backward-compatible singleton hook (with vanilla store API attached). */\nexport const useGifLibrary = Object.assign((selector) => useStore(gifLibraryStore, selector), {\n getState: gifLibraryStore.getState, setState: gifLibraryStore.setState, subscribe: gifLibraryStore.subscribe,\n});\n\nexport function startGifLibrarySync(store = gifLibraryStore) {\n return (store === useGifLibrary ? gifLibraryStore : store).startSync();\n}\n","/**\n * Motor de búsqueda de GIFs (sin React): feeds trending/search/recent/favorites,\n * búsqueda inteligente multi-variante, caché LRU con TTL y dedupe de requests en vuelo.\n */\nimport { fetchTrendingGifs, searchGifsPage, fetchRecentGifs, getKlipyLocale } from '../klipy/klipy.js';\nimport { expandGifQuery, normalizeQuery } from './gifQueryExpansion.js';\nimport { rankGifs, hasGoodResults } from './gifRelevance.js';\nimport { useGifLibrary } from './gifLibrary.js';\n\nconst CACHE_TTL_MS = 5 * 60 * 1000;\nconst CACHE_MAX = 150;\nconst MAX_VARIANTS_PAGE1 = 3;\nconst MAX_VARIANTS_NEXT = 2;\nconst APPROX_NOTICE = 'Mostrando resultados aproximados';\n\n/** @type {Map<string, { value: any, expires: number }>} */\nconst cache = new Map();\n/** @type {Map<string, { promise: Promise<any>, controller: AbortController, refs: number }>} */\nconst inflight = new Map();\n\n/** Vacía la caché en memoria (las requests en vuelo siguen su curso). */\nexport function clearGifCache() {\n cache.clear();\n}\n\nfunction makeAbortError() {\n try {\n return new DOMException('Aborted', 'AbortError');\n } catch {\n const err = new Error('Aborted');\n err.name = 'AbortError';\n return err;\n }\n}\n\nconst isAbortError = (err) => err?.name === 'AbortError';\n\nfunction cacheGet(key) {\n const entry = cache.get(key);\n if (!entry) return undefined;\n if (entry.expires <= Date.now()) {\n cache.delete(key);\n return undefined;\n }\n // LRU: mover al final.\n cache.delete(key);\n cache.set(key, entry);\n return entry.value;\n}\n\nfunction cacheSet(key, value) {\n cache.delete(key);\n cache.set(key, { value, expires: Date.now() + CACHE_TTL_MS });\n while (cache.size > CACHE_MAX) {\n cache.delete(cache.keys().next().value);\n }\n}\n\n/**\n * Ejecuta `fetcher(signal)` con caché + dedupe. La request compartida solo se aborta\n * cuando TODOS los callers abortaron; cada caller abortado recibe AbortError de inmediato.\n * @param {string} key\n * @param {(signal: AbortSignal) => Promise<any>} fetcher\n * @param {AbortSignal} [signal]\n */\nfunction cachedRequest(key, fetcher, signal) {\n if (signal?.aborted) return Promise.reject(makeAbortError());\n\n const hit = cacheGet(key);\n if (hit !== undefined) return Promise.resolve(hit);\n\n let entry = inflight.get(key);\n if (!entry) {\n const controller = new AbortController();\n const promise = Promise.resolve()\n .then(() => fetcher(controller.signal))\n .then((value) => {\n cacheSet(key, value); // nunca se cachean fallos\n return value;\n })\n .finally(() => {\n if (inflight.get(key) === entry) inflight.delete(key);\n });\n entry = { promise, controller, refs: 0 };\n inflight.set(key, entry);\n }\n const shared = entry;\n shared.refs += 1;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const release = () => {\n shared.refs -= 1;\n if (shared.refs <= 0) {\n if (inflight.get(key) === shared) inflight.delete(key);\n shared.controller.abort();\n }\n };\n const onAbort = () => {\n if (settled) return;\n settled = true;\n release();\n reject(makeAbortError());\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n\n shared.promise.then(\n (value) => {\n if (settled) return;\n settled = true;\n shared.refs -= 1;\n signal?.removeEventListener('abort', onAbort);\n resolve(value);\n },\n (err) => {\n if (settled) return;\n settled = true;\n shared.refs -= 1;\n signal?.removeEventListener('abort', onAbort);\n reject(err);\n },\n );\n });\n}\n\nconst keyOf = (kind, query, locale, page, perPage) =>\n `${kind}|${query}|${locale}|${page}|${perPage}`;\n\nconst normalizeResult = (res) => ({\n items: Array.isArray(res?.items) ? res.items : [],\n hasMore: Boolean(res?.hasMore),\n});\n\nfunction loadTrending({ page, perPage, signal }) {\n const key = keyOf('trending', '', getKlipyLocale(), page, perPage);\n return cachedRequest(\n key,\n (s) => fetchTrendingGifs({ page, perPage, locale: getKlipyLocale(), signal: s }).then(normalizeResult),\n signal,\n ).then((res) => ({ ...res, notice: null }));\n}\n\nfunction loadVariant(variant, page, perPage, signal) {\n const key = keyOf('search', normalizeQuery(variant.q), getKlipyLocale(), page, perPage);\n return cachedRequest(\n key,\n (s) =>\n searchGifsPage({ query: variant.q, page, perPage, locale: getKlipyLocale(), signal: s }).then(\n normalizeResult,\n ),\n signal,\n );\n}\n\n/** Elige variantes por peso, garantizando que la query original quede incluida. */\nfunction pickVariants(expansion, limit) {\n const all = Array.isArray(expansion?.variants) ? [...expansion.variants] : [];\n if (!all.length) {\n all.push({ q: expansion?.original || expansion?.normalized || '', weight: 1, lang: null, reason: 'original' });\n }\n const sorted = all\n .map((v, i) => ({ v, i }))\n .sort((a, b) => (b.v.weight ?? 0) - (a.v.weight ?? 0) || a.i - b.i)\n .map(({ v }) => v);\n const picked = sorted.slice(0, limit);\n const originalNorm = normalizeQuery(expansion?.original || '');\n if (originalNorm && !picked.some((v) => normalizeQuery(v.q) === originalNorm)) {\n const orig = sorted.find((v) => normalizeQuery(v.q) === originalNorm) || {\n q: expansion.original,\n weight: 1,\n lang: null,\n reason: 'original',\n };\n if (picked.length < limit) picked.push(orig);\n else picked[limit - 1] = orig;\n }\n return picked;\n}\n\nasync function loadSearch({ query, page, perPage, signal }) {\n const expansion = expandGifQuery(query);\n const variants = pickVariants(expansion, page > 1 ? MAX_VARIANTS_NEXT : MAX_VARIANTS_PAGE1);\n\n const settled = await Promise.allSettled(\n variants.map((v) => loadVariant(v, page, perPage, signal)),\n );\n if (signal?.aborted) throw makeAbortError();\n\n const groups = [];\n let firstError = null;\n settled.forEach((r, i) => {\n if (r.status === 'fulfilled') {\n groups.push({ ...variants[i], variant: variants[i], items: r.value.items, hasMore: r.value.hasMore });\n } else if (!firstError || isAbortError(firstError)) {\n firstError = r.reason;\n }\n });\n if (!groups.length) throw firstError || new Error('GIF search failed');\n\n const items = rankGifs(groups, expansion) || [];\n const hasMore = groups.some((g) => g.hasMore);\n let notice = null;\n if (page === 1 && items.length && !hasGoodResults(items, expansion)) notice = APPROX_NOTICE;\n\n return { items, hasMore, notice };\n}\n\nasync function loadRecent({ page, perPage, signal }) {\n const local = useGifLibrary.getState().recents || [];\n if (local.length) {\n return page === 1\n ? { items: local.slice(), hasMore: false, notice: null }\n : { items: [], hasMore: false, notice: null };\n }\n const key = keyOf('recent', '', '', page, perPage);\n const res = await cachedRequest(\n key,\n (s) => fetchRecentGifs({ page, perPage, signal: s }).then(normalizeResult),\n signal,\n );\n return { ...res, notice: null };\n}\n\nfunction loadFavorites({ page }) {\n const favs = useGifLibrary.getState().favorites || [];\n return Promise.resolve({\n items: page === 1 ? favs.slice() : [],\n hasMore: false,\n notice: null,\n });\n}\n\n/**\n * Carga una página del feed de GIFs.\n * @param {{ source: 'trending'|'search'|'recent'|'favorites', query?: string, page?: number, perPage?: number, signal?: AbortSignal }} opts\n * @returns {Promise<{ items: any[], hasMore: boolean, notice: string|null }>}\n */\nexport async function loadGifFeed({ source, query, page = 1, perPage = 24, signal } = {}) {\n if (signal?.aborted) throw makeAbortError();\n switch (source) {\n case 'search':\n if (!String(query ?? '').trim()) return loadTrending({ page, perPage, signal });\n return loadSearch({ query, page, perPage, signal });\n case 'recent':\n return loadRecent({ page, perPage, signal });\n case 'favorites':\n return loadFavorites({ page });\n case 'trending':\n default:\n return loadTrending({ page, perPage, signal });\n }\n}\n","/**\n * Categorías del selector de GIFs (orientadas a español/LatAm).\n * Módulo puro: sin efectos secundarios. Íconos de lucide-react.\n */\nimport {\n Angry, Clock, Eye, Flame, Frown, Hand, HandHeart, Heart, Laugh, Music, PartyPopper, Smile, Sparkles, Star,\n} from 'lucide-react';\nimport { normalizeQuery } from './gifQueryExpansion.js';\n\nexport const DEFAULT_CATEGORY_ID = 'trending';\n\nexport const GIF_CATEGORIES = Object.freeze([\n { id: 'trending', label: 'Tendencias', icon: Flame, source: 'trending', query: '' },\n { id: 'memes', label: 'Memes', icon: Laugh, source: 'search', query: 'memes en español' },\n { id: 'recent', label: 'Recientes', icon: Clock, source: 'recent', query: '' },\n { id: 'favorites', label: 'Favoritos', icon: Star, source: 'favorites', query: '' },\n { id: 'love', label: 'Amor', icon: Heart, source: 'search', query: 'amor' },\n { id: 'laugh', label: 'Risas', icon: Smile, source: 'search', query: 'jajaja' },\n { id: 'sad', label: 'Tristeza', icon: Frown, source: 'search', query: 'triste' },\n { id: 'angry', label: 'Enojo', icon: Angry, source: 'search', query: 'enojado' },\n { id: 'surprise', label: 'Sorpresa', icon: Sparkles, source: 'search', query: 'sorprendido' },\n { id: 'party', label: 'Celebración', icon: PartyPopper, source: 'search', query: 'celebracion' },\n { id: 'reactions', label: 'Reacciones', icon: Eye, source: 'search', query: 'reaccion' },\n { id: 'thanks', label: 'Gracias', icon: HandHeart, source: 'search', query: 'gracias' },\n { id: 'greet', label: 'Saludos', icon: Hand, source: 'search', query: 'hola' },\n { id: 'dance', label: 'Bailar', icon: Music, source: 'search', query: 'bailar' },\n].map((c) => Object.freeze(c)));\n\n/** Sinónimos (normalizados) por id de categoría, para emparejar con KLIPY. */\nconst CATEGORY_SYNONYMS = {\n memes: ['memes', 'meme', 'memes en espanol'],\n love: ['amor', 'love', 'enamorado', 'corazon'],\n laugh: ['risa', 'risas', 'jajaja', 'laugh', 'laughing', 'funny', 'lol'],\n sad: ['triste', 'tristeza', 'sad', 'crying', 'cry', 'llorar'],\n angry: ['enojo', 'enojado', 'angry', 'mad'],\n surprise: ['sorpresa', 'sorprendido', 'surprised', 'surprise', 'wow', 'omg'],\n party: ['celebracion', 'fiesta', 'party', 'celebrate', 'celebration'],\n reactions: ['reaccion', 'reacciones', 'reaction', 'reactions'],\n thanks: ['gracias', 'thank you', 'thanks', 'thankyou'],\n greet: ['hola', 'saludos', 'hello', 'hi', 'hey'],\n dance: ['bailar', 'baile', 'dance', 'dancing'],\n};\n\nconst safeNormalize = (value) => (typeof value === 'string' ? normalizeQuery(value) : '');\n\nfunction matchKeys(category) {\n const keys = new Set([safeNormalize(category.label), safeNormalize(category.query)]);\n for (const s of CATEGORY_SYNONYMS[category.id] || []) keys.add(safeNormalize(s));\n keys.delete('');\n return keys;\n}\n\nfunction findKlipyMatch(category, klipyCategories) {\n const keys = matchKeys(category);\n return klipyCategories.find((k) => {\n if (!k || typeof k !== 'object') return false;\n return keys.has(safeNormalize(k.category)) || keys.has(safeNormalize(k.query));\n });\n}\n\n/**\n * Enriquece nuestras categorías de búsqueda con preview/klipyQuery de KLIPY.\n * No agrega categorías de KLIPY sin coincidencia. No muta las entradas.\n */\nexport function mergeKlipyCategories(categories, klipyCategories) {\n const base = Array.isArray(categories) ? categories : GIF_CATEGORIES;\n const klipy = Array.isArray(klipyCategories) ? klipyCategories : [];\n return base.map((cat) => {\n const copy = { ...cat };\n if (cat.source !== 'search' || klipy.length === 0) return copy;\n const match = findKlipyMatch(cat, klipy);\n if (!match) return copy;\n if (match.preview) copy.preview = match.preview;\n const kq = match.query || match.category;\n if (kq) copy.klipyQuery = kq;\n return copy;\n });\n}\n\nexport function findCategory(id) {\n return GIF_CATEGORIES.find((c) => c.id === id) || null;\n}\n","/* eslint-disable react/prop-types */\nimport { memo, useCallback, useEffect, useRef, useState } from 'react';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\n\nconst prefersReducedMotion = () =>\n typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nfunction GifCategoryBar({ categories = [], activeId, onSelect, disabled }) {\n const scrollerRef = useRef(null);\n const chipRefs = useRef(new Map());\n const [canPrev, setCanPrev] = useState(false);\n const [canNext, setCanNext] = useState(false);\n\n const updateOverflow = useCallback(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const max = el.scrollWidth - el.clientWidth;\n setCanPrev(el.scrollLeft > 1);\n setCanNext(max > 1 && el.scrollLeft < max - 1);\n }, []);\n\n // Track scroll position and size changes to toggle nav buttons.\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return undefined;\n updateOverflow();\n el.addEventListener('scroll', updateOverflow, { passive: true });\n let ro;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(updateOverflow);\n ro.observe(el);\n } else {\n window.addEventListener('resize', updateOverflow);\n }\n return () => {\n el.removeEventListener('scroll', updateOverflow);\n if (ro) ro.disconnect();\n else window.removeEventListener('resize', updateOverflow);\n };\n }, [updateOverflow]);\n\n useEffect(() => { updateOverflow(); }, [categories, updateOverflow]);\n\n // Vertical wheel -> horizontal scroll when content overflows.\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return undefined;\n const onWheel = (event) => {\n if (event.ctrlKey) return;\n if (el.scrollWidth <= el.clientWidth) return;\n if (Math.abs(event.deltaY) <= Math.abs(event.deltaX)) return;\n const factor = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? el.clientWidth : 1;\n const before = el.scrollLeft;\n el.scrollLeft = before + event.deltaY * factor;\n if (el.scrollLeft !== before) event.preventDefault();\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, []);\n\n // Keep active chip visible.\n useEffect(() => {\n const chip = chipRefs.current.get(activeId);\n if (chip && typeof chip.scrollIntoView === 'function') {\n chip.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: prefersReducedMotion() ? 'auto' : 'smooth' });\n }\n }, [activeId]);\n\n const scrollByPage = (dir) => {\n const el = scrollerRef.current;\n if (!el) return;\n el.scrollBy({ left: dir * el.clientWidth * 0.7, behavior: prefersReducedMotion() ? 'auto' : 'smooth' });\n };\n\n const handleKeyDown = (event) => {\n if (disabled || !categories.length) return;\n const current = categories.findIndex((c) => c.id === activeId);\n const last = categories.length - 1;\n let next;\n switch (event.key) {\n case 'ArrowRight': next = current < 0 ? 0 : (current + 1) % categories.length; break;\n case 'ArrowLeft': next = current <= 0 ? last : current - 1; break;\n case 'Home': next = 0; break;\n case 'End': next = last; break;\n default: return;\n }\n event.preventDefault();\n const target = categories[next];\n chipRefs.current.get(target.id)?.focus();\n if (target.id !== activeId) onSelect?.(target.id);\n };\n\n const hasActive = categories.some((c) => c.id === activeId);\n\n return (\n <div className=\"chat-gif-cats\">\n <button\n type=\"button\"\n className=\"chat-gif-cats__nav chat-gif-cats__nav--prev\"\n aria-label=\"Categorías anteriores\"\n onClick={() => scrollByPage(-1)}\n hidden={!canPrev}\n tabIndex={-1}\n >\n <ChevronLeft size={16} aria-hidden=\"true\" />\n </button>\n <div\n ref={scrollerRef}\n className=\"chat-gif-cats__scroller\"\n role=\"tablist\"\n aria-label=\"Categorías de GIFs\"\n onKeyDown={handleKeyDown}\n >\n {categories.map((cat, index) => {\n const active = cat.id === activeId;\n const focusable = active || (!hasActive && index === 0);\n const Icon = cat.icon;\n return (\n <button\n key={cat.id}\n ref={(node) => {\n if (node) chipRefs.current.set(cat.id, node);\n else chipRefs.current.delete(cat.id);\n }}\n type=\"button\"\n role=\"tab\"\n className={`chat-gif-cats__chip${active ? ' chat-gif-cats__chip--active' : ''}`}\n aria-selected={active}\n tabIndex={focusable ? 0 : -1}\n disabled={disabled}\n title={cat.label}\n onClick={() => { if (!active) onSelect?.(cat.id); }}\n >\n {Icon && <Icon size={15} strokeWidth={1.75} aria-hidden=\"true\" className=\"chat-gif-cats__icon\" />}\n <span className=\"chat-gif-cats__label\">{cat.label}</span>\n </button>\n );\n })}\n </div>\n <button\n type=\"button\"\n className=\"chat-gif-cats__nav chat-gif-cats__nav--next\"\n aria-label=\"Más categorías\"\n onClick={() => scrollByPage(1)}\n hidden={!canNext}\n tabIndex={-1}\n >\n <ChevronRight size={16} aria-hidden=\"true\" />\n </button>\n </div>\n );\n}\n\nexport default memo(GifCategoryBar);\n","/* eslint-disable react/prop-types */\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Loader2, Star } from 'lucide-react';\n\nconst WIDE_BREAKPOINT = 420;\nconst PREVIEW_DELAY = 350;\nconst SKELETON_RATIOS = [1.3, 0.75, 1, 1.5, 0.8, 1.1, 0.9, 1.4, 0.7, 1.2, 1, 0.85];\n\nfunction ratioOf(item) {\n const w = Number(item?.width);\n const h = Number(item?.height);\n return w > 0 && h > 0 ? h / w : 1;\n}\n\n// Greedy masonry: each entry goes to the currently shortest column (stable for appends).\nfunction distribute(list, cols, getRatio) {\n const columns = Array.from({ length: cols }, () => []);\n const heights = new Array(cols).fill(0);\n list.forEach((entry, index) => {\n let target = 0;\n for (let c = 1; c < cols; c += 1) {\n if (heights[c] < heights[target] - 0.001) target = c;\n }\n columns[target].push({ entry, index });\n heights[target] += getRatio(entry);\n });\n return columns;\n}\n\nfunction prefersReducedMotion() {\n try {\n return window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n } catch {\n return false;\n }\n}\n\nfunction isFocusVisible(el) {\n try {\n return el.matches(':focus-visible');\n } catch {\n return true;\n }\n}\n\nconst GifTile = memo(function GifTile({ item, fav, disabled, onSelect, onToggleFavorite }) {\n const [loaded, setLoaded] = useState(false);\n const [broken, setBroken] = useState(false);\n const [preview, setPreview] = useState(false);\n const [previewFailed, setPreviewFailed] = useState(false);\n const timerRef = useRef(null);\n\n const w = Number(item.width);\n const h = Number(item.height);\n const aspectRatio = w > 0 && h > 0 ? `${w} / ${h}` : '1 / 1';\n const label = item.title || 'GIF';\n const canPreview = Boolean(item.url) && item.url !== item.preview && !previewFailed;\n const showPreview = preview && canPreview && !broken;\n\n const clearTimer = () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n useEffect(() => clearTimer, []);\n\n const startPreview = (immediate) => {\n if (!canPreview || prefersReducedMotion()) return;\n clearTimer();\n if (immediate) setPreview(true);\n else timerRef.current = setTimeout(() => setPreview(true), PREVIEW_DELAY);\n };\n\n const stopPreview = () => {\n clearTimer();\n setPreview(false);\n };\n\n const handleError = () => {\n if (showPreview) {\n setPreviewFailed(true);\n setPreview(false);\n return;\n }\n setBroken(true);\n };\n\n return (\n <div\n role=\"listitem\"\n className={`chat-gif-tile${showPreview ? ' chat-gif-tile--preview' : ''}`}\n onPointerEnter={(e) => {\n if (e.pointerType === 'touch') return;\n startPreview(false);\n }}\n onPointerLeave={stopPreview}\n >\n <button\n type=\"button\"\n className=\"chat-gif-tile__pick\"\n aria-label={label}\n disabled={disabled}\n onClick={() => onSelect(item)}\n onFocus={(e) => {\n if (isFocusVisible(e.currentTarget)) startPreview(true);\n }}\n onBlur={stopPreview}\n >\n <span className=\"chat-gif-tile__media\" style={{ aspectRatio }}>\n {broken ? (\n <span className=\"chat-gif-tile__broken\" aria-hidden=\"true\">GIF</span>\n ) : (\n <img\n className={`chat-gif-tile__img${loaded ? ' chat-gif-tile__img--loaded' : ''}`}\n src={showPreview ? item.url : item.preview}\n alt={label}\n loading=\"lazy\"\n decoding=\"async\"\n onLoad={() => setLoaded(true)}\n onError={handleError}\n />\n )}\n </span>\n </button>\n {onToggleFavorite && (\n <button\n type=\"button\"\n className={`chat-gif-tile__fav${fav ? ' chat-gif-tile__fav--on' : ''}`}\n aria-pressed={fav}\n aria-label={fav ? 'Quitar de favoritos' : 'Agregar a favoritos'}\n onClick={(e) => {\n e.stopPropagation();\n onToggleFavorite(item);\n }}\n >\n <Star size={14} fill={fav ? 'currentColor' : 'none'} />\n </button>\n )}\n </div>\n );\n});\n\nfunction findNeighbor(container, current, key) {\n const buttons = Array.from(container.querySelectorAll('.chat-gif-tile__pick:not(:disabled)'));\n const from = current.getBoundingClientRect();\n const fx = from.left + from.width / 2;\n const fy = from.top + from.height / 2;\n let best = null;\n let bestScore = Infinity;\n buttons.forEach((btn) => {\n if (btn === current) return;\n const r = btn.getBoundingClientRect();\n const cx = r.left + r.width / 2;\n const cy = r.top + r.height / 2;\n const dx = cx - fx;\n const dy = cy - fy;\n let primary;\n let secondary;\n if (key === 'ArrowDown') { primary = dy; secondary = Math.abs(dx); }\n else if (key === 'ArrowUp') { primary = -dy; secondary = Math.abs(dx); }\n else if (key === 'ArrowRight') { primary = dx; secondary = Math.abs(dy); }\n else { primary = -dx; secondary = Math.abs(dy); }\n if (primary <= 1) return;\n const score = primary + secondary * 2;\n if (score < bestScore) {\n bestScore = score;\n best = btn;\n }\n });\n return best;\n}\n\nexport default function GifGrid({\n items,\n loading,\n hasMore,\n error,\n onLoadMore,\n onRetry,\n onSelect,\n onToggleFavorite,\n isFavorite,\n empty,\n disabled,\n scrollKey,\n}) {\n const list = items || [];\n const containerRef = useRef(null);\n const sentinelRef = useRef(null);\n const [cols, setCols] = useState(2);\n\n // Stable callbacks so memoized tiles don't re-render when parent handlers change identity.\n const handlersRef = useRef({ onSelect, onToggleFavorite, onLoadMore });\n handlersRef.current = { onSelect, onToggleFavorite, onLoadMore };\n const stableSelect = useCallback((item) => handlersRef.current.onSelect?.(item), []);\n const stableToggle = useCallback((item) => handlersRef.current.onToggleFavorite?.(item), []);\n\n const stateRef = useRef({ loading, error, hasMore });\n stateRef.current = { loading, error, hasMore };\n const intersectingRef = useRef(false);\n const lastFiredCountRef = useRef(-1);\n\n const requestMore = useCallback(() => {\n const s = stateRef.current;\n if (!s.hasMore || s.loading || s.error) return;\n handlersRef.current.onLoadMore?.();\n }, []);\n\n // Responsive column count.\n useEffect(() => {\n const el = containerRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return undefined;\n const ro = new ResizeObserver((entries) => {\n const width = entries[0]?.contentRect?.width ?? el.clientWidth;\n setCols(width >= WIDE_BREAKPOINT ? 3 : 2);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // Reset scroll when the query/tab changes.\n useEffect(() => {\n if (containerRef.current) containerRef.current.scrollTop = 0;\n lastFiredCountRef.current = -1;\n }, [scrollKey]);\n\n // Infinite scroll.\n useEffect(() => {\n const root = containerRef.current;\n const sentinel = sentinelRef.current;\n if (!hasMore || !root || !sentinel) return undefined;\n const observer = new IntersectionObserver(\n (entries) => {\n const visible = entries.some((e) => e.isIntersecting);\n intersectingRef.current = visible;\n if (visible) requestMore();\n },\n { root, rootMargin: '200px' },\n );\n observer.observe(sentinel);\n return () => {\n observer.disconnect();\n intersectingRef.current = false;\n };\n }, [hasMore, requestMore]);\n\n // If the sentinel is still visible after a page loads, keep filling (once per new item count).\n useEffect(() => {\n if (loading || error || !hasMore || !intersectingRef.current) return;\n if (lastFiredCountRef.current === list.length) return;\n lastFiredCountRef.current = list.length;\n requestMore();\n }, [loading, error, hasMore, list.length, requestMore]);\n\n const columns = useMemo(() => distribute(list, cols, ratioOf), [list, cols]);\n const skeletonColumns = useMemo(\n () => distribute(SKELETON_RATIOS, cols, (r) => r),\n [cols],\n );\n\n const handleKeyDown = (e) => {\n if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) return;\n const target = e.target;\n if (!(target instanceof Element) || !target.classList.contains('chat-gif-tile__pick')) return;\n const next = findNeighbor(containerRef.current, target, e.key);\n e.preventDefault();\n if (next) {\n next.focus();\n next.scrollIntoView?.({ block: 'nearest' });\n }\n };\n\n const showSkeletons = loading && list.length === 0;\n const showEmpty = !loading && !error && list.length === 0;\n const EmptyIcon = empty?.icon;\n\n return (\n <>\n {error && (\n <div className=\"chat-attachment-notice chat-gif-error\" role=\"alert\">\n {error}{' '}\n <button type=\"button\" onClick={onRetry}>Reintentar</button>\n </div>\n )}\n <div\n ref={containerRef}\n className=\"chat-gif-grid\"\n role=\"list\"\n aria-label=\"Resultados de GIFs\"\n aria-busy={loading}\n onKeyDown={handleKeyDown}\n >\n {showSkeletons &&\n skeletonColumns.map((col, c) => (\n <div className=\"chat-gif-col\" key={`sk-${c}`}>\n {col.map(({ entry, index }) => (\n <div\n key={index}\n className=\"chat-gif-skeleton\"\n style={{ aspectRatio: `1 / ${entry}` }}\n aria-hidden=\"true\"\n />\n ))}\n </div>\n ))}\n\n {!showSkeletons &&\n list.length > 0 &&\n columns.map((col, c) => (\n <div className=\"chat-gif-col\" key={c}>\n {col.map(({ entry }) => (\n <GifTile\n key={entry.id ?? entry.slug}\n item={entry}\n fav={Boolean(isFavorite?.(entry))}\n disabled={disabled}\n onSelect={stableSelect}\n onToggleFavorite={onToggleFavorite ? stableToggle : undefined}\n />\n ))}\n </div>\n ))}\n\n {showEmpty && empty && (\n <div className=\"chat-gif-empty\" role=\"status\">\n {EmptyIcon && <EmptyIcon size={24} strokeWidth={1.5} aria-hidden=\"true\" className=\"chat-gif-empty__icon\" />}\n <strong className=\"chat-gif-empty__title\">{empty.title}</strong>\n {empty.hint && <small className=\"chat-gif-empty__hint\">{empty.hint}</small>}\n </div>\n )}\n\n {hasMore && (\n <div ref={sentinelRef} className=\"chat-gif-load-more\">\n {loading && list.length > 0 && <Loader2 size={20} className=\"spin\" />}\n </div>\n )}\n </div>\n </>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useCallback, useRef, useMemo } from 'react';\nimport { X, Search, SearchX, Star, Clock, ImageOff } from 'lucide-react';\nimport { fetchGifCategories, isTrustedKlipyUrl } from '../../media/klipy/klipy';\nimport { loadGifFeed } from '../../media/gif-search/gifSearchEngine';\nimport { GIF_CATEGORIES, DEFAULT_CATEGORY_ID, mergeKlipyCategories } from '../../media/gif-search/gifCategories';\nimport { useGifLibrary } from '../../media/gif-search/gifLibrary';\nimport GifCategoryBar from './GifCategoryBar';\nimport GifGrid from './GifGrid';\nimport '../styles/GifPicker.css';\n\nconst PER_PAGE = 24;\nconst SEARCH_DEBOUNCE_MS = 300;\n\nconst isSafeGif = (gif) => Boolean(gif?.id) && isTrustedKlipyUrl(gif.url) && isTrustedKlipyUrl(gif.preview);\n\nconst getEmptyState = (source, query) => {\n if (source === 'search') {\n return { icon: SearchX, title: `Sin resultados para “${query}”`, hint: 'Prueba con otra palabra o una expresión (ej. “no puede ser”)' };\n }\n if (source === 'favorites') {\n return { icon: Star, title: 'Aún no tienes favoritos', hint: 'Toca la estrella de un GIF para guardarlo aquí' };\n }\n if (source === 'recent') {\n return { icon: Clock, title: 'Sin GIFs recientes', hint: 'Los GIFs que envíes aparecerán aquí' };\n }\n return { icon: ImageOff, title: 'No se encontraron GIFs' };\n};\n\nexport default function GifPicker({ onSelect, onClose, disabled }) {\n const [query, setQuery] = useState('');\n const [categoryId, setCategoryId] = useState(DEFAULT_CATEGORY_ID);\n const [klipyCats, setKlipyCats] = useState([]);\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(false);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState('');\n const [notice, setNotice] = useState('');\n const requestRef = useRef(null);\n const versionRef = useRef(0);\n\n const favorites = useGifLibrary((s) => s.favorites);\n const recents = useGifLibrary((s) => s.recents);\n const toggleFavorite = useGifLibrary((s) => s.toggleFavorite);\n\n const favoriteIds = useMemo(() => new Set((favorites || []).map((g) => g?.id)), [favorites]);\n const isFavorite = useCallback((item) => favoriteIds.has(typeof item === 'object' ? item?.id : item), [favoriteIds]);\n\n // Load KLIPY categories once (errors ignored)\n useEffect(() => {\n const controller = new AbortController();\n fetchGifCategories({ signal: controller.signal })\n .then((cats) => { if (!controller.signal.aborted && Array.isArray(cats)) setKlipyCats(cats); })\n .catch(() => {});\n return () => controller.abort();\n }, []);\n\n const categories = useMemo(() => mergeKlipyCategories(GIF_CATEGORIES, klipyCats), [klipyCats]);\n const activeCategory = useMemo(\n () => categories.find((c) => c.id === categoryId) ?? categories[0],\n [categories, categoryId],\n );\n\n const trimmedQuery = query.trim();\n const source = trimmedQuery ? 'search' : (activeCategory?.source ?? 'trending');\n const feedQuery = trimmedQuery || activeCategory?.query || '';\n const libraryKey = source === 'favorites' ? (favorites?.length ?? 0) : source === 'recent' ? (recents?.length ?? 0) : 0;\n\n const feedRef = useRef({ source, query: feedQuery });\n feedRef.current = { source, query: feedQuery };\n\n const loadPage = useCallback(async (pageNum, append) => {\n requestRef.current?.abort();\n const controller = new AbortController();\n requestRef.current = controller;\n const version = ++versionRef.current;\n const { source: src, query: q } = feedRef.current;\n setLoading(true);\n setError('');\n try {\n const result = await loadGifFeed({ source: src, query: q, page: pageNum, perPage: PER_PAGE, signal: controller.signal });\n if (version !== versionRef.current) return;\n const safe = (result?.items || []).filter(isSafeGif);\n setItems((prev) => [...new Map([...(append ? prev : []), ...safe].map((g) => [g.id, g])).values()]);\n setHasMore(Boolean(result?.hasMore));\n setNotice(result?.notice || '');\n setPage(pageNum);\n } catch (err) {\n if (err?.name !== 'AbortError' && version === versionRef.current) setError('Error cargando GIFs. Intenta de nuevo.');\n } finally {\n if (version === versionRef.current) setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n requestRef.current?.abort();\n versionRef.current++;\n setItems([]);\n setHasMore(false);\n setError('');\n setNotice('');\n setLoading(true);\n const delay = source === 'search' ? SEARCH_DEBOUNCE_MS : 0;\n const timer = setTimeout(() => loadPage(1, false), delay);\n return () => { clearTimeout(timer); requestRef.current?.abort(); };\n }, [source, feedQuery, libraryKey, loadPage]);\n\n const handleLoadMore = useCallback(() => {\n if (loading || !hasMore || error) return;\n loadPage(page + 1, true);\n }, [loading, hasMore, error, page, loadPage]);\n\n const handleRetry = useCallback(() => {\n if (items.length) loadPage(page + 1, true);\n else loadPage(1, false);\n }, [items.length, page, loadPage]);\n\n const handleCategorySelect = useCallback((id) => {\n setQuery('');\n setCategoryId(id);\n }, []);\n\n const handleKeyDown = (e) => {\n if (e.key === 'Escape' && query) {\n e.preventDefault();\n e.stopPropagation();\n setQuery('');\n }\n };\n\n const handleSelect = (gif) => {\n if (disabled || !gif || !isTrustedKlipyUrl(gif.url)) return;\n onSelect?.({\n kind: 'gif',\n id: gif.id,\n slug: gif.slug,\n title: gif.title,\n preview: gif.preview,\n url: gif.url,\n name: gif.title || 'GIF',\n type: 'image/gif',\n size: 0,\n // KLIPY share is registered by the chat only after the message is sent.\n shareQuery: source === 'search' ? trimmedQuery : (source === 'trending' ? '' : feedQuery),\n });\n useGifLibrary.getState().addRecent(gif);\n onClose?.();\n };\n\n const handleToggleFavorite = useCallback((item) => {\n if (disabled || !item) return;\n toggleFavorite(item);\n }, [disabled, toggleFavorite]);\n\n const empty = getEmptyState(source, trimmedQuery);\n\n return (\n <div className=\"chat-gif-picker chat-gif-picker--smart\" role=\"dialog\" aria-label=\"Buscar GIFs\">\n <div className=\"chat-gif-picker-header\">\n <strong>Buscar GIFs</strong>\n <button type=\"button\" className=\"chat-btn\" aria-label=\"Cerrar selector GIF\" onClick={onClose}><X size={16} /></button>\n </div>\n <div className=\"chat-gif-search\">\n <Search size={18} aria-hidden=\"true\" />\n <input\n type=\"search\"\n autoFocus\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Busca memes, reacciones… (ej. cuánta bendición)\"\n disabled={disabled}\n aria-label=\"Buscar GIFs\"\n autoComplete=\"off\"\n enterKeyHint=\"search\"\n />\n {query && (\n <button\n type=\"button\"\n className=\"chat-gif-search__clear\"\n aria-label=\"Borrar búsqueda\"\n onClick={() => setQuery('')}\n disabled={disabled}\n >\n <X size={14} aria-hidden=\"true\" />\n </button>\n )}\n </div>\n <GifCategoryBar\n categories={categories}\n activeId={trimmedQuery ? null : activeCategory?.id ?? null}\n onSelect={handleCategorySelect}\n disabled={disabled}\n />\n {notice && <p className=\"chat-gif-notice\" role=\"status\">{notice}</p>}\n <GifGrid\n items={items}\n loading={loading}\n hasMore={hasMore}\n error={error}\n onLoadMore={handleLoadMore}\n onRetry={handleRetry}\n onSelect={handleSelect}\n onToggleFavorite={handleToggleFavorite}\n isFavorite={isFavorite}\n empty={empty}\n disabled={disabled}\n scrollKey={`${source}:${feedQuery}`}\n />\n <p className=\"chat-gif-attribution\">\n Powered by <a href=\"https://klipy.com\" target=\"_blank\" rel=\"noopener noreferrer\">KLIPY</a>\n </p>\n </div>\n );\n}\n","import { getKlipyApiRoot, isTrustedKlipyUrl } from './klipy.js';\nimport { getKlipyCustomerId } from './klipyCustomer.js';\nimport { STICKER_NAME_PREFIX } from '../../core/extras/messageExtras.js';\n\nconst getStickersUrl = () => `${getKlipyApiRoot()}/stickers`;\nconst PREVIEW_SIZES = ['sm', 'xs', 'md', 'hd'];\nconst FULL_SIZES = ['md', 'hd', 'sm'];\nconst FORMATS = ['gif', 'webp'];\nconst ERROR_MESSAGE = 'Error consultando KLIPY';\n\nlet categoriesCache = null;\n\nexport function getStickerCustomerId() {\n return getKlipyCustomerId();\n}\n\nconst pickMedia = (file, sizes) => {\n for (const size of sizes) {\n for (const format of FORMATS) {\n const media = file?.[size]?.[format];\n if (isTrustedKlipyUrl(media?.url)) return media;\n }\n }\n return null;\n};\n\nconst normalizeItem = (item) => {\n if (!item || item.type === 'ad') return null;\n const full = pickMedia(item.file, FULL_SIZES);\n const preview = pickMedia(item.file, PREVIEW_SIZES) || full;\n if (!full || !preview) return null;\n return {\n id: item.id,\n slug: item.slug,\n title: item.title || '',\n preview: preview.url,\n url: full.url,\n width: Number(full.width) || null,\n height: Number(full.height) || null,\n };\n};\n\nconst request = async (path, params, signal) => {\n const query = params ? `?${new URLSearchParams(params)}` : '';\n const response = await fetch(`${getStickersUrl()}${path}${query}`, { signal });\n if (!response.ok) throw new Error(ERROR_MESSAGE);\n return response.json();\n};\n\nconst toPage = (json, perPage) => {\n const raw = Array.isArray(json?.data?.data) ? json.data.data : [];\n const items = raw.map(normalizeItem).filter(Boolean);\n const hasNext = json?.data?.has_next;\n return {\n items,\n hasMore: typeof hasNext === 'boolean' ? hasNext : raw.length >= perPage,\n };\n};\n\nconst pageParams = (page, perPage) => ({\n page: String(page),\n per_page: String(perPage),\n});\n\nexport async function fetchTrendingStickers({ page = 1, perPage = 24, signal } = {}) {\n const json = await request('/trending', {\n ...pageParams(page, perPage),\n customer_id: getStickerCustomerId(),\n }, signal);\n return toPage(json, perPage);\n}\n\nexport async function searchStickers({ query, page = 1, perPage = 24, signal } = {}) {\n const q = String(query ?? '').trim();\n if (!q) return fetchTrendingStickers({ page, perPage, signal });\n const json = await request('/search', {\n ...pageParams(page, perPage),\n q,\n customer_id: getStickerCustomerId(),\n }, signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchRecentStickers({ page = 1, perPage = 24, signal } = {}) {\n const customerId = encodeURIComponent(getStickerCustomerId());\n const json = await request(`/recent/${customerId}`, pageParams(page, perPage), signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchStickerCategories({ signal } = {}) {\n if (categoriesCache) return categoriesCache;\n const json = await request('/categories', null, signal);\n const raw = json?.data?.categories ?? json?.data?.data ?? json?.data ?? [];\n const list = Array.isArray(raw) ? raw : [];\n const categories = list\n .map((entry) => {\n if (typeof entry === 'string') {\n const name = entry.trim();\n return name ? { category: name, query: name, preview: null } : null;\n }\n const category = String(entry?.category ?? entry?.name ?? entry?.title ?? '').trim();\n const query = String(entry?.query ?? entry?.q ?? category).trim();\n if (!category || !query) return null;\n const previewUrl = entry?.preview_url ?? entry?.preview ?? entry?.image;\n return { category, query, preview: isTrustedKlipyUrl(previewUrl) ? previewUrl : null };\n })\n .filter(Boolean);\n categoriesCache = categories;\n return categories;\n}\n\nexport async function shareSticker(slug, { query } = {}) {\n if (!slug) return false;\n try {\n const body = { customer_id: getStickerCustomerId() };\n const q = String(query ?? '').trim();\n if (q) body.q = q;\n const response = await fetch(`${getStickersUrl()}/share/${encodeURIComponent(slug)}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport function toStickerAttachment(item) {\n return {\n kind: 'gif',\n id: item.id,\n slug: item.slug,\n title: item.title,\n preview: item.preview,\n url: item.url,\n name: STICKER_NAME_PREFIX + (item.title || 'Sticker').slice(0, 140),\n type: 'image/gif',\n size: 0,\n sticker: true,\n };\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { X, Loader2, Search } from 'lucide-react';\nimport {\n fetchTrendingStickers,\n searchStickers,\n fetchStickerCategories,\n fetchRecentStickers,\n toStickerAttachment,\n} from '../../media/klipy/klipyStickers';\nimport '../styles/StickerPicker.css';\n\nconst PER_PAGE = 24;\nconst SEARCH_DEBOUNCE_MS = 300;\n\nconst EMPTY_TEXT = {\n trending: 'No hay stickers en tendencia',\n recent: 'No hay stickers recientes todavía',\n category: 'No se encontraron stickers',\n search: 'No se encontraron stickers',\n};\n\nconst requestFor = (mode, term, page, signal) => {\n if (mode === 'recent') return fetchRecentStickers({ page, perPage: PER_PAGE, signal });\n if (mode === 'trending') return fetchTrendingStickers({ page, perPage: PER_PAGE, signal });\n return searchStickers({ query: term, page, perPage: PER_PAGE, signal });\n};\n\nexport default function StickerPicker({ onSelect, onClose, disabled }) {\n const [query, setQuery] = useState('');\n const [mode, setMode] = useState('trending');\n const [activeCategory, setActiveCategory] = useState(null);\n const [categories, setCategories] = useState([]);\n const [stickers, setStickers] = useState([]);\n const [loading, setLoading] = useState(false);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState('');\n const [previewItem, setPreviewItem] = useState(null);\n const gridRef = useRef(null);\n const requestRef = useRef(null);\n const versionRef = useRef(0);\n const loadMoreRef = useRef(null);\n const prevTabRef = useRef({ mode: 'trending', category: null });\n\n const term = mode === 'search'\n ? query.trim()\n : mode === 'category' ? (activeCategory?.query || '') : '';\n\n const loadStickers = useCallback(async (loadMode, loadTerm, pageNum = 1, append = false) => {\n requestRef.current?.abort();\n const controller = new AbortController();\n requestRef.current = controller;\n const version = ++versionRef.current;\n setLoading(true);\n setError('');\n try {\n const { items = [], hasMore: more = false } = await requestFor(loadMode, loadTerm, pageNum, controller.signal) || {};\n if (version !== versionRef.current) return;\n setStickers(prev => [...new Map([...(append ? prev : []), ...items].map(item => [item.id, item])).values()]);\n setHasMore(Boolean(more) && items.length > 0);\n setPage(pageNum);\n } catch (err) {\n if (err?.name !== 'AbortError' && version === versionRef.current) {\n setError(loadMode === 'recent' ? 'Recientes no disponible.' : 'Error cargando stickers. Intenta de nuevo.');\n setHasMore(false);\n }\n } finally {\n if (version === versionRef.current) setLoading(false);\n }\n }, []);\n\n // Categories load once.\n useEffect(() => {\n const controller = new AbortController();\n fetchStickerCategories({ signal: controller.signal })\n .then(list => { if (Array.isArray(list)) setCategories(list.filter(c => c?.query)); })\n .catch(() => {});\n return () => controller.abort();\n }, []);\n\n // Reload whenever mode/term changes; only searches are debounced.\n useEffect(() => {\n requestRef.current?.abort();\n versionRef.current++;\n setStickers([]);\n setHasMore(false);\n setPreviewItem(null);\n setError('');\n setLoading(true);\n const timer = setTimeout(() => {\n gridRef.current?.scrollTo({ top: 0 });\n loadStickers(mode, term, 1, false);\n }, mode === 'search' ? SEARCH_DEBOUNCE_MS : 0);\n return () => { clearTimeout(timer); requestRef.current?.abort(); };\n }, [mode, term, loadStickers]);\n\n // Infinite scroll.\n useEffect(() => {\n if (!hasMore || loading || error) return undefined;\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadStickers(mode, term, page + 1, true);\n }, { root: gridRef.current, rootMargin: '80px' });\n if (loadMoreRef.current) observer.observe(loadMoreRef.current);\n return () => observer.disconnect();\n }, [hasMore, loading, error, page, mode, term, loadStickers]);\n\n const handleQueryChange = (value) => {\n setQuery(value);\n if (value.trim()) {\n if (mode !== 'search') {\n prevTabRef.current = { mode, category: activeCategory };\n setMode('search');\n }\n } else if (mode === 'search') {\n setActiveCategory(prevTabRef.current.category);\n setMode(prevTabRef.current.mode || 'trending');\n }\n };\n\n const selectTab = (nextMode, category = null) => {\n setQuery('');\n setActiveCategory(category);\n setMode(nextMode);\n };\n\n const handleSelect = (item) => {\n if (disabled || !item) return;\n // KLIPY share is registered by the chat only after the message is sent.\n onSelect?.({ ...toStickerAttachment(item), shareQuery: term || '' });\n onClose?.();\n };\n\n const handleGridKeyDown = (e) => {\n const keys = ['ArrowRight', 'ArrowLeft', 'ArrowDown', 'ArrowUp', 'Home', 'End'];\n if (!keys.includes(e.key)) return;\n const items = Array.from(gridRef.current?.querySelectorAll('.chat-sticker-item') || []);\n const index = items.indexOf(document.activeElement);\n if (index === -1 || !items.length) return;\n const firstTop = items[0].offsetTop;\n const columns = Math.max(1, items.findIndex(el => el.offsetTop !== firstTop) === -1\n ? items.length\n : items.findIndex(el => el.offsetTop !== firstTop));\n let next = index;\n if (e.key === 'ArrowRight') next = index + 1;\n else if (e.key === 'ArrowLeft') next = index - 1;\n else if (e.key === 'ArrowDown') next = index + columns;\n else if (e.key === 'ArrowUp') next = index - columns;\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = items.length - 1;\n e.preventDefault();\n next = Math.min(items.length - 1, Math.max(0, next));\n items[next]?.focus();\n };\n\n const isTabSelected = (tabMode, category = null) => (\n mode === tabMode && (tabMode !== 'category' || activeCategory?.query === category?.query)\n );\n\n return (\n <div className=\"chat-gif-picker chat-sticker-picker\" role=\"dialog\" aria-label=\"Buscar stickers\">\n <div className=\"chat-gif-picker-header\">\n <strong>Stickers</strong>\n <button type=\"button\" className=\"chat-btn\" aria-label=\"Cerrar selector de stickers\" onClick={onClose}><X size={16} /></button>\n </div>\n <div className=\"chat-gif-search\">\n <Search size={18} aria-hidden=\"true\" />\n <input\n type=\"search\"\n autoFocus\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder=\"Buscar stickers (ej. hola, gato, gracias)...\"\n disabled={disabled}\n aria-label=\"Buscar stickers\"\n />\n </div>\n <div className=\"chat-sticker-tabs\" role=\"tablist\" aria-label=\"Categorías de stickers\">\n <button\n type=\"button\"\n role=\"tab\"\n className=\"chat-sticker-tab\"\n aria-selected={isTabSelected('trending')}\n onClick={() => selectTab('trending')}\n disabled={disabled}\n >\n Tendencias\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n className=\"chat-sticker-tab\"\n aria-selected={isTabSelected('recent')}\n onClick={() => selectTab('recent')}\n disabled={disabled}\n >\n Recientes\n </button>\n {categories.map((cat) => (\n <button\n key={cat.query}\n type=\"button\"\n role=\"tab\"\n className=\"chat-sticker-tab chat-sticker-chip\"\n aria-selected={isTabSelected('category', cat)}\n onClick={() => selectTab('category', cat)}\n disabled={disabled}\n title={cat.category}\n >\n {cat.preview && <img src={cat.preview} alt=\"\" aria-hidden=\"true\" loading=\"lazy\" />}\n <span>{cat.category}</span>\n </button>\n ))}\n </div>\n {error && (\n <div className=\"chat-attachment-notice\" role=\"alert\">\n {error}{' '}\n <button type=\"button\" onClick={() => loadStickers(mode, term, stickers.length ? page + 1 : 1, stickers.length > 0)}>Reintentar</button>\n </div>\n )}\n <div\n ref={gridRef}\n className=\"chat-gif-grid chat-sticker-grid\"\n role=\"list\"\n aria-label=\"Resultados de stickers\"\n onKeyDown={handleGridKeyDown}\n >\n {stickers.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n className=\"chat-sticker-item\"\n role=\"listitem\"\n onClick={() => handleSelect(item)}\n onMouseEnter={() => setPreviewItem(item)}\n onFocus={() => setPreviewItem(item)}\n disabled={disabled}\n aria-label={item.title || 'Sticker'}\n >\n <img src={item.preview} alt={item.title || 'Sticker'} loading=\"lazy\" />\n </button>\n ))}\n {(hasMore || loading) && (\n <div ref={loadMoreRef} className=\"chat-gif-load-more\" aria-hidden=\"true\">\n {loading && <Loader2 size={24} className=\"spin\" />}\n </div>\n )}\n {!stickers.length && !loading && !error && (\n <p className=\"chat-gif-empty\">{EMPTY_TEXT[mode]}</p>\n )}\n </div>\n <div className=\"chat-sticker-preview\" aria-live=\"polite\">\n {previewItem ? (\n <>\n <img src={previewItem.url || previewItem.preview} alt={previewItem.title || 'Sticker'} />\n <span>{previewItem.title || 'Sticker'}</span>\n </>\n ) : (\n <span className=\"chat-sticker-preview-hint\">Pasa el cursor sobre un sticker para verlo</span>\n )}\n </div>\n <p className=\"chat-gif-attribution\">\n Powered by <a href=\"https://klipy.com\" target=\"_blank\" rel=\"noopener noreferrer\">KLIPY</a>\n </p>\n </div>\n );\n}\n","// Exact, familiar emoticons take priority over name searches, without a catalog load.\nconst faces = [\n [[':)', ':-)'], '🙂', 'slightly_smiling_face', 'Cara sonriente'],\n [[':D', ':-D'], '😄', 'smile', 'Sonrisa grande'],\n [[':O', ':-O'], '😮', 'open_mouth', 'Cara de asombro'],\n [[':/', ':-/', ':\\\\', ':-\\\\'], '😕', 'confused', 'Cara confundida'],\n [[':(', ':-('], '🙁', 'slightly_frowning_face', 'Cara triste'],\n [[';)', ';-)'], '😉', 'wink', 'Guiño'],\n [[':P', ':-P'], '😛', 'stuck_out_tongue', 'Sacando la lengua'],\n [[':*', ':-*'], '😘', 'kissing_heart', 'Beso'],\n [[':|', ':-|'], '😐', 'neutral_face', 'Cara neutral'],\n [[\":'(\"], '😢', 'cry', 'Cara llorando'],\n [['<3'], '❤️', 'heart', 'Corazón'],\n];\nconst shortcuts = new Map(faces.flatMap(([aliases, emoji, shortcode, label]) => aliases.map(alias => [alias.toLowerCase(), { emoji, shortcode, label, source: 'unicode' }])));\n\nexport function findEmojiToken(text, cursor = text.length) {\n const prefix = text.slice(0, cursor);\n const match = /(^|[^\\p{L}\\p{N}_/:\\\\])([:;<][^\\s]{1,32})$/u.exec(prefix);\n if (!match) return null;\n const token = match[2];\n const start = match.index + match[1].length;\n const face = shortcuts.get(token.toLowerCase());\n if (face) return { start, shortcode: token.slice(1), emoticon: { ...face, emoticon: token } };\n if (/^:[\\p{L}\\p{N}_+\\p{M}-]{1,32}$/u.test(token)) return { start, shortcode: token.slice(1) };\n return null;\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState, useCallback, useId, useMemo } from 'react';\nimport MessageText from './MessageText';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nimport { searchCustomEmojis } from '../../media/emoji/customEmojiCatalog';\nimport { searchEmojiShortcodes, applySkinTone } from '../../media/emoji/emojiShortcodes';\nimport { useEmojiPreferences } from '../../media/emoji/emojiPreferences';\nimport { useEmojiDataReady } from '../../media/emoji/useEmojiData';\nimport { findEmojiToken } from '../../media/emoji/emojiAutocompleteToken.js';\nimport '../styles/EmojiPicker.css';\n\nconst RESULT_LIMIT = 8;\nconst RECENT_POOL_LIMIT = 48;\n\nconst recentValue = (recent) => (typeof recent === 'string' ? recent : recent?.emoji || '');\nconst stripVariation = (text) => String(text || '').replace(/️/g, '');\n\nconst foldText = (text) => String(text).normalize('NFD').replace(/\\p{M}/gu, '').toLowerCase();\n\n// Wrap the matched prefix of the shortcode in <mark>.\nfunction HighlightedShortcode({ shortcode, query }) {\n const folded = foldText(shortcode);\n const q = foldText(query);\n if (q && folded.startsWith(q)) {\n return <>:<mark className=\"chat-emoji-autocomplete-match\">{shortcode.slice(0, q.length)}</mark>{shortcode.slice(q.length)}:</>;\n }\n const at = q ? folded.indexOf(q) : -1;\n if (at > 0 && /[_+-]/.test(folded[at - 1])) {\n return <>:{shortcode.slice(0, at)}<mark className=\"chat-emoji-autocomplete-match\">{shortcode.slice(at, at + q.length)}</mark>{shortcode.slice(at + q.length)}:</>;\n }\n return <>:{shortcode}:</>;\n}\n\nexport default function EmojiAutocomplete({\n textareaRef,\n value,\n onInsert,\n onClose,\n isOpen\n}) {\n const customRecords = useCustomEmojis();\n const [suggestions, setSuggestions] = useState([]);\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [query, setQuery] = useState('');\n const dropdownRef = useRef(null);\n const shortcodeStartRef = useRef(-1);\n const prefs = useEmojiPreferences() || {};\n const { skinTone, recents, addRecent } = prefs;\n // Mounted with the composer: starts the lazy emoji catalog load early (also used by resolveEmojiShortcode).\n const emojiReady = useEmojiDataReady();\n const baseId = useId().replace(/:/g, '');\n const listId = `chat-emoji-ac-${baseId}`;\n const optionId = (index) => `${listId}-opt-${index}`;\n\n const valueFor = useCallback((record) => (\n record.source === 'custom' ? record.emoji : (applySkinTone(record, skinTone) || record.emoji)\n ), [skinTone]);\n\n const recentList = useMemo(\n () => (Array.isArray(recents) ? recents.map(recentValue).filter(Boolean) : []),\n [recents]\n );\n\n // Update suggestions based on current textarea state\n useEffect(() => {\n if (!isOpen || !textareaRef.current) {\n setSuggestions([]);\n return;\n }\n\n const textarea = textareaRef.current;\n const cursorPos = textarea.selectionStart;\n const found = findEmojiToken(value, cursorPos);\n\n if (!found || found.shortcode.length === 0) {\n setSuggestions([]);\n onClose();\n return;\n }\n\n const search = (query, limit) => [...searchCustomEmojis(customRecords, query), ...searchEmojiShortcodes(query, { limit })].slice(0, limit);\n let results;\n if (found.emoticon) {\n results = [found.emoticon];\n } else if (found.shortcode.length === 1 && recentList.length) {\n // Boost matching recents (most recent first) for very short queries.\n const pool = search(found.shortcode, RECENT_POOL_LIMIT);\n const rank = (record) => {\n const candidates = [stripVariation(record.emoji), stripVariation(valueFor(record))];\n const idx = recentList.findIndex((recent) => candidates.includes(stripVariation(recent)));\n return idx === -1 ? Infinity : idx;\n };\n const ranked = pool.map((record, order) => ({ record, order, recent: rank(record) }));\n ranked.sort((a, b) => (a.recent === b.recent ? a.order - b.order : a.recent - b.recent));\n results = ranked.slice(0, RESULT_LIMIT).map(({ record }) => record);\n } else {\n results = search(found.shortcode, RESULT_LIMIT);\n }\n\n if (!results.length) {\n setSuggestions([]);\n onClose();\n return;\n }\n\n shortcodeStartRef.current = found.start;\n setQuery(found.shortcode);\n setSuggestions(results);\n setSelectedIndex(0);\n }, [value, isOpen, textareaRef, onClose, recentList, valueFor, emojiReady, customRecords]);\n\n const insertEmoji = useCallback((record) => {\n const textarea = textareaRef.current;\n if (!textarea || !record) return;\n const start = shortcodeStartRef.current;\n if (start < 0) return;\n const end = textarea.selectionStart;\n const emoji = valueFor(record);\n\n onInsert(value.substring(0, start) + emoji + value.substring(end));\n addRecent?.(emoji);\n\n setTimeout(() => {\n textarea.focus();\n const newPos = start + emoji.length;\n textarea.setSelectionRange(newPos, newPos);\n }, 0);\n\n onClose();\n }, [textareaRef, value, onInsert, onClose, addRecent, valueFor]);\n\n const active = isOpen && suggestions.length > 0;\n\n // Keyboard navigation in capture phase so it beats the composer's Enter-to-send.\n useEffect(() => {\n const node = textareaRef.current;\n if (!node || !active) return undefined;\n const count = suggestions.length;\n const stop = (event) => { event.preventDefault(); event.stopPropagation(); };\n const handleKeyDown = (event) => {\n if (event.isComposing || event.keyCode === 229) return;\n switch (event.key) {\n case 'ArrowDown':\n stop(event);\n setSelectedIndex((prev) => (prev + 1) % count);\n break;\n case 'ArrowUp':\n stop(event);\n setSelectedIndex((prev) => (prev - 1 + count) % count);\n break;\n case 'Home':\n stop(event);\n setSelectedIndex(0);\n break;\n case 'End':\n stop(event);\n setSelectedIndex(count - 1);\n break;\n case 'Enter':\n case 'Tab':\n if (event.shiftKey && event.key === 'Enter') return;\n stop(event);\n insertEmoji(suggestions[selectedIndex] || suggestions[0]);\n break;\n case 'Escape':\n stop(event);\n onClose();\n break;\n case 'ArrowLeft':\n case 'ArrowRight':\n onClose();\n break;\n default:\n break;\n }\n };\n const dismiss = () => onClose();\n node.addEventListener('keydown', handleKeyDown, true);\n node.addEventListener('click', dismiss);\n return () => {\n node.removeEventListener('keydown', handleKeyDown, true);\n node.removeEventListener('click', dismiss);\n };\n }, [textareaRef, active, suggestions, selectedIndex, insertEmoji, onClose]);\n\n // ARIA combobox wiring on the textarea while open.\n useEffect(() => {\n const node = textareaRef.current;\n if (!node) return undefined;\n if (active) {\n node.setAttribute('aria-expanded', 'true');\n node.setAttribute('aria-controls', listId);\n node.setAttribute('aria-autocomplete', 'list');\n node.setAttribute('aria-activedescendant', `${listId}-opt-${selectedIndex}`);\n } else {\n node.setAttribute('aria-expanded', 'false');\n node.removeAttribute('aria-controls');\n node.removeAttribute('aria-activedescendant');\n node.removeAttribute('aria-autocomplete');\n }\n return undefined;\n }, [textareaRef, active, listId, selectedIndex]);\n\n useEffect(() => () => {\n const node = textareaRef.current;\n if (!node) return;\n node.removeAttribute('aria-expanded');\n node.removeAttribute('aria-controls');\n node.removeAttribute('aria-activedescendant');\n node.removeAttribute('aria-autocomplete');\n }, [textareaRef]);\n\n useEffect(() => {\n if (!active) return;\n dropdownRef.current?.querySelector('[aria-selected=\"true\"]')?.scrollIntoView({ block: 'nearest', behavior: 'auto' });\n }, [selectedIndex, active, suggestions]);\n\n if (!active) return null;\n\n return (\n <div ref={dropdownRef} className=\"chat-emoji-autocomplete chat-emoji-autocomplete--modern\">\n <div className=\"chat-emoji-autocomplete-hint\">\n <span>Emojis que coinciden con <strong>:{query}</strong></span>\n <span aria-hidden=\"true\"><kbd>↑</kbd><kbd>↓</kbd> navegar · <kbd>Enter</kbd>/<kbd>Tab</kbd> elegir · <kbd>Esc</kbd> cerrar</span>\n </div>\n <div className=\"chat-emoji-autocomplete-list\" id={listId} role=\"listbox\" aria-label=\"Sugerencias de emoji\">\n {suggestions.map((suggestion, index) => {\n const selected = index === selectedIndex;\n const display = valueFor(suggestion);\n return (\n <div\n key={`${suggestion.source}-${suggestion.shortcode}-${index}`}\n id={optionId(index)}\n className={`chat-emoji-autocomplete-item${selected ? ' selected' : ''}`}\n role=\"option\"\n aria-selected={selected}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => insertEmoji(suggestion)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n <span className=\"chat-emoji-autocomplete-emoji\" aria-hidden=\"true\"><MessageText text={display} /></span>\n <span className=\"chat-emoji-autocomplete-text\">\n <span className=\"chat-emoji-autocomplete-shortcode\">{suggestion.emoticon || <HighlightedShortcode shortcode={suggestion.shortcode} query={query} />}</span>\n {suggestion.label && <span className=\"chat-emoji-autocomplete-label\">{suggestion.label}</span>}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { Paperclip, Smile, Clapperboard, Send, X, Mic, Square, GripHorizontal, Loader2, Gamepad2, Anchor, CircleDot, Box, Check, Sticker, Crosshair, Flag } from 'lucide-react';\nimport { EffectPicker } from '../../effects/ChatEffects.jsx';\nimport EmojiPicker from './EmojiPicker';\nimport MediaPreview from './MediaPreview';\nimport useVoiceRecorder from '../hooks/useVoiceRecorder';\nimport GifPicker from './GifPicker';\nimport StickerPicker from './StickerPicker';\nimport EmojiAutocomplete from './EmojiAutocomplete';\nimport { resolveEmojiShortcode } from '../../media/emoji/emojiShortcodes';\nimport { findEmojiToken } from '../../media/emoji/emojiAutocompleteToken.js';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nimport { isStickerAttachment } from '../../core/extras/messageExtras';\nimport '../styles/gameMenu.css';\n// Loaded eagerly as on master: the Battleship preview overlay renders in the shell before its lazy chunk.\nimport '../../games/battleship/battleship.css';\n\nconst DEFAULT_GAME_TYPES = ['connect4', 'battleship'];\nconst GAME_MENU = [\n { type: 'connect4', label: 'Conecta 4', Icon: CircleDot },\n { type: 'battleship', label: 'Batalla Naval', Icon: Anchor },\n { type: 'tanks', label: 'Tanques de guerra', Icon: Crosshair },\n { type: 'tanks_live', label: 'Tanques LIVE 3D', Icon: Crosshair },\n { type: 'racing_live', label: 'Carreras LIVE 🏎️', Icon: Flag },\n];\n// Carreras LIVE opens a class submenu; ids must match src/games/racing-live/logic/classes.js.\nconst RACE_CLASS_MENU = [\n { id: '50cc', hint: '~80 km/h' }, { id: '100cc', hint: '~130 km/h' }, { id: '200cc', hint: '~200 km/h · recomendada' },\n { id: '400cc', hint: '~300 km/h' }, { id: '500cc', hint: '~380 km/h' },\n];\n// Tanques LIVE opens map → lives submenus; ids must match src/games/tanks-live/logic/maps.js.\nconst TANK_MAP_MENU = [\n { id: 'random', label: 'Aleatorio 🎲', hint: 'recomendado' }, { id: 'meadow', label: 'Pradera 🌿', hint: 'clásico' },\n { id: 'forest', label: 'Bosque 🌲', hint: 'combate cercano' }, { id: 'desert', label: 'Desierto 🏜️', hint: 'abierto' },\n { id: 'ruins', label: 'Ciudad en ruinas 🏚️', hint: 'pasillos' }, { id: 'arctic', label: 'Ártico ❄️', hint: 'bloques de hielo' },\n];\nconst TANK_LIVES_MENU = [{ lives: 1, hint: 'muerte súbita' }, { lives: 3, hint: 'recomendado' }, { lives: 5, hint: 'partida larga' }];\n\nexport default function MessageComposer({ onSendEffect, value, onChange, onSend, disabled, attachments = [], attachmentError, sending = false, onAddAttachment, onRemoveAttachment, reply, onCancelReply, onInviteGame, gameInviteDisabled, gameTypes = DEFAULT_GAME_TYPES, onOpenBattleshipPreview, editing = null, onStartEditLast, onCancelEdit }) {\n const customEmojis = useCustomEmojis();\n const textareaRef = useRef(null);\n const composerRef = useRef(null);\n const [pickerHeight, setPickerHeight] = useState(520);\n const [pickerAvailableHeight, setPickerAvailableHeight] = useState(520);\n const pickerResizeRef = useRef(null);\n const fileInputRef = useRef(null);\n const gameMenuRef = useRef(null);\n const gameButtonRef = useRef(null);\n const [popover, setPopover] = useState(null);\n const [raceMenu, setRaceMenu] = useState(false);\n const [tankMenu, setTankMenu] = useState(null); // null | 'map' | 'lives'\n const [tankMap, setTankMap] = useState('random');\n const [autocompleteOpen, setAutocompleteOpen] = useState(false);\n const handleAutocompleteClose = useCallback(() => setAutocompleteOpen(false), []);\n const handleAutocompleteInsert = useCallback((next) => onChange(next), [onChange]);\n const voice = useVoiceRecorder(onAddAttachment);\n const recording = voice.status !== 'idle';\n const sendingMedia = attachments[0];\n const sendingTitle = isStickerAttachment(sendingMedia) ? 'Enviando sticker…'\n : sendingMedia?.kind === 'gif' ? 'Enviando GIF…'\n : sendingMedia?.type?.startsWith('audio/') ? 'Enviando audio…'\n : sendingMedia ? 'Enviando archivo…' : 'Enviando mensaje…';\n useEffect(() => { if (sending) { setPopover(null); setAutocompleteOpen(false); } }, [sending]);\n const canSend = editing ? !disabled && Boolean(value.trim()) : !disabled && (attachments.length > 0 || Boolean(value.trim()));\n const editingId = editing?.messageId;\n const pickerKind = popover === 'gif' || popover === 'sticker' ? popover : null;\n\n useEffect(() => { if (reply) { setPopover(null); setAutocompleteOpen(false); textareaRef.current?.focus(); } }, [reply]);\n\n // Entering edit mode: the parent fills `value`; focus and place the caret at the end.\n useEffect(() => {\n if (editingId == null) return undefined;\n setPopover(null); setAutocompleteOpen(false);\n const frame = requestAnimationFrame(() => { const node = textareaRef.current; if (!node) return; node.focus(); const end = node.value.length; node.setSelectionRange(end, end); });\n return () => cancelAnimationFrame(frame);\n }, [editingId]);\n\n useEffect(() => {\n const node = textareaRef.current;\n if (node) { node.style.height = 'auto'; node.style.height = `${Math.min(node.scrollHeight, 144)}px`; }\n }, [value]);\n\n useEffect(() => {\n const composer = composerRef.current;\n const parent = composer?.parentElement;\n if (!composer || !parent || (!popover && !autocompleteOpen)) return undefined;\n const resize = () => setPickerAvailableHeight(Math.max(60,\n composer.getBoundingClientRect().top - parent.getBoundingClientRect().top - 8));\n const observer = new ResizeObserver(resize);\n observer.observe(parent);\n observer.observe(composer);\n resize();\n return () => observer.disconnect();\n }, [popover, autocompleteOpen]);\n\n // Games menu: focus the first entry on open, close on outside pointer.\n useEffect(() => {\n if (popover !== 'games') { setRaceMenu(false); setTankMenu(null); return undefined; }\n gameMenuRef.current?.querySelector('[role=\"menuitem\"]:not(:disabled)')?.focus();\n const close = (event) => {\n if (gameMenuRef.current?.contains(event.target) || gameButtonRef.current?.contains(event.target)) return;\n setPopover(null);\n };\n document.addEventListener('pointerdown', close);\n return () => document.removeEventListener('pointerdown', close);\n }, [popover]);\n useEffect(() => {\n if (popover === 'games') gameMenuRef.current?.querySelector('[role=\"menuitem\"]:not(:disabled)')?.focus();\n }, [raceMenu, tankMenu]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const chooseGame = (action) => { setPopover(null); textareaRef.current?.focus(); action?.(); };\n const handleGameMenuKeyDown = (event) => {\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) return;\n event.preventDefault();\n const items = [...(gameMenuRef.current?.querySelectorAll('[role=\"menuitem\"]:not(:disabled)') || [])];\n const index = items.indexOf(document.activeElement);\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? items.length - 1\n : (index + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length;\n items[next]?.focus();\n };\n\n const handleKeyDown = useCallback((event) => {\n if (event.key === 'Escape' && popover) {\n event.preventDefault(); event.stopPropagation();\n const fromGames = popover === 'games';\n setPopover(null);\n (fromGames ? gameButtonRef.current : textareaRef.current)?.focus(); return;\n }\n if (event.key === 'Escape' && editing && !event.defaultPrevented && !autocompleteOpen) {\n event.preventDefault(); onCancelEdit?.(); return;\n }\n if (event.defaultPrevented || event.target !== textareaRef.current) return;\n if (event.key === 'ArrowUp' && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey\n && value === '' && !attachments.length && !event.nativeEvent.isComposing && event.keyCode !== 229\n && !popover && !autocompleteOpen && !recording && !sending && !editing) {\n event.preventDefault();\n if (onStartEditLast?.()) requestAnimationFrame(() => { const node = textareaRef.current; if (!node) return; node.focus(); const end = node.value.length; node.setSelectionRange(end, end); });\n return;\n }\n if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing && event.keyCode !== 229) {\n event.preventDefault();\n if (canSend && !recording) onSend();\n }\n }, [popover, canSend, recording, onSend, editing, onCancelEdit, onStartEditLast, autocompleteOpen, value, attachments.length, sending]);\n\n const handlePaste = useCallback((event) => {\n const files = Array.from(event.clipboardData?.files || []);\n if (!files.length) {\n for (const item of Array.from(event.clipboardData?.items || [])) {\n if (item.kind === 'file') { const file = item.getAsFile(); if (file) files.push(file); }\n }\n }\n if (files.length) { event.preventDefault(); files.forEach((file) => onAddAttachment?.(file)); }\n }, [onAddAttachment]);\n\n const handleInputChange = useCallback((event) => {\n const newValue = event.target.value;\n const caret = event.target.selectionStart;\n // Commit an exact shortcode on space or closing colon, without sending.\n // Keep partial tokens editable, including longer aliases such as :detective_woman.\n const completed = /(^|[^\\p{L}\\p{N}_]):([\\p{L}\\p{N}\\p{M}_+-]{1,64})(:| )$/u.exec(newValue.slice(0, caret));\n if (!event.nativeEvent.isComposing && completed && event.nativeEvent.inputType !== 'insertFromPaste') {\n const emoji = customEmojis.find((item) => item.shortcode === completed[2].toLowerCase())?.emoji || resolveEmojiShortcode(completed[2]);\n if (emoji) {\n const start = completed.index + completed[1].length;\n const suffix = completed[3] === ' ' ? ' ' : '';\n onChange(newValue.slice(0, start) + emoji + suffix + newValue.slice(caret));\n setAutocompleteOpen(false);\n setPopover(null);\n requestAnimationFrame(() => textareaRef.current?.setSelectionRange(start + emoji.length + suffix.length, start + emoji.length + suffix.length));\n return;\n }\n }\n onChange(newValue);\n if (popover) setPopover(null);\n \n setAutocompleteOpen(Boolean(findEmojiToken(newValue, caret)));\n }, [onChange, popover, customEmojis]);\n\n return (\n <div ref={composerRef} className={`chat-composer${editing ? ' chat-composer--editing' : ''}`} style={{ '--chat-picker-available-height': `${pickerAvailableHeight}px` }} onKeyDown={handleKeyDown}\n onPaste={handlePaste} onDragOver={(event) => event.preventDefault()}\n onDrop={(event) => { event.preventDefault(); Array.from(event.dataTransfer.files).forEach((file) => onAddAttachment?.(file)); }}>\n <input ref={fileInputRef} type=\"file\" multiple hidden onChange={(event) => { Array.from(event.target.files || []).forEach((file) => onAddAttachment?.(file)); event.target.value = ''; }} />\n {sending && <div className=\"chat-send-status\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n <div className=\"chat-send-status-body\">\n <span className=\"chat-send-status-icon\"><Loader2 size={23} className=\"chat-send-spinner\" aria-hidden=\"true\" /></span>\n <div className=\"chat-send-status-copy\"><strong>{sendingTitle}</strong>\n {sendingMedia?.name && <span className=\"chat-send-status-file\" title={sendingMedia.name}>{sendingMedia.name}</span>}\n <small>Mantén esta conversación abierta hasta que termine.</small>\n </div>\n </div>\n <div className=\"chat-send-status-track\" aria-hidden=\"true\"><span /></div>\n </div>}\n {attachmentError && <div className=\"chat-attachment-notice\" role=\"alert\">{attachmentError}</div>}\n {voice.error && <div className=\"chat-attachment-notice\" role=\"alert\">{voice.error}</div>}\n {editing && <div className=\"chat-reply-preview chat-edit-preview\"><div><strong>Editando mensaje</strong><span>{String(editing.original?.message || editing.original?.text || '').slice(0, 180)}</span><small>Enter para guardar · Esc para cancelar</small></div><button type=\"button\" className=\"chat-btn\" onClick={onCancelEdit} aria-label=\"Cancelar edición\"><X size={16} /></button></div>}\n {reply && !editing && <div className=\"chat-reply-preview\"><div><strong>Respuesta a {reply.username || 'Usuario'}</strong><span>{String(reply.message || reply.text || '[Archivo adjunto]').slice(0, 180)}</span><small>Se enviará como cita de texto</small></div><button type=\"button\" className=\"chat-btn\" onClick={onCancelReply} aria-label=\"Cancelar respuesta\"><X size={16} /></button></div>}\n <MediaPreview items={attachments} onRemove={sending ? undefined : onRemoveAttachment} />\n <div className=\"chat-composer-top\">\n <textarea ref={textareaRef} className=\"chat-composer-textarea\" value={value} onChange={handleInputChange}\n readOnly={disabled} aria-label=\"Mensaje\" placeholder=\"Escribe un mensaje…\" rows={1} spellCheck />\n </div>\n {recording && <div className=\"chat-voice-recording\" role=\"status\">\n <span className=\"chat-recording-indicator\" />\n <span>{voice.status === 'requesting' ? 'Esperando permiso del micrófono…' : `Grabando ${Math.floor(voice.seconds / 60)}:${String(voice.seconds % 60).padStart(2, '0')} / 2:00`}</span>\n {voice.status === 'recording' && <button type=\"button\" className=\"chat-composer-btn\" onClick={voice.stop} aria-label=\"Terminar grabación y previsualizar\" title=\"Terminar y previsualizar\"><Square size={16} /></button>}\n <button type=\"button\" className=\"chat-composer-btn\" onClick={voice.cancel} aria-label=\"Cancelar grabación\" title=\"Cancelar grabación\"><X size={16} /></button>\n </div>}\n <div className=\"chat-composer-bottom\">\n <div className=\"chat-composer-actions\">\n {(onInviteGame || onOpenBattleshipPreview) && <button ref={gameButtonRef} type=\"button\" className=\"chat-composer-btn\"\n disabled={sending || Boolean(editing) || (gameInviteDisabled && !onOpenBattleshipPreview)}\n onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'games' ? null : 'games'); }}\n aria-label=\"Juegos\" aria-haspopup=\"menu\" aria-expanded={popover === 'games'} title=\"Invitar a jugar\"><Gamepad2 size={18} /></button>}\n {onSendEffect && <button type=\"button\" className=\"chat-composer-btn\" disabled={disabled || Boolean(editing)} onClick={() => setPopover(popover === 'effects' ? null : 'effects')} aria-label=\"Efectos y zumbidos\" aria-expanded={popover === 'effects'} title=\"Efectos y zumbidos\">✨</button>}\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending || Boolean(editing)} onClick={() => fileInputRef.current?.click()} aria-label=\"Adjuntar archivos\" title=\"Adjuntar archivos\"><Paperclip size={18} /></button>\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending} onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'emoji' ? null : 'emoji'); }} aria-label=\"Emojis\" aria-expanded={popover === 'emoji'} title=\"Emojis\"><Smile size={18} /></button>\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending || Boolean(editing)} onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'gif' ? null : 'gif'); }} aria-label=\"Buscar GIFs\" aria-expanded={popover === 'gif'} title=\"Buscar GIFs\"><Clapperboard size={18} /></button>\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending || Boolean(editing)} onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'sticker' ? null : 'sticker'); }} aria-label=\"Stickers\" aria-expanded={popover === 'sticker'} title=\"Stickers\"><Sticker size={18} /></button>\n <button type=\"button\" className={`chat-composer-btn ${recording ? 'is-active' : ''}`} onClick={voice.start} disabled={recording || sending || Boolean(editing)} aria-label=\"Grabar nota de voz\" title=\"Grabar nota de voz\"><Mic size={18} /></button>\n </div>\n <span className=\"chat-composer-hint\">{sending ? 'Enviando…' : editing ? 'Enter para guardar · Esc para cancelar' : attachments.length ? 'Máx. 10 MB · temporal, sin historial' : disabled ? 'Sin conexión · prepara tus archivos' : 'Enter para enviar · Shift+Enter nueva línea'}</span>\n <button type=\"button\" className=\"chat-composer-send\" onClick={() => { if (canSend && !recording) onSend(); }} disabled={!canSend || recording}\n aria-label={sending ? 'Enviando mensaje' : editing ? 'Guardar edición' : 'Enviar mensaje'} aria-busy={sending} title={sending ? 'Enviando…' : editing ? 'Guardar edición' : 'Enviar mensaje'}>{sending ? <Loader2 size={18} className=\"chat-send-spinner\" aria-hidden=\"true\" /> : editing ? <Check size={17} /> : <Send size={17} />}</button>\n </div>\n {popover === 'games' && <div ref={gameMenuRef} className=\"chat-game-menu\" role=\"menu\" aria-label=\"Juegos\" onKeyDown={handleGameMenuKeyDown}\n onBlur={(event) => {\n // Close when keyboard focus leaves (e.g. Tab). A null relatedTarget is left to the\n // outside-pointer handler so Safari's non-focusing button clicks still reach the item.\n const next = event.relatedTarget;\n if (!next || gameMenuRef.current?.contains(next) || gameButtonRef.current?.contains(next)) return;\n setPopover(null);\n }}>\n {onInviteGame && raceMenu && <>\n <span className=\"chat-game-menu-title\">Carreras LIVE · categoría</span>\n {RACE_CLASS_MENU.map(({ id, hint }) => (\n <button key={id} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => chooseGame(() => onInviteGame('racing_live', { speedClass: id }))}><Flag size={16} aria-hidden=\"true\" /><span><strong>{id}</strong> · {hint}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setRaceMenu(false)}><span>← Volver</span></button>\n </>}\n {onInviteGame && tankMenu === 'map' && <>\n <span className=\"chat-game-menu-title\">Tanques LIVE · mapa</span>\n {TANK_MAP_MENU.map(({ id, label, hint }) => (\n <button key={id} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => { setTankMap(id); setTankMenu('lives'); }}><Crosshair size={16} aria-hidden=\"true\" /><span><strong>{label}</strong> · {hint}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setTankMenu(null)}><span>← Volver</span></button>\n </>}\n {onInviteGame && tankMenu === 'lives' && <>\n <span className=\"chat-game-menu-title\">Tanques LIVE · vidas</span>\n {TANK_LIVES_MENU.map(({ lives, hint }) => (\n <button key={lives} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => chooseGame(() => onInviteGame('tanks_live', { mapId: tankMap, lives }))}><span aria-hidden=\"true\">{'❤️'.repeat(lives)}</span><span><strong>{lives} {lives === 1 ? 'vida' : 'vidas'}</strong> · {hint}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setTankMenu('map')}><span>← Volver</span></button>\n </>}\n {onInviteGame && !raceMenu && !tankMenu && <>\n <span className=\"chat-game-menu-title\">Invitar a jugar</span>\n {GAME_MENU.filter((item) => gameTypes.includes(item.type)).map(({ type, label, Icon }) => (\n <button key={type} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => (type === 'racing_live' ? setRaceMenu(true) : type === 'tanks_live' ? setTankMenu('map') : chooseGame(() => onInviteGame(type)))}><Icon size={16} aria-hidden=\"true\" /><span>{label}</span></button>))}\n </>}\n {onOpenBattleshipPreview && !raceMenu && !tankMenu && <>\n {onInviteGame && <hr className=\"chat-game-menu-separator\" />}\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\"\n onClick={() => chooseGame(onOpenBattleshipPreview)}><Box size={16} aria-hidden=\"true\" /><span>Vista previa 3D (sin rival)</span></button>\n </>}\n </div>}\n {popover === 'effects' && <EffectPicker onSend={onSendEffect} disabled={disabled || Boolean(editing)} onClose={() => setPopover(null)} />}\n {popover === 'emoji' && <div onKeyDownCapture={(event) => { if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); setPopover(null); textareaRef.current?.focus(); } }}>\n <EmojiPicker isOpen disabled={disabled} onSelect={(emoji) => { const node = textareaRef.current; const start = node?.selectionStart ?? value.length; const end = node?.selectionEnd ?? start; onChange(value.slice(0, start) + emoji + value.slice(end)); requestAnimationFrame(() => node?.setSelectionRange(start + emoji.length, start + emoji.length)); setPopover(null); textareaRef.current?.focus(); }} onClose={() => setPopover(null)} />\n </div>}\n {pickerKind && <div className={`chat-gif-picker-wrapper${pickerKind === 'sticker' ? ' chat-sticker-picker-wrapper' : ''}`} style={{ height: Math.min(pickerHeight, pickerAvailableHeight) }} role=\"dialog\" aria-label={pickerKind === 'sticker' ? 'Buscar stickers' : 'Buscar GIFs'} onKeyDown={(event) => {\n if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); setPopover(null); textareaRef.current?.focus(); }\n }}>\n <button type=\"button\" className=\"chat-gif-resize-handle\" aria-label={pickerKind === 'sticker' ? 'Cambiar altura del selector de stickers' : 'Cambiar altura del selector de GIFs'}\n title=\"Arrastra hacia arriba para ampliar · flechas para ajustar\"\n onPointerDown={(event) => {\n if (event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n pickerResizeRef.current = { y: event.clientY, height: Math.min(pickerHeight, pickerAvailableHeight) };\n event.currentTarget.setPointerCapture(event.pointerId);\n }}\n onPointerMove={(event) => {\n const start = pickerResizeRef.current;\n if (start) setPickerHeight(Math.min(pickerAvailableHeight, Math.max(220, start.height + start.y - event.clientY)));\n }}\n onPointerUp={(event) => {\n pickerResizeRef.current = null;\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n }}\n onPointerCancel={() => { pickerResizeRef.current = null; }}\n onLostPointerCapture={() => { pickerResizeRef.current = null; }}\n onKeyDown={(event) => {\n if (!['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) return;\n event.preventDefault();\n event.stopPropagation();\n setPickerHeight((height) => Math.min(pickerAvailableHeight, Math.max(220,\n event.key === 'End' ? pickerAvailableHeight : event.key === 'Home' ? 220 : Math.min(height, pickerAvailableHeight) + (event.key === 'ArrowUp' ? 30 : -30))));\n }}><GripHorizontal size={18} /></button>\n {pickerKind === 'sticker' ? <StickerPicker\n onSelect={(sticker) => { onAddAttachment?.(sticker); textareaRef.current?.focus(); }}\n onClose={() => setPopover(null)}\n disabled={disabled}\n /> : <GifPicker\n onSelect={(gif) => { onAddAttachment?.(gif); textareaRef.current?.focus(); }}\n onClose={() => setPopover(null)}\n disabled={disabled}\n />}\n </div>}\n <EmojiAutocomplete\n textareaRef={textareaRef}\n value={value}\n onInsert={handleAutocompleteInsert}\n onClose={handleAutocompleteClose}\n isOpen={autocompleteOpen}\n />\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { ChevronUp, Gamepad2 } from 'lucide-react';\nimport useChatGames from './useChatGames';\nimport useGamePanelStore from './useGamePanelStore';\nimport ConnectedGameCard from './ConnectedGameCard';\nimport { getGameTitle, getShortGameStatus, isTerminalGame, sameUser } from './gameStatus';\n\nexport default function ChatGamePanel({ gameKey, currentUserId }) {\n const game = useChatGames((state) => state.games[gameKey]);\n const minimized = useGamePanelStore((state) => Boolean(state.panels[gameKey]?.minimized));\n if (!game) return null;\n const { setMinimized, dismiss } = useGamePanelStore.getState();\n const myTurn = game.game !== 'racing_live' && game.status === 'active' && sameUser(currentUserId, game.turnId);\n const title = getGameTitle(game);\n const keepMounted = game.game === 'tanks_live' || game.game === 'racing_live';\n const canDismiss = isTerminalGame(game) && !game.pendingEvent;\n return (\n <section className={`chat-game-panel${minimized ? ' chat-game-panel--minimized' : ''}`} aria-label={`Partida activa de ${title}`}>\n {minimized && (\n <button type=\"button\" className={`chat-game-panel-bar${myTurn ? ' chat-game-panel-bar--my-turn' : ''}`} onClick={() => setMinimized(gameKey, false)} aria-label={`Mostrar tablero de ${title}`}>\n <Gamepad2 size={15} aria-hidden=\"true\" />\n <span>{title} · {getShortGameStatus(game, currentUserId)}</span>\n <ChevronUp size={15} aria-hidden=\"true\" />\n </button>\n )}\n {(keepMounted || !minimized) && <div hidden={minimized}>\n <ConnectedGameCard suspended={minimized} gameKey={gameKey} currentUserId={currentUserId} variant=\"panel\"\n onMinimize={() => setMinimized(gameKey, true)} onDismiss={canDismiss ? () => dismiss(gameKey) : undefined} />\n </div>}\n </section>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { Suspense, useEffect, useRef, useState } from 'react';\nimport { Grip, ArrowLeft } from 'lucide-react';\nimport { useChatUnread } from '../../core/unread/unreadMessages';\nimport useChatTextSize from '../hooks/useChatTextSize';\nimport useFocusTrap from '../hooks/useFocusTrap';\nimport useResizable from '../hooks/useResizable';\nimport ChatHeader from './ChatHeader';\nimport ChatSidebar from './ChatSidebar';\nimport ChatEmptyState from './ChatEmptyState';\nimport MessageList from './MessageList';\nimport MessageComposer from './MessageComposer';\nimport { ChatEffects } from '../../effects/ChatEffects.jsx';\nimport ChatGamePanel from '../../games/shared/ChatGamePanel';\n\n\nexport default function ChatWindow({\n effectsConfig, effectScope, effectIdentityScope, onSendEffect, effectError,\n BattleshipPreviewComponent = null,\n placement = 'floating',\n theme,\n standalone, onDetach, onInstall, installHelp, onDismissInstallHelp,\n title,\n subtitle,\n headerType,\n headerSecondary,\n headerPresence,\n currentUserName, myPresence, onSetPresence,\n isOpen,\n isMaximized,\n isMinimized,\n onClose,\n onMinimize,\n onToggleMaximize,\n rooms,\n users,\n messages,\n onInviteGame, gameInviteDisabled, gameTypes, gameError, gamePanelKey,\n currentUserId,\n currentUserIds,\n onSelectRoom,\n onSelectUser,\n selectedId,\n inputValue,\n onInputChange,\n onSend,\n attachments,\n onAddAttachment,\n onRemoveAttachment,\n status,\n disabled,\n onSearch, searchResults, searchStatus, searchQuery, presenceStatus,\n onCreateGroup,\n attachmentError, sending, reply, onReply, onCancelReply,\n privateRooms,\n knownUsers,\n unreadCounts,\n onlineUsers,\n editing, onStartEditLast, onCancelEdit, onEditMessage, onReact,\n}) {\n const [textSize, setTextSize] = useChatTextSize();\n const dialogRef = useRef(null);\n const [showSidebar, setShowSidebar] = useState(true);\n const [battleshipPreview, setBattleshipPreview] = useState(false);\n useEffect(() => { setBattleshipPreview(false); }, [selectedId]);\n const [isFullscreen, setFullscreen] = useState(() => window.matchMedia('(max-width: 640px)').matches);\n useEffect(() => {\n const media = window.matchMedia('(max-width: 640px)');\n const update = () => setFullscreen(media.matches);\n media.addEventListener('change', update);\n return () => media.removeEventListener('change', update);\n }, []);\n // Wide windows show list and conversation side by side; small ones show one pane at a time.\n const wide = !isFullscreen && (isMaximized || standalone);\n const resizable = !standalone && !isFullscreen && !isMaximized;\n const { size, isResizing, handleProps: resizeHandleProps } = useResizable({ initial: { width: 420, height: 740 }, min: { width: 360, height: 380 }, enabled: resizable, targetRef: dialogRef });\n const listVisible = wide ? showSidebar : showSidebar || selectedId == null;\n useEffect(() => {\n if (selectedId != null && !wide) setShowSidebar(false);\n }, [selectedId, wide]);\n useEffect(() => {\n const update = () => {\n const showingConversation = isOpen && !isMinimized && selectedId != null && (wide || !listVisible);\n useChatUnread.getState().setVisibleRoom(showingConversation\n && document.visibilityState === 'visible' && document.hasFocus() ? selectedId : null);\n };\n update();\n window.addEventListener('focus', update);\n window.addEventListener('blur', update);\n document.addEventListener('visibilitychange', update);\n return () => {\n window.removeEventListener('focus', update);\n window.removeEventListener('blur', update);\n document.removeEventListener('visibilitychange', update);\n useChatUnread.getState().setVisibleRoom(null);\n };\n }, [isOpen, isMinimized, selectedId, wide, listVisible]);\n const selectRoom = (id) => { if (sending) return; if (!wide) setShowSidebar(false); onSelectRoom?.(id); };\n const trapFocus = useFocusTrap(dialogRef, { active: isFullscreen, autoFocus: isOpen && !isMinimized });\n if (isMinimized) {\n return (\n <button type=\"button\" className={`mc-chat chat-window ${placement === 'floating' ? 'chat-window--floating ' : ''}chat-window--minimized`} data-chat-theme={theme} onClick={onMinimize} aria-label=\"Abrir chat\">\n <span style={{ width: '32px', height: '32px', borderRadius: '50%', background: 'var(--chat-primary)', color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, margin: 'auto' }}>\n {title?.charAt(0).toUpperCase()}\n </span>\n </button>\n );\n }\n\n if (!isOpen) return null;\n return (\n <ChatEffects roomId={selectedId} scope={effectScope} identityScope={effectIdentityScope} messages={messages} currentUserIds={currentUserIds} config={{ ...effectsConfig, enabled: effectsConfig?.enabled !== false && (headerType === 'private' || effectsConfig?.allowGroups === true) }} visible={isOpen && !isMinimized && selectedId != null && (wide || !listVisible)} targetRef={dialogRef}>\n <div ref={dialogRef} className={`mc-chat chat-window ${placement === 'floating' ? 'chat-window--floating' : ''} ${standalone ? 'chat-window--standalone' : ''} ${isMaximized ? 'chat-window--maximized' : 'chat-window--compact'} ${wide ? `chat-window--wide${listVisible ? '' : ' chat-window--hide-sidebar'}` : (listVisible ? 'chat-window--show-sidebar' : '')} ${isResizing ? 'chat-window--resizing' : ''}`} style={{ '--chat-message-font-size': `${textSize}px`, ...(resizable ? { '--chat-window-width': `${size.width}px`, '--chat-window-height': `${size.height}px` } : {}) }} data-chat-theme={theme} role=\"dialog\" aria-modal={isFullscreen || undefined} aria-label={title} onKeyDown={trapFocus} tabIndex={-1}>\n {resizable && <button type=\"button\" className=\"chat-resize-handle\"\n aria-label=\"Cambiar tamaño del chat\" title=\"Arrastra para ajustar el tamaño · también puedes usar las flechas\"\n {...resizeHandleProps}>\n <Grip size={13} aria-hidden=\"true\" />\n </button>}\n <ChatHeader\n textSize={textSize} onTextSizeChange={setTextSize}\n onDetach={onDetach} onInstall={onInstall}\n title={title}\n subtitle={subtitle}\n type={headerType}\n secondary={headerSecondary}\n presence={headerPresence}\n onClose={onClose}\n onMinimize={onMinimize}\n onMaximize={onToggleMaximize}\n onRestore={onToggleMaximize}\n isMaximized={isMaximized}\n showSidebar={listVisible} onToggleSidebar={() => setShowSidebar(!listVisible)}\n />\n {installHelp && <div className=\"chat-install-help\" role=\"status\"><span>{installHelp}</span><button type=\"button\" className=\"chat-btn\" onClick={onDismissInstallHelp} aria-label=\"Cerrar ayuda de instalación\">×</button></div>}\n <div className=\"chat-body\">\n <ChatSidebar\n rooms={rooms}\n users={users}\n onlineUsers={onlineUsers}\n privateRooms={privateRooms}\n knownUsers={knownUsers}\n selectedId={selectedId}\n onSelect={selectRoom}\n onSelectUser={onSelectUser}\n onSearch={onSearch} searchResults={searchResults} searchStatus={searchStatus} searchQuery={searchQuery} presenceStatus={presenceStatus}\n onCreateGroup={onCreateGroup}\n unreadCounts={unreadCounts}\n currentUserId={currentUserId}\n currentUserIds={currentUserIds}\n currentUserName={currentUserName} myPresence={myPresence} onSetPresence={onSetPresence}\n />\n <div className=\"chat-messages-wrapper\">\n {selectedId != null ? (\n <>\n {!wide && <button type=\"button\" className=\"chat-back-btn\" onClick={() => setShowSidebar(true)} aria-label=\"Volver a conversaciones\"><ArrowLeft size={16} aria-hidden=\"true\" /><span>Conversaciones</span></button>}\n <MessageList key={`messages:${selectedId}`} messages={messages} currentUserId={currentUserId} onReply={onReply} panelGameKey={gamePanelKey} onReact={onReact} onEditMessage={onEditMessage} editingId={editing?.messageId} />\n {gamePanelKey && !battleshipPreview && <ChatGamePanel key={gamePanelKey} gameKey={gamePanelKey} currentUserId={currentUserId} />}\n {battleshipPreview && BattleshipPreviewComponent && <div className=\"bs-proto-overlay\">\n <Suspense fallback={<p className=\"bs-proto-overlay__loading\" role=\"status\">Cargando vista previa 3D…</p>}>\n <BattleshipPreviewComponent compact={!isMaximized || isFullscreen} onClose={() => setBattleshipPreview(false)} />\n </Suspense>\n </div>}\n <div className=\"chat-connection-status\" role=\"status\">\n <span className={`chat-connection-dot ${status === 'connected' ? 'chat-connection-dot--connected' : 'chat-connection-dot--disconnected'}`} />\n <span>{status === 'connected' ? 'Conectado' : 'Sin conexión · puedes preparar archivos y notas de voz'}</span>\n </div>\n {effectError && <p className=\"chat-game-launch-error\" role=\"alert\">{effectError}</p>}\n {gameError && <p className=\"chat-game-launch-error\" role=\"alert\">{gameError}</p>}\n <MessageComposer key={`composer:${selectedId}`}\n onSendEffect={onSendEffect}\n onInviteGame={onInviteGame} gameInviteDisabled={gameInviteDisabled} gameTypes={gameTypes}\n onOpenBattleshipPreview={BattleshipPreviewComponent ? () => setBattleshipPreview(true) : undefined}\n reply={reply} onCancelReply={onCancelReply}\n editing={editing} onStartEditLast={onStartEditLast} onCancelEdit={onCancelEdit}\n value={inputValue}\n onChange={onInputChange}\n onSend={onSend}\n disabled={disabled}\n attachments={attachments}\n sending={sending}\n attachmentError={attachmentError}\n onAddAttachment={onAddAttachment}\n onRemoveAttachment={onRemoveAttachment}\n />\n </>\n ) : (\n <ChatEmptyState />\n )}\n </div>\n </div>\n </div>\n </ChatEffects>\n );\n}\n","import { useEffect, useState } from 'react';\n\nlet installPrompt = null;\nconst hasWindow = () => typeof window !== 'undefined';\nconst notifyInstall = () => { if (hasWindow()) window.dispatchEvent(new Event('chat-install-change')); };\n\n// Ref-counted, idempotent: listeners are registered once; the last stop() removes them.\nlet installUsers = 0;\nlet removeInstallListeners = null;\nexport function startChatApp() {\n if (!hasWindow()) return () => {};\n if (installUsers++ === 0) {\n const onPrompt = (event) => {\n event.preventDefault();\n installPrompt = event;\n notifyInstall();\n };\n const onInstalled = () => {\n installPrompt = null;\n notifyInstall();\n };\n window.addEventListener('beforeinstallprompt', onPrompt);\n window.addEventListener('appinstalled', onInstalled);\n removeInstallListeners = () => {\n window.removeEventListener('beforeinstallprompt', onPrompt);\n window.removeEventListener('appinstalled', onInstalled);\n };\n }\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n if (--installUsers === 0) {\n removeInstallListeners?.();\n removeInstallListeners = null;\n installPrompt = null;\n }\n };\n}\n\nexport function useChatInstall() {\n const standalone = () => hasWindow() && (window.matchMedia('(display-mode: standalone)').matches || Boolean(navigator.standalone));\n const [installed, setInstalled] = useState(standalone);\n const [available, setAvailable] = useState(Boolean(installPrompt));\n const [installHelp, setInstallHelp] = useState('');\n useEffect(() => {\n const media = window.matchMedia('(display-mode: standalone)');\n const update = () => { setInstalled(standalone()); setAvailable(Boolean(installPrompt)); };\n window.addEventListener('chat-install-change', update);\n media.addEventListener('change', update);\n return () => { window.removeEventListener('chat-install-change', update); media.removeEventListener('change', update); };\n }, []);\n const install = async () => {\n if (!window.isSecureContext) {\n setInstallHelp('Para instalar el chat, abre la aplicación mediante HTTPS o localhost.');\n return;\n }\n if (!installPrompt) {\n setInstallHelp('Abre el menú del navegador y elige “Instalar LIRA Chat” o “Añadir al Dock / pantalla de inicio”. Si no aparece, abre esta ventana de chat en una pestaña del navegador.');\n return;\n }\n const prompt = installPrompt;\n installPrompt = null;\n notifyInstall();\n try {\n await prompt.prompt();\n await prompt.userChoice;\n } catch {\n setInstallHelp('No se pudo iniciar la instalación. Puedes usar la opción de instalar del menú del navegador.');\n }\n };\n return { installed, available, install, installHelp, dismissInstallHelp: () => setInstallHelp('') };\n}\n\nlet chatPopup = null;\nexport function openChatWindow({ path = '/chat', windowName = 'lira-independent-chat' } = {}) {\n if (chatPopup && !chatPopup.closed) { chatPopup.focus(); return true; }\n const width = Math.min(520, window.screen.availWidth);\n const height = Math.min(800, window.screen.availHeight);\n chatPopup = window.open(path, windowName, `popup=yes,width=${width},height=${height},resizable=yes,scrollbars=yes`);\n if (!chatPopup) return false;\n // The window restores its own session and socket; it never depends on the opener.\n chatPopup.opener = null;\n chatPopup.focus();\n return true;\n}\n\nexport function registerChatWorker({ enabled = true, path = '/chat', swUrl = '/chat-sw.js' } = {}) {\n if (enabled && hasWindow() && 'serviceWorker' in navigator && window.isSecureContext && window.location.pathname === path) {\n navigator.serviceWorker.register(swUrl, { scope: path }).catch((error) => console.warn('Chat service worker:', error));\n }\n}\n","import { useState, useEffect, useRef, useMemo } from 'react';\nimport { useShallow } from 'zustand/react/shallow';\nimport { useChatUnread } from '../../core/unread/unreadMessages.js';\nimport useChatGames from '../../games/shared/useChatGames.js';\nimport { isGameMessage } from '../../games/shared/protocol.js';\nimport { isWebrtcMessage } from '../../net/webrtc/protocol.js';\nimport useGamePanelStore from '../../games/shared/useGamePanelStore.js';\nimport { isLiveGame, isTerminalGame } from '../../games/shared/gameStatus.js';\nimport { useChatStore, useChatIdentity, useChatConfig, useChatConnection } from '../../provider/hooks.js';\nimport { setDesktopConversation } from '../../notifications/desktopNotifications.js';\nimport { useChatInstall } from '../../pwa/chatApp.js';\nimport { shareGif } from '../../media/klipy/klipy.js';\nimport { shareSticker } from '../../media/klipy/klipyStickers.js';\nimport { encodeEffect, decodeEffect, effectMessageText } from '../../effects/protocol.js';\nimport { useChatMessageExtras, isStickerAttachment, encodeEdit, encodeReaction, groupReactions, findLastOwnEditable, messageId, isMessageAction } from '../../core/extras/messageExtras.js';\n\n// Matched by the backend relay limit; files are never persisted.\nconst MAX_PREVIEW_BYTES = 10 * 1024 * 1024;\n\n/**\n * Chat data logic: store subscriptions, timeline, composer and actions.\n * `isOpen`/`isMinimized` come from useChatLayout (desktop notifications and presence refresh).\n */\nexport default function useChatController({ isOpen = false, isMinimized = false } = {}) {\n const installation = useChatInstall();\n const { effects: rawEffectsConfig, features } = useChatConfig();\n const gamesFeatures = features?.games;\n const gameTypes = useMemo(() => ['connect4', 'battleship', 'tanks', 'tanks_live', 'racing_live'].filter((type) => (type === 'racing_live' ? gamesFeatures?.racingLive === true : type === 'tanks_live' ? gamesFeatures?.tanksLive === true : type === 'tanks' ? gamesFeatures?.tanks === true : gamesFeatures?.[type] !== false)), [gamesFeatures]);\n const effectsConfig = rawEffectsConfig === false ? { enabled: false } : rawEffectsConfig ?? {};\n const effectCooldowns = useRef(new Map());\n const effectPending = useRef(false);\n const [effectError, setEffectError] = useState('');\n const { chatMessages, chatState, onlineUsers, rawPrivateRooms, userSearchQuery, userSearchResults,\n userSearchStatus, presenceStatus, rawKnownUsers, myPresence } = useChatStore(useShallow((state) => ({\n chatMessages: state.chatMessages,\n chatState: state.chatState,\n onlineUsers: state.onlineUsers,\n rawPrivateRooms: state.privateRooms,\n userSearchQuery: state.userSearchQuery,\n userSearchResults: state.userSearchResults,\n userSearchStatus: state.userSearchStatus,\n presenceStatus: state.presenceStatus,\n rawKnownUsers: state.knownUsers,\n myPresence: state.myPresence,\n })));\n const chatIdentity = useChatIdentity();\n const effectConnection = useChatConnection();\n const websocketStatus = chatIdentity.status;\n const { selectChat, fetchGroups, searchUsers, setUserSearchQuery, sendChatMessage, createGroup, openPrivateChat, setMyPresence } = useChatStore(useShallow((state) => ({\n selectChat: state.selectChat,\n fetchGroups: state.fetchGroups,\n searchUsers: state.searchUsers,\n setUserSearchQuery: state.setUserSearchQuery,\n sendChatMessage: state.sendChatMessage,\n createGroup: state.createGroup,\n openPrivateChat: state.openPrivateChat,\n setMyPresence: state.setMyPresence,\n })));\n const unreadCounts = useChatUnread((state) => state.counts);\n const unreadRooms = useChatUnread((state) => state.ledger.rooms);\n // Keep private pending conversations reachable after reloading, even offline.\n const privateRooms = useMemo(() => ({ ...Object.fromEntries(Object.entries(unreadRooms)\n .map(([room, info]) => [info.peerId, room])), ...rawPrivateRooms }), [unreadRooms, rawPrivateRooms]);\n const knownUsers = useMemo(() => ({ ...Object.fromEntries(Object.values(unreadRooms)\n .map((info) => [info.peerId, { user_id: info.peerId, username: info.username }])), ...rawKnownUsers }), [unreadRooms, rawKnownUsers]);\n const [reply, setReply] = useState(null);\n const [editing, setEditing] = useState(null);\n const [gameError, setGameError] = useState('');\n const edits = useChatMessageExtras((s) => s.edits);\n const reactions = useChatMessageExtras((s) => s.reactions);\n useEffect(() => { setReply(null); setEffectError(''); }, [chatState.currentChat?.id, chatIdentity.userId]);\n const [inputValue, setInputValue] = useState('');\n // selectRoom and the identity reset already clear the input.\n useEffect(() => { setEditing(null); }, [chatState.currentChat?.id, chatIdentity.userId]);\n const [attachments, setAttachments] = useState([]);\n const [sending, setSending] = useState(false);\n const sendingRef = useRef(false);\n const objectUrls = useRef(new Set());\n const [attachmentError, setAttachmentError] = useState('');\n const attachmentRef = useRef([]);\n const activeRoom = chatState.currentChat?.id;\n const selectedId = activeRoom ?? null;\n // Same `${backend}:${userId}` scope the host transport reports (games and desktop notifications).\n const gameScope = chatIdentity.scope;\n const gameKeys = useChatGames(useShallow((state) => Object.keys(state.games).filter((key) => {\n const game = state.games[key];\n return game.scope === gameScope && String(game.roomId) === String(activeRoom);\n })));\n const gameMessages = useMemo(() => gameKeys.map((key) => {\n const game = useChatGames.getState().games[key];\n return { id: `game:${key}`, gameKey: key, room_id: activeRoom, timestamp: game.createdAt };\n }), [gameKeys, activeRoom]);\n const hasLiveGame = useChatGames((state) => Object.values(state.games).some((game) =>\n game.scope === gameScope && String(game.roomId) === String(activeRoom) && isLiveGame(game)));\n const gamePanels = useGamePanelStore((state) => state.panels);\n // One interactive board per room: the live game, else the latest finished one not dismissed.\n const gamePanelKey = useChatGames((state) => {\n const games = Object.values(state.games).filter((game) => game.scope === gameScope && String(game.roomId) === String(activeRoom));\n const live = games.find(isLiveGame);\n if (live) return live.key;\n // Only the newest finished game may reopen; dismissing it must not fall back to older ones.\n const latest = games.filter(isTerminalGame)\n .sort((a, b) => (Date.parse(b.createdAt) || 0) - (Date.parse(a.createdAt) || 0))[0];\n return latest && !gamePanels[latest.key]?.dismissed ? latest.key : null;\n });\n useEffect(() => { setGameError(''); }, [activeRoom, gameScope]);\n useEffect(() => {\n setDesktopConversation({ scope: gameScope, room: activeRoom, open: isOpen && !isMinimized });\n return () => setDesktopConversation(null);\n }, [gameScope, activeRoom, isOpen, isMinimized]);\n const visible = isOpen && !isMinimized;\n const handleSelectUser = (item) => {\n if (sendingRef.current) return;\n const recipientId = item?.user_id ?? item?.id;\n if (!recipientId) return;\n const existingRoom = privateRooms[recipientId];\n if (existingRoom) {\n selectRoom(existingRoom, 'private');\n } else {\n openPrivateChat(recipientId);\n }\n };\n\n const identity = chatIdentity.userId;\n const currentUserIds = chatIdentity.ids;\n // Names for reaction tooltips (ReactionBar reads this instead of global stores).\n const people = useMemo(() => ({\n ownIds: currentUserIds,\n resolveName: (id) => {\n const known = knownUsers?.[id];\n if (known?.username || known?.name) return known.name || known.username;\n const online = onlineUsers.find((user) => String(user.user_id ?? user.id) === String(id));\n return online?.name || online?.username || null;\n },\n }), [currentUserIds, knownUsers, onlineUsers]);\n useEffect(() => {\n setAttachments([]);\n attachmentRef.current = [];\n objectUrls.current.forEach((url) => URL.revokeObjectURL(url));\n objectUrls.current.clear();\n setInputValue('');\n setAttachmentError('');\n }, [identity]);\n\n useEffect(() => {\n if (websocketStatus === 'connected') fetchGroups();\n }, [websocketStatus, fetchGroups]);\n\n // Refresh on connection/open, without another request when the chat closes.\n const presenceTrigger = useRef({ connected: false, visible: false });\n useEffect(() => {\n const connected = websocketStatus === 'connected';\n const previous = presenceTrigger.current;\n presenceTrigger.current = { connected, visible };\n if (connected && (!previous.connected || (visible && !previous.visible))) searchUsers('');\n }, [websocketStatus, visible, searchUsers]);\n useEffect(() => {\n if (!visible || websocketStatus !== 'connected' || !userSearchQuery) return undefined;\n const timer = setTimeout(() => searchUsers(userSearchQuery), 300);\n return () => clearTimeout(timer);\n }, [userSearchQuery, websocketStatus, visible, searchUsers]);\n\n // Public channels are joined in the store on GROUPS_LIST; private rooms need no CHAT_JOIN.\n\n useEffect(() => {\n attachmentRef.current = attachments;\n }, [attachments]);\n useEffect(() => {\n const urls = objectUrls.current;\n return () => { urls.forEach((url) => URL.revokeObjectURL(url)); urls.clear(); };\n }, []);\n\n const messages = useMemo(() => chatMessages.map((envelope) => {\n const body = envelope.data ?? envelope.payload;\n return body && typeof body === 'object' ? { ...envelope, ...body } : envelope;\n }).filter((message) =>\n !['CHAT_JOINED', 'CHAT_LEFT'].includes(message.event)\n && message.room_id != null && String(message.room_id) === String(activeRoom)\n && !isGameMessage(message.message ?? message.text)\n && !isWebrtcMessage(message.message ?? message.text)\n && !isMessageAction(message.message ?? message.text)\n && (typeof message.message === 'string' || typeof message.text === 'string' || message.attachments?.length || message.attachment)\n ).map((message) => {\n const id = messageId(message);\n if (!id) return message;\n const edit = edits[id];\n const merged = edit ? { ...message, message: edit.text, edited: true, editedAt: edit.editedAt } : message;\n return { ...merged, reactionGroups: groupReactions(reactions[id], currentUserIds) };\n }), [chatMessages, activeRoom, edits, reactions, currentUserIds]);\n const timeline = useMemo(() => {\n // Insert game anchors without changing the arrival order of ordinary messages.\n const result = [...messages];\n for (const game of gameMessages) {\n const time = Date.parse(game.timestamp);\n const index = result.findIndex((message) => Date.parse(message.timestamp) > time);\n result.splice(index < 0 ? result.length : index, 0, game);\n }\n return result;\n }, [messages, gameMessages]);\n\n const selectRoom = (id, type) => {\n if (id == null || sendingRef.current || String(id) === String(activeRoom)) return;\n // Auto-detect type: private_ prefix or privateRooms values\n const inferredType = (type || (String(id).startsWith('private_') ? 'private' : 'group'));\n selectChat(id, inferredType);\n setInputValue('');\n attachmentRef.current.forEach((item) => { if (item.preview?.startsWith('blob:')) { URL.revokeObjectURL(item.preview); objectUrls.current.delete(item.preview); } });\n attachmentRef.current = [];\n setAttachments([]);\n setAttachmentError('');\n };\n const startEdit = (message) => {\n if (sendingRef.current || !message || message.localOnly || message.sending || decodeEffect(message.message ?? message.text)) return false;\n const id = messageId(message);\n const text = message.message ?? message.text;\n if (!id || typeof text !== 'string' || !text.trim() || !currentUserIds.includes(String(message.user_id))) return false;\n const match = text.match(/^> ([^\\n]{1,240})\\n\\n/);\n const quote = match ? match[0] : '';\n setInputValue(text.slice(quote.length));\n setReply(null);\n setAttachmentError('');\n setEditing({ messageId: id, original: message, quote });\n return true;\n };\n const cancelEdit = () => { setEditing(null); setInputValue(''); };\n const handleReact = (message, emoji) => {\n const id = messageId(message);\n if (!id || !emoji || websocketStatus !== 'connected') return;\n const mine = (reactions[id]?.[emoji] || []).some((userId) => currentUserIds.includes(String(userId)));\n void sendChatMessage(String(message.room_id ?? activeRoom), encodeReaction({ targetId: id, emoji, on: !mine }), [])\n .catch((error) => setAttachmentError(error.message));\n };\n const handleSend = async () => {\n if (activeRoom == null || sendingRef.current || websocketStatus !== 'connected') return;\n if (editing) {\n const text = inputValue.trim();\n const original = editing.original?.message ?? editing.original?.text ?? '';\n if (!text || editing.quote + text === original) { cancelEdit(); return; }\n sendingRef.current = true;\n setSending(true);\n setAttachmentError('');\n try {\n await sendChatMessage(activeRoom, encodeEdit({ targetId: editing.messageId, text: editing.quote + text }), []);\n setEditing(null);\n setInputValue('');\n } catch (error) {\n setAttachmentError(error.message);\n } finally {\n sendingRef.current = false;\n setSending(false);\n }\n return;\n }\n const outgoingAttachments = [...attachmentRef.current];\n const text = inputValue.trim();\n if (!text && !outgoingAttachments.length) return;\n sendingRef.current = true;\n setSending(true);\n setAttachmentError('');\n try {\n // Reply is ordinary quoted text under the existing backend contract.\n const quoted = reply ? `> ${String(reply.username || 'Usuario').replace(/[\\r\\n]/g, ' ').slice(0, 50)}: ${String(reply.message || reply.text || '[Archivo adjunto]').replace(/\\s+/g, ' ').slice(0, 180)}\\n\\n` : '';\n await sendChatMessage(activeRoom, quoted + text, outgoingAttachments);\n // Register KLIPY usage only for media that was actually sent (never on mere selection).\n outgoingAttachments.forEach((item) => {\n if (item.kind !== 'gif' || !item.slug) return;\n if (isStickerAttachment(item)) void shareSticker(item.slug, { query: item.shareQuery || '' });\n else void shareGif(item.slug, { query: item.shareQuery || '' });\n });\n setReply(null);\n outgoingAttachments.forEach((item) => {\n if (item.preview?.startsWith('blob:')) { URL.revokeObjectURL(item.preview); objectUrls.current.delete(item.preview); }\n });\n attachmentRef.current = [];\n setAttachments([]);\n setInputValue('');\n } catch (error) {\n setAttachmentError(error.message);\n } finally {\n sendingRef.current = false;\n setSending(false);\n }\n };\n const handleAddAttachment = (file) => {\n if (sendingRef.current) return;\n if (attachmentRef.current.length >= 1) {\n setAttachmentError('Envía un archivo o GIF por mensaje.');\n return;\n }\n let item;\n if (file.kind === 'gif') {\n try {\n const url = new URL(file.url);\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error('invalid');\n item = { ...file, preview: url.href, url: url.href };\n } catch {\n setAttachmentError('Introduce un enlace HTTPS válido para el GIF.');\n return;\n }\n } else {\n if (!(file instanceof Blob) || (!file.size || file.size > MAX_PREVIEW_BYTES)) {\n setAttachmentError('Máximo 10 MB por archivo.');\n return;\n }\n const preview = URL.createObjectURL(file);\n objectUrls.current.add(preview);\n item = { file, name: file.name || 'Nota de voz', size: file.size, type: file.type || 'application/octet-stream', preview };\n }\n const next = [...attachmentRef.current, item];\n attachmentRef.current = next;\n setAttachments(next);\n setAttachmentError('');\n };\n const removeAttachment = (index) => {\n if (sendingRef.current) return;\n const item = attachmentRef.current[index];\n if (item?.preview?.startsWith('blob:')) { URL.revokeObjectURL(item.preview); objectUrls.current.delete(item.preview); }\n const next = attachmentRef.current.filter((_, i) => i !== index);\n attachmentRef.current = next;\n setAttachments(next);\n setAttachmentError('');\n };\n const room = chatState.availableGroups?.find((group) => String(group.id) === String(activeRoom));\n const isPrivate = chatState.currentChat?.type === 'private';\n const users = onlineUsers;\n let title = 'Chat';\n let headerSecondary;\n let headerPresence = null;\n if (activeRoom != null) {\n if (isPrivate) {\n const userId = Object.keys(privateRooms).find((key) => privateRooms[key] === activeRoom);\n const user = (userId && knownUsers[userId]) || onlineUsers.find((item) => String(item.user_id ?? item.id) === String(userId));\n title = user?.name || user?.username || (userId ? `Usuario ${String(userId).slice(0, 8)}` : 'Conversación privada');\n if (user?.username && user.username !== title) headerSecondary = user.username;\n // Offline peers are absent from onlineUsers; a missing status means plain online.\n const peer = userId != null && onlineUsers.find((item) => String(item.user_id ?? item.id) === String(userId));\n headerPresence = peer ? peer.status || 'online' : null;\n } else {\n title = room?.name || String(activeRoom);\n }\n }\n\n // Props for ChatWindow that do not depend on window layout.\n const windowProps = {\n effectsConfig,\n effectIdentityScope: chatIdentity.scope,\n effectScope: `${chatIdentity.scope}:${effectConnection.connectionId ?? effectConnection.status}`,\n effectError,\n onSendEffect: effectsConfig.enabled !== false && (isPrivate || effectsConfig.allowGroups) ? async (effectId, countdown) => {\n if (activeRoom == null || websocketStatus !== 'connected' || sendingRef.current || editing || effectPending.current) return { ok: false, error: 'No se puede enviar un efecto ahora.' };\n const key = `${chatIdentity.scope}:${activeRoom}`;\n const last = effectCooldowns.current.get(key) ?? 0;\n const wait = (effectsConfig.cooldownMs ?? 5000) - (Date.now() - last);\n if (wait > 0) { const error = `Espera ${Math.ceil(wait / 1000)} s para enviar otro efecto.`; setEffectError(error); return { ok: false, error }; }\n effectPending.current = true; setEffectError('');\n try {\n await sendChatMessage(activeRoom, encodeEffect({ effectId, ...(countdown ? { endsAt: Date.now() + countdown.durationMs, sound: countdown.sound } : {}) }), []);\n effectCooldowns.current.set(key, Date.now());\n return { ok: true };\n } catch (error) { const message = error.message || 'No se pudo enviar el efecto.'; setEffectError(message); return { ok: false, error: message }; }\n finally { effectPending.current = false; }\n } : undefined,\n title,\n headerType: isPrivate ? 'private' : 'group',\n headerSecondary,\n headerPresence,\n currentUserName: chatIdentity.name ?? undefined,\n myPresence,\n onSetPresence: setMyPresence,\n subtitle: websocketStatus,\n onInstall: !installation.installed ? installation.install : undefined,\n installHelp: installation.installHelp,\n onDismissInstallHelp: installation.dismissInstallHelp,\n rooms: chatState.availableGroups || [],\n users,\n onlineUsers,\n presenceStatus,\n searchResults: userSearchResults,\n searchStatus: userSearchStatus,\n searchQuery: userSearchQuery,\n onSearch: setUserSearchQuery,\n privateRooms,\n knownUsers,\n messages: timeline,\n gamePanelKey,\n gameError,\n gameInviteDisabled: hasLiveGame || websocketStatus !== 'connected',\n gameTypes,\n onInviteGame: isPrivate && activeRoom != null ? (gameType = 'connect4', options = {}) => {\n const opponentId = Object.keys(privateRooms).find((key) => String(privateRooms[key]) === String(activeRoom));\n if (!opponentId) { setGameError('Abre de nuevo la conversación privada para invitar a jugar.'); return; }\n setGameError('');\n void useChatGames.getState().invite({ roomId: String(activeRoom), opponentId, gameType, ...(gameType === 'racing_live' && options.speedClass ? { speedClass: options.speedClass } : {}), ...(gameType === 'tanks_live' ? { ...(options.mapId ? { mapId: options.mapId } : {}), ...(options.lives ? { lives: options.lives } : {}) } : {}) }).catch((error) => setGameError(error.message));\n } : undefined,\n currentUserId: identity,\n currentUserIds,\n unreadCounts,\n onSelectRoom: (id) => selectRoom(id),\n onSelectUser: handleSelectUser,\n editing,\n onStartEditLast: () => { const message = findLastOwnEditable(messages, currentUserIds); return message ? startEdit(message) : false; },\n onCancelEdit: () => { if (!sendingRef.current) cancelEdit(); },\n onEditMessage: (message) => { startEdit(message); },\n onReact: handleReact,\n reply,\n onReply: (message) => { if (!sendingRef.current) setReply({ ...message, message: effectMessageText(message.message ?? message.text) }); },\n onCancelReply: () => { if (!sendingRef.current) setReply(null); },\n selectedId,\n inputValue,\n onInputChange: (value) => { if (!sendingRef.current) setInputValue(value); },\n onSend: handleSend,\n onCreateGroup: (name) => { if (websocketStatus === 'connected' && name.trim()) createGroup(name.trim()); },\n attachments,\n onAddAttachment: handleAddAttachment,\n onRemoveAttachment: removeAttachment,\n sending,\n attachmentError,\n status: websocketStatus,\n disabled: sending || websocketStatus !== 'connected',\n };\n\n return { identity, people, windowProps, setAttachmentError };\n}\n","import { createStore, useStore } from 'zustand';\n\n// Uncontrolled open state shared by ChatButton and ChatWindow (when no `open` prop is given).\nexport const chatUiStore = createStore((set) => ({\n isOpen: false,\n open: () => set({ isOpen: true }),\n close: () => set({ isOpen: false }),\n toggle: () => set((state) => ({ isOpen: !state.isOpen })),\n}));\n\nconst identity = (state) => state;\nexport const useChatUi = (selector = identity) => useStore(chatUiStore, selector);\n\nexport default chatUiStore;\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { openChatWindow } from '../../pwa/chatApp.js';\nimport { useChatConfig } from '../../provider/hooks.js';\nimport { chatUiStore, useChatUi } from './chatUiStore.js';\n\n// Escape only acts when the key comes from the chat dialog or from no focused element.\nconst isChatEscapeTarget = (target) => !target || target === document || target === document.body\n || document.documentElement === target\n || (typeof target.closest === 'function' && Boolean(target.closest('.chat-window')));\n\n/**\n * Window layout state for the connected chat.\n * mode: 'floating' | 'modal' | 'embedded' | 'page'. Embedded and page are always open.\n * Open state is controlled by `open`/`onOpenChange` when `open` is given, else by chatUiStore.\n */\nexport default function useChatLayout({ mode = 'floating', open, onOpenChange } = {}) {\n const config = useChatConfig();\n const alwaysOpen = mode === 'embedded' || mode === 'page';\n const controlled = open !== undefined;\n const storeOpen = useChatUi((state) => state.isOpen);\n const isOpen = alwaysOpen || Boolean(controlled ? open : storeOpen);\n const [isMaximized, setMaximized] = useState(false);\n const [isMinimized, setMinimized] = useState(false);\n\n const latest = useRef({});\n latest.current = { controlled, onOpenChange, onConfigOpenChange: config?.callbacks?.onOpenChange };\n const setOpen = useCallback((value) => {\n const { controlled: isControlled, onOpenChange: handler, onConfigOpenChange } = latest.current;\n if (!isControlled) chatUiStore.setState({ isOpen: value });\n handler?.(value);\n onConfigOpenChange?.(value);\n }, []);\n\n useEffect(() => {\n if (isOpen) setMinimized(false);\n }, [isOpen]);\n\n const canMinimize = mode === 'floating';\n const minimize = useCallback(() => { setMinimized(true); setOpen(false); }, [setOpen]);\n const restore = useCallback(() => { setMinimized(false); setOpen(true); }, [setOpen]);\n const close = useCallback(() => { setMinimized(false); setOpen(false); }, [setOpen]);\n const toggleMinimize = useCallback(() => { if (isMinimized) restore(); else minimize(); }, [isMinimized, restore, minimize]);\n const toggleMaximize = useCallback(() => setMaximized((value) => !value), []);\n const pwa = config?.pwa;\n // Returns false when the browser blocked the popup.\n const detach = useCallback(() => {\n if (!openChatWindow({ path: pwa?.path, windowName: pwa?.windowName })) return false;\n setMinimized(false);\n setOpen(false);\n return true;\n }, [pwa, setOpen]);\n\n useEffect(() => {\n if (!isOpen || alwaysOpen) return undefined;\n const handleKey = (event) => {\n if (event.key !== 'Escape' || event.defaultPrevented || !isChatEscapeTarget(event.target)) return;\n event.preventDefault();\n if (canMinimize) minimize();\n else close();\n };\n document.addEventListener('keydown', handleKey);\n return () => document.removeEventListener('keydown', handleKey);\n }, [isOpen, alwaysOpen, canMinimize, minimize, close]);\n\n return {\n mode,\n standalone: mode === 'page',\n isOpen,\n isMinimized: canMinimize && isMinimized,\n isMaximized,\n setMaximized,\n setOpen,\n minimize,\n restore,\n close,\n toggleMinimize,\n toggleMaximize,\n detach,\n };\n}\n","/* eslint-disable react/prop-types */\nimport { useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport ChatWindowShell from '../components/ChatWindow.jsx';\nimport { ChatPeopleContext } from '../chatPeopleContext.js';\nimport useFocusTrap from '../hooks/useFocusTrap.js';\nimport { useChatConfig } from '../../provider/hooks.js';\nimport useChatController from './useChatController.js';\nimport useChatLayout from './useChatLayout.js';\n\nconst POPUP_BLOCKED = 'El navegador bloqueó la ventana. Permite ventanas emergentes para este sitio.';\n\nconst portalTarget = (config) => {\n if (typeof document === 'undefined') return null;\n const container = typeof config?.portalContainer === 'function' ? config.portalContainer() : config?.portalContainer;\n return container || document.body;\n};\n\n/** Modal frame: backdrop (click closes), focus trapped inside the dialog. */\nfunction ModalFrame({ open, onClose, theme, children }) {\n const frameRef = useRef(null);\n const trap = useFocusTrap(frameRef, { active: open, autoFocus: open });\n if (!open) return null;\n return (\n <div className=\"mc-chat-portal mc-chat-modal-backdrop\" data-chat-theme={theme}\n onMouseDown={(event) => { if (event.target === event.currentTarget) onClose(); }}>\n <div ref={frameRef} className=\"mc-chat-modal\" onKeyDown={trap}>{children}</div>\n </div>\n );\n}\n\n/**\n * Connected chat window (must be inside LiraChatProvider).\n * placement: 'floating' (portal, minimize/maximize/detach, Escape minimizes) |\n * 'modal' (portal + backdrop + focus trap, Escape/backdrop close) | 'embedded' (inline, always open).\n * Open state: controlled with `open`/`onOpenChange`, else shared chatUiStore (ChatButton).\n */\nexport default function ChatWindow({\n placement = 'floating', open, onOpenChange, theme, className, BattleshipPreviewComponent = null,\n}) {\n const config = useChatConfig();\n const mode = placement === 'modal' || placement === 'embedded' ? placement : 'floating';\n const layout = useChatLayout({ mode, open, onOpenChange });\n const chat = useChatController({ isOpen: layout.isOpen, isMinimized: layout.isMinimized });\n const floating = mode === 'floating';\n const canDetach = floating && config?.features?.detach !== false;\n\n const shell = (\n <ChatWindowShell key={chat.identity} {...chat.windowProps}\n BattleshipPreviewComponent={BattleshipPreviewComponent}\n placement={mode} theme={theme}\n isOpen={layout.isOpen}\n isMaximized={floating && layout.isMaximized}\n isMinimized={layout.isMinimized}\n onDetach={canDetach ? () => { if (!layout.detach()) chat.setAttachmentError(POPUP_BLOCKED); } : undefined}\n onClose={mode === 'embedded' ? undefined : layout.close}\n onMinimize={floating ? layout.toggleMinimize : undefined}\n onToggleMaximize={floating ? layout.toggleMaximize : undefined} />\n );\n const content = <ChatPeopleContext.Provider value={chat.people}>{shell}</ChatPeopleContext.Provider>;\n\n if (mode === 'embedded') {\n return <div className={`mc-chat-embedded${className ? ` ${className}` : ''}`}>{content}</div>;\n }\n const target = portalTarget(config);\n if (!target) return null;\n if (mode === 'modal') {\n return createPortal(\n <ModalFrame open={layout.isOpen} onClose={layout.close} theme={theme}>\n {className ? <div className={className}>{content}</div> : content}\n </ModalFrame>,\n target,\n );\n }\n return createPortal(className ? <div className={className}>{content}</div> : content, target);\n}\n","/* eslint-disable react/prop-types */\nimport { createPortal } from 'react-dom';\nimport ChatWindowShell from '../components/ChatWindow.jsx';\nimport { ChatPeopleContext } from '../chatPeopleContext.js';\nimport { useChatConfig } from '../../provider/hooks.js';\nimport useChatController from './useChatController.js';\nimport useChatLayout from './useChatLayout.js';\n\n/**\n * Full-page chat (detached window / PWA route). Always open, viewport-sized,\n * no minimize/maximize/detach. Must be inside LiraChatProvider.\n * Portaled like the floating window (document.body or config.portalContainer).\n */\nexport default function ChatPage({ theme, className, BattleshipPreviewComponent = null }) {\n const config = useChatConfig();\n const layout = useChatLayout({ mode: 'page' });\n const chat = useChatController({ isOpen: true, isMinimized: false });\n if (typeof document === 'undefined') return null;\n const target = (typeof config?.portalContainer === 'function' ? config.portalContainer() : config?.portalContainer) || document.body;\n const content = (\n <ChatPeopleContext.Provider value={chat.people}>\n <ChatWindowShell key={chat.identity} {...chat.windowProps}\n BattleshipPreviewComponent={BattleshipPreviewComponent}\n placement=\"page\" theme={theme} standalone\n isOpen={layout.isOpen} isMaximized={layout.isMaximized} isMinimized={false} />\n </ChatPeopleContext.Provider>\n );\n return createPortal(className ? <div className={className}>{content}</div> : content, target);\n}\n","/* eslint-disable react/prop-types */\nimport { MessageCircle } from 'lucide-react';\nimport { useChatUnread, totalUnread } from '../../core/unread/unreadMessages.js';\nimport { chatUiStore, useChatUi } from './chatUiStore.js';\n\n/**\n * Chat launcher with the total unread badge. Without `onClick` it toggles chatUiStore\n * (the uncontrolled ChatWindow); with `onClick` the host owns the open state and may pass `pressed`.\n * Does not require LiraChatProvider (unread counts live in the package unread store).\n */\nexport default function ChatButton({ className, label = 'Chat', onClick, pressed, badgeClassName, iconSize = 17 }) {\n const unread = useChatUnread(totalUnread);\n const storeOpen = useChatUi((state) => state.isOpen);\n const isPressed = pressed ?? (onClick ? undefined : storeOpen);\n return (\n <button type=\"button\" className={className ?? 'mc-chat mc-chat-button'}\n onClick={(event) => { if (onClick) onClick(event); else chatUiStore.getState().toggle(); }}\n aria-label={unread ? `${label}, ${unread} mensajes nuevos` : label}\n aria-pressed={isPressed} title={label}>\n <MessageCircle size={iconSize} aria-hidden=\"true\" />\n {unread > 0 && <span className={badgeClassName ?? 'mc-chat-button__badge'}>{unread > 99 ? '99+' : unread}</span>}\n </button>\n );\n}\n","/*\n * Mirrors the total chat unread count on the installed app icon (Badging API).\n * Works from window context; no service worker changes needed.\n * Support: Chromium/Edge installed PWAs on Windows/macOS/ChromeOS, macOS Safari 17+\n * \"Add to Dock\" web apps, iOS/iPadOS 16.4+ Home Screen web apps only after notification\n * permission is granted. Not supported: Android Chrome (badge dots come only from\n * notifications), Firefox, or regular browser tabs (calls are no-ops or reject).\n */\nimport { useChatUnread, totalUnread } from '../core/unread/unreadMessages.js';\n\nconst running = new WeakMap();\n\n// onFail lets the caller forget the applied value so the next store change retries it.\nconst call = (nav, method, onFail, ...args) => {\n try {\n const result = nav[method](...args);\n if (result && typeof result.catch === 'function') result.catch(onFail);\n } catch { /* NotAllowedError / SecurityError (iframes, insecure contexts, iOS without permission). */ onFail(); }\n};\n\n/** True when startAppBadge() is already mirroring `store` (someone else owns its stop()). */\nexport const isAppBadgeRunning = (store = useChatUnread) => running.has(store);\n\nexport function startAppBadge({ store = useChatUnread, nav = globalThis.navigator, schedule = queueMicrotask } = {}) {\n if (running.has(store)) return running.get(store);\n if (!nav || !('setAppBadge' in nav)) {\n const noop = () => {};\n running.set(store, noop);\n return noop;\n }\n let last;\n let pending = false;\n const apply = () => {\n pending = false;\n const state = store.getState();\n const total = state.scope ? totalUnread(state) : 0;\n if (total === last) return;\n last = total;\n const retry = () => { if (last === total) last = undefined; };\n if (total > 0) call(nav, 'setAppBadge', retry, total);\n else if ('clearAppBadge' in nav) call(nav, 'clearAppBadge', retry);\n else call(nav, 'setAppBadge', retry, 0);\n };\n apply();\n const unsubscribe = store.subscribe(() => {\n if (pending) return;\n pending = true;\n schedule(apply);\n });\n const stop = () => {\n unsubscribe();\n running.delete(store);\n };\n running.set(store, stop);\n return stop;\n}\n","import { useEffect } from 'react';\nimport { startDesktopNotifications } from '../../notifications/desktopNotifications.js';\nimport { startAppBadge, isAppBadgeRunning } from '../../notifications/appBadge.js';\nimport { initChatSounds } from '../../notifications/chatSounds.js';\nimport { startConnect4Sounds, isConnect4SoundsRunning } from '../../games/connect4/connect4Sounds.js';\nimport { useChatConfig } from '../../provider/hooks.js';\n\n/**\n * Renders nothing. While mounted keeps desktop notifications, the app icon badge and\n * chat/game sounds running. Safe when the host also starts them: desktop notifications are\n * ref-counted, and idempotent services already started elsewhere are left to their owner.\n */\nexport default function ChatNotifications() {\n const notifications = useChatConfig()?.notifications;\n const enabled = notifications !== false;\n const desktop = enabled && notifications?.desktop !== false;\n const badge = enabled && notifications?.appBadge !== false;\n const sound = enabled && notifications?.sound !== false;\n\n useEffect(() => (desktop ? startDesktopNotifications() : undefined), [desktop]);\n useEffect(() => {\n if (!badge || isAppBadgeRunning()) return undefined;\n return startAppBadge();\n }, [badge]);\n useEffect(() => {\n if (!sound) return undefined;\n initChatSounds(); // idempotent, no teardown\n if (isConnect4SoundsRunning()) return undefined;\n return startConnect4Sounds();\n }, [sound]);\n return null;\n}\n","import { randomUuid } from '../ids/randomUuid.js';\n// File bytes only live in connected browsers. The server relays 32 KB frames.\nconst MAX_BYTES = 10 * 1024 * 1024;\nconst sessions = new WeakMap();\nconst sessionFor = (socket) => {\n if (!sessions.has(socket)) sessions.set(socket, { pending: new Map(), files: new Map() });\n return sessions.get(socket);\n};\n\nexport function relayRequest(socket, action, payload) {\n if (socket?.readyState !== WebSocket.OPEN) return Promise.reject(new Error('Sin conexión'));\n const state = sessionFor(socket);\n const request_id = randomUuid();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n state.pending.delete(request_id);\n reject(new Error('El servidor no confirmó el envío. Conservamos el borrador.'));\n }, 15000);\n state.pending.set(request_id, { resolve, reject, timer });\n socket.send(JSON.stringify({ action, payload: { ...payload, request_id } }));\n });\n}\n\nexport function consumeRelayEvent(socket, event) {\n const state = sessionFor(socket);\n const data = event.data || event.payload || {};\n if (event.event === 'CHAT_ACK' || event.event === 'ERROR' || event.type === 'ERROR') {\n const pending = state.pending.get(data.request_id);\n if (pending) {\n clearTimeout(pending.timer);\n state.pending.delete(data.request_id);\n if (event.event === 'CHAT_ACK') pending.resolve();\n else pending.reject(new Error(data.message || 'No se pudo enviar'));\n return true;\n }\n // Unknown ACKs belong to another requester (e.g. the shared-socket adapter); let them through.\n return false;\n }\n if (event.event !== 'CHAT_FILE') return false;\n const now = Date.now();\n for (const [id, file] of state.files) {\n if (now - file.created > 60000) state.files.delete(id);\n }\n if (!Number.isInteger(data.size) || data.size <= 0 || data.size > MAX_BYTES) return true;\n if (data.index === 0) {\n if (state.files.size >= 4) return true;\n state.files.set(data.id, { parts: [], bytes: 0, index: 0, created: now, room: data.room_id, user: data.user_id });\n }\n const file = state.files.get(data.id);\n if (!file || file.index !== data.index || file.room !== data.room_id || file.user !== data.user_id) return true;\n const raw = atob(data.chunk);\n const bytes = Uint8Array.from(raw, (c) => c.charCodeAt(0));\n file.bytes += bytes.length;\n if (file.bytes > data.size || bytes.length > 32768) { state.files.delete(data.id); return true; }\n file.parts.push(bytes);\n file.index++;\n if (data.final && file.bytes === data.size) file.blob = new Blob(file.parts, { type: data.type });\n return true;\n}\n\nexport function hydrateRelayMessage(socket, message) {\n const state = sessionFor(socket);\n return { ...message, attachments: (message.attachments || []).map((item) => {\n if (item.kind === 'gif') return item;\n const file = state.files.get(item.id);\n state.files.delete(item.id);\n if (!file?.blob || file.room !== message.room_id || file.user !== message.user_id) return { ...item, name: `${item.name} (no disponible)` };\n return { ...item, url: URL.createObjectURL(file.blob) };\n }) };\n}\n\nexport function closeRelay(socket) {\n const state = sessions.get(socket);\n if (!state) return;\n state.pending.forEach(({ reject, timer }) => { clearTimeout(timer); reject(new Error('Conexión interrumpida. Reintenta el envío.')); });\n state.pending.clear();\n state.files.clear();\n}\n\nexport async function sendRelayMessage(socket, roomId, message, attachments = []) {\n if (attachments.length > 1) throw new Error('Envía un archivo o GIF por mensaje.');\n const outgoing = [];\n for (const attachment of attachments) {\n if (attachment.kind === 'gif') {\n outgoing.push({ kind: 'gif', url: attachment.url, name: attachment.name });\n continue;\n }\n const file = attachment.file;\n if (!(file instanceof Blob) || !file.size || file.size > MAX_BYTES) throw new Error('El archivo debe pesar entre 1 byte y 10 MB.');\n const id = randomUuid();\n for (let start = 0, index = 0; start < file.size; start += 32768, index++) {\n const bytes = new Uint8Array(await file.slice(start, start + 32768).arrayBuffer());\n const chunk = btoa(String.fromCharCode(...bytes));\n await relayRequest(socket, 'CHAT_FILE', {\n id, room_id: roomId, size: file.size, type: file.type || 'application/octet-stream',\n name: attachment.name, index, chunk,\n });\n }\n outgoing.push({ id });\n }\n await relayRequest(socket, 'CHAT_MESSAGE', { room_id: roomId, message, attachments: outgoing });\n}\n","import { lazy } from 'react';\n\n// Public WebRTC surface (TANQUES LIVE groundwork). The lab UI is a separate chunk.\nexport { createPeerLink, DEFAULT_ICE_SERVERS } from './createPeerLink.js';\nexport { rtcSignals, createChatSignaling } from './rtcSignals.js';\nexport { withSignalFaults } from './signalFaults.js';\nexport { WEBRTC_PREFIX, MAX_SIGNAL_LENGTH, isWebrtcMessage, encodeSignal, decodeSignal } from './protocol.js';\nexport const WebRtcLab = lazy(() => import('./WebRtcLab.jsx'));\n","// @minicode-dev/chat public API. Only what is exported here is supported; internal\n// paths may change between versions. See README.md and, in the LIRA repo,\n// docs/MBSoft-Chat-NPM-Migration.md for the migration status.\nimport './styles.css';\n\nexport const MINICODE_CHAT_VERSION = '0.1.0';\n\n// Provider, configuration and hooks\nexport { LiraChatProvider } from './provider/LiraChatProvider.jsx';\nexport { ChatContext, useChatContext } from './provider/ChatContext.js';\nexport { useChatStore, useChatStoreApi, useChatConfig, useChatTransport, useChatConnection, useChatUnreadTotal, useChatIdentity } from './provider/hooks.js';\nexport { normalizeConfig, normalizeUser, DEFAULT_CONFIG } from './config/normalizeConfig.js';\n\n// Transport\nexport { createStandaloneTransport } from './core/transport/createStandaloneTransport.js';\nexport { TRANSPORT_STATUSES, assertTransport } from './core/transport/chatTransport.js';\nexport { chatConnectionStore, setChatConnectionStatus, useChatConnectionStatus } from './core/connection/connectionStore.js';\n\n// Chat domain store (messages, rooms, presence, user search) over a ChatTransport\nexport { createChatStore, MAX_CHAT_MESSAGES } from './core/chat/createChatStore.js';\n\n// Protocol helpers (wire format is frozen; see test/contract)\nexport {\n EDIT_PREFIX, REACT_PREFIX, STICKER_NAME_PREFIX, encodeEdit, encodeReaction, parseMessageAction,\n isMessageAction, isStickerAttachment, groupReactions,\n} from './core/extras/messageExtras.js';\n\n// Media configuration\nexport { configureKlipy } from './media/klipy/klipy.js';\nexport { setChatAssetsBaseUrl, getChatAssetsBaseUrl } from './assets/chatAssets.js';\n\n// Connected components (decision §11, option A). Must be rendered inside LiraChatProvider,\n// except ChatButton and chatUiStore, which only use package-level stores.\nexport { default as ChatWindow } from './ui/connected/ChatWindow.jsx';\nexport { default as ChatPage } from './ui/connected/ChatPage.jsx';\nexport { default as ChatButton } from './ui/connected/ChatButton.jsx';\nexport { default as ChatNotifications } from './ui/connected/ChatNotifications.jsx';\nexport { chatUiStore, useChatUi } from './ui/connected/chatUiStore.js';\n\n// Unread counters (package singleton; also used by host badges)\nexport { useChatUnread, totalUnread, unreadScope, startUnreadStorageSync } from './core/unread/unreadMessages.js';\n\n// Host integration: background services a host starts once (see LIRA src/chat/startChat.js).\n// All starters are idempotent or ref-counted and return stop().\nexport { startDesktopNotifications } from './notifications/desktopNotifications.js';\nexport { startAppBadge } from './notifications/appBadge.js';\nexport { startChatApp, registerChatWorker, openChatWindow, useChatInstall } from './pwa/chatApp.js';\nexport { startGifLibrarySync } from './media/gif-search/gifLibrary.js';\nexport { startEmojiPreferencesSync } from './media/emoji/emojiPreferences.js';\nexport { chatGamesStore, useChatGames } from './games/shared/useChatGames.js';\nexport { startConnect4Sounds } from './games/connect4/connect4Sounds.js';\n// File relay over a raw WebSocket (hosts that share their own socket, like LIRA).\nexport { consumeRelayEvent, hydrateRelayMessage, closeRelay, sendRelayMessage } from './core/relay/fileRelay.js';\n// Battleship 3D preview (three.js) stays out of the main chunk.\nexport const loadBattleshipPreview = () => import('./games/battleship/BattleshipPrototype.jsx');\n\n// UI primitives (presentational)\nexport { default as ChatWindowShell } from './ui/components/ChatWindow.jsx';\nexport { default as MessageList } from './ui/components/MessageList.jsx';\nexport { default as MessageBubble } from './ui/components/MessageBubble.jsx';\nexport { default as MessageComposer } from './ui/components/MessageComposer.jsx';\nexport { default as EmojiPicker } from './ui/components/EmojiPicker.jsx';\nexport { default as GifPicker } from './ui/components/GifPicker.jsx';\nexport { default as StickerPicker } from './ui/components/StickerPicker.jsx';\nexport { ChatPeopleContext } from './ui/chatPeopleContext.js';\n\n// Original audiovisual chat effects (ordinary versioned text messages).\nexport { EFFECT_CATALOG, getChatEffect } from './effects/catalog.js';\nexport { EFFECT_PREFIX, encodeEffect, decodeEffect } from './effects/protocol.js';\n\n// WebRTC peer links signaled through the chat (LIRA_WEBRTC_V1:) and the lab UI (lazy chunk).\nexport {\n createPeerLink, DEFAULT_ICE_SERVERS, rtcSignals, createChatSignaling, withSignalFaults,\n WEBRTC_PREFIX, MAX_SIGNAL_LENGTH, isWebrtcMessage, encodeSignal, decodeSignal, WebRtcLab,\n} from './net/webrtc/index.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["browserStorage","MAX_EMOJI_LENGTH","pending","read","identity","key","ERROR_MESSAGE","PREVIEW_SIZES","FULL_SIZES","categoriesCache","normalizeItem","request","toPage","pageParams","PRESENCE_TEXT","PRESENCE_TEXT","_Fragment","prefersReducedMotion","prefersReducedMotion","_Fragment","_Fragment","safeUrl","File","_Fragment","identity","STORAGE_KEY","hasWindow","cleanList","readStorage","writeStorage","_Fragment","prefersReducedMotion","ReactionBar","GameCard","ConnectedGameCard","keyOf","hasWindow","prefersReducedMotion","_Fragment","PER_PAGE","SEARCH_DEBOUNCE_MS","GifCategoryBar","_Fragment","_Fragment","_Fragment","ConnectedGameCard","ChatWindow","_Fragment","createStore","ChatWindowShell","ChatWindowShell","rtcSignals","useChatGames","createChatSignaling","isGameMessage","randomUuid","getChatAssetsBaseUrl","setChatAssetsBaseUrl","chatSoundUrl","RACING_TRACKS","WEBRTC_PREFIX","isWebrtcMessage","MAX_SIGNAL_LENGTH","createPeerLink","decodeSignal","encodeSignal","DEFAULT_ICE_SERVERS","requestNotification","isSoundEnabled","useChatContext","subscribeSoundPreference","initChatSounds","toggleSound","ChatContext","setChatConnectionStatus","useChatConnectionStatus","chatConnectionStore","boltFlicker","THUNDER_CUES","THUNDER_DURATION_MS","isBattleshipGame","isTerminalGame","sameUser","getGameTitle","isLiveGame","getShortGameStatus","isTanksGame","getGameStatus","startConnect4Sounds","isConnect4SoundsRunning","GameSoundControls","settleConnect4Drop","connect4Sounds","withSignalFaults","createStore$1","File$1","dayjs","noop","DEFAULT_CONFIG","isPlainObject","value","normalizeUser","user","id","ids","uniqueIds","name","SECTIONS","SCALARS","mergeSection","defaults","merged","key","entry","normalizeConfig","input","config","result","section","detach","callbacks","OPEN","DEFAULT_TIMEOUT_MS","defaultIsFatal","frame","idCounter","newId","withToken","token","tokenParam","url","createStandaloneTransport","maxRetries","reconnect","baseMs","capMs","pingAction","ping","pingEvery","socket","connectionId","status","attempts","fatal","voluntary","connecting","retryTimer","pingTimer","handlers","statusListeners","pending","setStatus","next","prev","err","rejectAll","timer","reject","message","clearRetry","stopPing","startPing","send","scheduleReconnect","delay","connect","settle","body","ev","dispatch","h","resolveUrl","base","getToken","WebSocketImpl","target","opened","ws","resolve","msg","isFatal","evt","close","code","payload","request","request_id","timeoutMs","action","handler","cb","identity","PREFIX","SEEN_LIMIT","record","safeTime","unreadStorageKey","scope","unreadScope","userId","backend","dictionary","empty","mergeUnread","first","second","readThrough","source","room","time","unread","seen","rooms","entries","info","b","a","unreadCounts","ledger","messages","totalUnread","state","total","count","normalizeChatMessage","envelope","fingerprint","index","parseServerTime","unreadCandidate","text","ownIds","connectedAt","browserStorage$1","createUnreadStore","read","storage","save","store","createStore","commit","get","set","candidate","roomId","times","latest","stopStorageSync","onStorage","event","stop","unreadStore","useChatUnread","useStore","selector","startUnreadStorageSync","EDIT_PREFIX","REACT_PREFIX","MAX_EDIT_LENGTH","MAX_EMOJI_LENGTH$1","MAX_TRACKED","STICKER_NAME_PREFIX","isStickerAttachment","item","stickerTitle","isMessageAction","messageId","encodeEdit","targetId","encodeReaction","emoji","on","parseMessageAction","edit","data","bounded","keys","map","messageExtrasStore","author","frameId","original","previous","current","users","nextForMessage","useChatMessageExtras","groupReactions","own","byEmoji","findLastOwnEditable","preferenceKey","previewKey","channel","activeNotifications","pending$1","conversation","read$1","desktopSettings","supported","setDesktopPreviews","toggleDesktopNotifications","settings","enabled","setDesktopConversation","isVisible","onChannelMessage","pause","ms","clearDesktopNotifications","notification","notifyDesktopMessage","visible","query","isCurrent","show","storageKey","previews","sender","onClick","closeDisplayed","desktopUsers","startDesktopNotifications","stopped","MAX_CHAT_MESSAGES","PRESENCE_STATUSES","MANUAL_STATUSES","initialPresence","STALE_REPLY_MS","SEARCH_TIMEOUT_MS","PRESENCE_SYNC_MS","ACTIVITY_EVENTS","initialChatState","normalizeUsers","byId","rememberUsers","known","revokeBlobs","attachment","appendBounded","nextItems","items","fileBytes","sum","file","retainedBytes","limit","removed","createChatStore","chatGamesStore","transport","getOwnIds","isOpen","session","newSession","live","s","pruneStale","now","search","releaseUserSearch","stale","pumpUserSearch","startActivityTracker","lastSentAt","lastInputAt","sendActivity","onInput","onVisibility","options","interval","endSession","startSession","onStatus","games","receiveMessage","ownId","senderId","parsed","isIncoming","roomKey","parts","otherId","nested","gameMessage","gameText","maxMessages","isOptimistic","liveIncoming","msgId","onOpenChat","handleFrame","eventType","kind","type","groups","group","rawId","i","room_id","recipient_user_id","from_user_id","errorBody","errorAction","offEvent","offStatus","extras","kindOf","presence","onlineUsers","manual","sendMessage","attachments","tab","recipientUserId","noopUnsubscribe","IDLE","useChatConfig","useChatTransport","identity$2","useChatStore","chatStore","useChatStoreApi","readStatus","raw","readConnectionId","useChatConnection","subscribe","useCallback","unsubscribe","notify","useSyncExternalStore","sumCounts","counts","useChatUnreadTotal","valid","getSnapshot","useChatIdentity","fromTransport","idsKey","useMemo","list","DEFAULT_MAX_AGE_MS","DEFAULT_REPLAY_WINDOW_MS","CLAIM_PREFIX","PRUNE_INTERVAL_MS","isLiveMessage","effectSkipReason","arrivedAt","maxAgeMs","browserStorage","validEntry","readClaims","claimAutoEffect","recent","pruneEffectStorage","pruneTimes","field","ttlMs","debugEffect","reason","details","RECORDINGS","GESTURES","unlocked","primedAudio","primeConsumers","removeGestures","stopSharedPlayback","unlockListeners","markUnlocked","silentWavUrl","bytes","view","offset","char","binary","byte","unlockEffectAudio","primeEffectAudio","page","onGesture","disposed","playEffectSound","recording","effectId","audio","reported","failed","onBlocked","error","onError","playing","onPlaying","volume","EFFECT_PREFIX","COUNTDOWN_PREFIX","validCountdown","IDS","createEffectId","crypto","encodeEffect","sentAt","label","endsAt","decodeEffect","prefix","effectMessageText","effect","foreground","preferences","key$1","setForegroundRoom","isForegroundRoom","setEffectPreferences","getEffectPreferences","MISSED_LIMIT","rememberBackgroundEffect","takeBackgroundEffect","windowMs","pruneBackgroundEffects","CLAIM_DELAY_MS","BackgroundEffects","useRef","useEffect","lastByRoom","timers","stops","prune","consider","effects","picker","blocked","release","LiraChatProvider","injectedTransport","injectedChatStore","normalized","configRef","ownedTransport","useState","websocket","auth","ownedChatStore","onConnectionChange","stores","children","TRANSPORT_STATUSES","REQUIRED_METHODS","assertTransport","obj","missing","CUSTOMER_ID_KEY","memoryCustomerId","randomId","hex","getKlipyCustomerId","stored","configureKlipy","apiKey","locale","categoriesLocale","getApiKey","getKlipyApiRoot","getBaseUrl","ERROR_MESSAGE$1","TRUSTED_HOSTS","PREVIEW_SIZES$1","FULL_SIZES$1","getKlipyLocale","getKlipyCategoriesLocale","categoriesCache$1","isTrustedKlipyUrl","pickGif","size","sizes","media","toDimension","n","normalizeItem$1","full","preview","tag","request$1","params","response","path","toPage$1","json","hasNext","perPage","pageParams$1","withCountryLocale","toCategoriesLocale","lang","country","fetchTrendingGifs","signal","searchGifsPage","q","fetchRecentGifs","fetchGifCategories","apiLocale","cacheKey","categories","category","shareGif","slug","normalize","useChatTextSize","setSize","sync","FOCUSABLE","useFocusTrap","autoFocus","ref","active","nodes","node","last","DEFAULT_INITIAL","DEFAULT_MIN","RESIZE_KEYS","useResizable","startRef","initial","isResizing","setResizing","targetRect","targetRef","constrainSize","min","width","height","onPointerDown","rect","onPointerMove","start","endResize","step","PRESENCE_TEXT$2","ChatHeader","isPrivate","privateSubtitle","secondary","notificationRef","closeOutside","desktop","setDesktop","soundEnabled","setSoundEnabled","onToggleSidebar","showSidebar","PanelLeft","title","Hash","subtitle","Bell","BellOff","textSize","onTextSizeChange","RotateCcw","jsx","Volume2","VolumeX","onDetach","ExternalLink","onInstall","Download","onMinimize","Minimize2","onMaximize","isMaximized","onRestore","Maximize2","onClose","X","PRESENCE_TEXT$1","ConversationItem","isPerson","conv","typeClass","statusHidden","presenceText","selected","onSelect","User","Fragment","ConversationList","conversations","MessageCircle","selectedId","PRESENCE_LABELS","StatusMenu","open","setOpen","rootRef","buttonRef","onKeyDown","select","onChange","option","Check","userIdOf","displayName","PRESENCE_TEXT","secondaryOf","buildConversations","convs","privateRooms","c","knownUsers","u","presenceById","ChatSidebar","setQuery","searchQuery","groupName","setGroupName","creating","setCreating","onSearch","selfIds","currentUserIds","currentUserId","isSelf","peers","found","searchResults","onlySelf","renderUser","explicitOnline","connected","online","onSelectUser","onSetPresence","currentUserName","myPresence","onCreateGroup","presenceStatus","searchStatus","ChatEmptyState","CONFETTI_DURATION_MS","CONFETTI_CUES","AVALANCHE_DURATION_MS","AVALANCHE_CUES","EFFECT_CATALOG","getChatEffect","rand","max","jagged","points","x1","y1","x2","y2","pass","passes","ax","ay","bx","by","length","spread","createThunderScene2d","ctx","canvas","flash","bolts","sparks","x","y","startX","endX","endY","main","branches","power","dt","bolt","opacity","branch","scale","spark","t","ratio","nextWidth","nextHeight","SHAKE_STEPS","shake","frames","k","ThunderEffect","hostRef","flashRef","host","reducedMotion","mountedAt","animations","scene","track","animation","mount","factory","fallback","createThunderScene","elapsed","audioTime","clockRef","wall","waitForAudio","fire","tick","observer","prefersReducedMotion$4","ConfettiEffect","useFallback","setUseFallback","lastTime","onContextLost","createConfettiScene","peak","cue","seeded","seed","KINDS","CUE_MIX","LAND","BINS","buildLayout","range","pieces","gusts","tanks","mix","at","cueIndex","heights","half","piece","from","to","finale","LAYOUT","AvalancheFallback","startMs","still","p","g","f","prefersReducedMotion$3","flashOf","AvalancheEffect","fallbackAt","setFallbackAt","toFallback","createAvalancheScene","CONFETTI","Pig","confettiFallback","EffectScene","sound","EffectPlayer","closeRef","setBlocked","attempt","setAttempt","fallDistance","setFallDistance","update","onKey","enableSound","onReplay","player","createPortal","EffectsContext","createContext","subscribeVisibility","listener","isPageVisible","ChatEffects","globalSound","pageVisible","setActive","setSound","auto","setAuto","playbackId","lastAuto","play","eventSound","replace","changed","identityScope","missed","CountdownCard","setNow","mountedBeforeEnd","seconds","done","burst","context","EffectCard","useContext","EffectPicker","countdown","setCountdown","duration","setDuration","customDuration","setCustomDuration","customValue","setCustomValue","customUnit","setCustomUnit","finalEffect","setFinalEffect","countdownSound","setCountdownSound","sending","setSending","feedback","setFeedback","mounted","pickerRef","latestContext","durationSeconds","validDuration","selectedEffect","durationLabel","disabled","timed","sessionKey","onSend","Sparkles","sent","Icon","Zap","PartyPopper","Rocket","Loader2","ArrowUpRight","unit","Play","customEmojis","CUSTOM_EMOJI_NAME","rasterData","isCustomEmojiUrl","origin","normalizeCustomEmojis","names","searchCustomEmojis","folded","records","useCustomEmojis","catalog","InlineEmoji","setFailed","MessageText","part","safeUrl$1","fileSize","clock","VoicePlayer","audioRef","setPlaying","position","setPosition","playError","setPlayError","updateDuration","Pause","Mic","AttachmentCard","mime","sticker","visual","available","extension","FileArchive","FileSpreadsheet","FileText","history","onExpand","AlertCircle","onRemove","MediaPreview","activeImage","setActiveImage","previousFocus","VIDEO_ID","HOSTS","parseYouTubeUrl","suffix","findYouTubeVideo","candidates","video","YouTubePreview","loadSources","modules","mod","EMOJI_SHORTCUTS","SPANISH_ALIASES","normalizeEmojiQuery","TONE_RE","identity$1","baseIdentity","asList","capitalize","compact","COMPONENT_GROUP","SKIN_TONES","buildCategories","emojiCategories","legacyByEmoji","alias","curatedByEmoji","toneOfHex","tones","hexcode","tone","buildSkins","byTone","skin","skins","buildUnicodeIndex","spanishByHex","spanish","english","localized","primary","githubShortcodes","emojibaseShortcodes","iamcalShortcodes","curated","shortcodes","shortcode","labelEs","keywords","customIndex","words","setOnce","buildState","primaryAliases","unicodeIndex","searchData","aliases","labels","word","keyword","aliasMap","labelMap","termMap","term","customByCode","loaded","loading","listeners","isEmojiDataLoaded","subscribeEmojiData","loadEmojiData","ensureEmojiData","TIER","NO_MATCH","scoreWord","best","scoreQuery","score","worst","searchEmojiShortcodes","results","getEmojisByCategory","getEmojiRecord","applySkinTone","itemOrEmoji","level","resolveEmojiShortcode","STORAGE_KEY$1","LEGACY_RECENTS_KEY","MAX_EMOJI_LENGTH","hasWindow$2","CONTROL_CHARS","sanitizeEmoji","sanitizeSkinTone","cleanList$1","out","EMPTY","parse","readStorage$1","writeStorage$1","migrateLegacy","wrote","legacy","recents","createEmojiPreferencesStore","favorites","rest","syncRefs","migrated","emojiPreferencesStore","useEmojiPreferences","startEmojiPreferencesSync","useEmojiDataReady","ready","categoryIcons","Clock","Star","Smile","Hand","Puzzle","PawPrint","Utensils","Car","Trophy","Lightbulb","Heart","Flag","CELL_SIZE","ESTIMATED_COLUMNS","LONG_PRESS_MS","resolveRecord","customRecords","EmojiCell","memo","longPressed","clear","favorite","onPreview","onToggleFavorite","onPick","EmojiSection","cellProps","setVisible","lazy","minHeight","EmojiPicker","skinTone","addRecent","toggleFavorite","setSkinTone","emojiReady","toneOpen","setToneOpen","activeSection","setActiveSection","setPreview","bodyRef","searchRef","scrollFrame","favoriteSet","toValue","trimmed","sections","wrap","firstItem","shown","updateActive","top","scrollToSection","focusCell","cell","columnsOf","cells","grid","onBodyKeyDown","grids","all","gridIndex","cols","prevCols","lastRowStart","currentTone","navTabs","previewFav","previewCode","QUICK_REACTIONS","ReactionPicker","setFull","quickRef","onCloseRef","handlePointerDown","choose","align","buttons","Plus","ChatPeopleContext","useChatPeople","MAX_NAMES","BUMP_MS","prefersReducedMotion$2","ReactionBar","ownIdList","bumped","setBumped","prevCounts","grown","reactions","copy","nameOf","resolveName","titleFor","userIds","mine","onToggle","ReactionBar_default","MessageBubble","quoteUnavailable","setQuoteUnavailable","copyState","setCopyState","pickerOpen","setPickerOpen","reactBtnRef","quote","date","timestamp","validDate","isSticker","hasReactions","closePicker","bubbleClass","isMine","isEditing","senderName","onJumpQuote","onReact","v","SmilePlus","onEdit","Pencil","onReply","Reply","onCopy","Copy","createGamePanelStore","minimized","gamePanelStore","useGamePanelStore","SyncControls","onAdoptOffer","onResync","GameCard","isHost","game","isGuest","isParticipant","myTurn","controlsDisabled","canMove","terminal","board","variant","soundControls","ChevronDown","onDismiss","column","onMove","ArrowDown","row","occupied","owner","rowIndex","winning","col","onDropSettled","onAccept","onDecline","onRetry","GameCard_default","_typeof","o","toPrimitive","e","r","toPropertyKey","_defineProperty","LAZY_CARDS","lazyCards","lazyCard","LazyCardFallback","LazyCardErrorBoundary","Component","_args","ConnectedGameCard","gameKey","Card","Suspense","act","run","ConnectedGameCard_default","GameTimelineEntry","inPanel","Gamepad2","validTime","MessageList","scrollRef","nearBottom","hasNew","setHasNew","scrollToBottom","prevLength","grew","editingId","Paperclip","previousTimed","sameDay","gap","grouped","occurrence","panelGameKey","onEditMessage","matches","LIMIT_SECONDS","useVoiceRecorder","setSeconds","setError","sessionRef","mountedRef","callbackRef","onRecorded","finish","cancelled","stream","mimeType","recorder","blob","failure","MAX_VARIANTS","STOPWORDS","SPORTS_TERMS","AVOID_TERMS","PHRASE_RULES","WORDS","EN_WORDS","normalizeQuery","tokenize","kept","squash","lev","j","cur","rowMin","COMPILED_RULES","findRule","padded","bestScore","rule","translateWord","uniq","arr","expandGifQuery","tokens","isEnglish","translated","enPhrase","idx","variants","push","match","intent","sports","factor","exact","en","hasMeme","RANK_DECAY","TITLE_PHRASE","TAG_PHRASE","TITLE_TOKEN","TAG_TOKEN","PARTIAL_PHRASE","AVOID_PENALTY","EMPTY_PENALTY","PROTECT_TOP","PROTECT_SLACK","norm","keyOf$1","prepareTerms","prep","intentTerms","avoidTerms","prepareItem","tags","tagText","intentMatch","bonus","matched","doc","hits","tk","scoreWith","prior","rank","variantWeight","terms","rankGifs","expansion","noIntent","seq","weight","protectedRank","gi","sorted","pinned","maxIdx","hasGoodResults","STORAGE_KEY","hasWindow$1","safeUrl","dimension","sanitizeItem","savedAt","cleanList","readStorage","writeStorage","idOf","createGifLibraryStore","gifLibraryStore","useGifLibrary","startGifLibrarySync","CACHE_TTL_MS","CACHE_MAX","MAX_VARIANTS_PAGE1","MAX_VARIANTS_NEXT","APPROX_NOTICE","cache","inflight","makeAbortError","isAbortError","cacheGet","cacheSet","cachedRequest","hit","controller","fetcher","shared","settled","onAbort","keyOf","normalizeResult","res","loadTrending","loadVariant","pickVariants","picked","originalNorm","orig","loadSearch","firstError","hasMore","notice","loadRecent","local","loadFavorites","favs","loadGifFeed","DEFAULT_CATEGORY_ID","GIF_CATEGORIES","Flame","Laugh","Frown","Angry","Eye","HandHeart","Music","CATEGORY_SYNONYMS","safeNormalize","matchKeys","findKlipyMatch","klipyCategories","mergeKlipyCategories","klipy","cat","kq","prefersReducedMotion$1","GifCategoryBar","scrollerRef","chipRefs","canPrev","setCanPrev","canNext","setCanNext","updateOverflow","el","ro","onWheel","before","chip","activeId","scrollByPage","dir","handleKeyDown","hasActive","ChevronLeft","focusable","ChevronRight","GifCategoryBar_default","WIDE_BREAKPOINT","PREVIEW_DELAY","SKELETON_RATIOS","ratioOf","w","distribute","columns","getRatio","prefersReducedMotion","isFocusVisible","GifTile","setLoaded","broken","setBroken","previewFailed","setPreviewFailed","timerRef","aspectRatio","canPreview","showPreview","clearTimer","startPreview","immediate","stopPreview","fav","findNeighbor","container","fx","fy","btn","cx","cy","dx","dy","GifGrid","containerRef","sentinelRef","setCols","handlersRef","stableSelect","stableToggle","stateRef","intersectingRef","lastFiredCountRef","requestMore","scrollKey","root","sentinel","skeletonColumns","showSkeletons","showEmpty","EmptyIcon","isFavorite","PER_PAGE$1","SEARCH_DEBOUNCE_MS$1","isSafeGif","gif","getEmptyState","SearchX","ImageOff","GifPicker","categoryId","setCategoryId","klipyCats","setKlipyCats","setItems","setLoading","setPage","setHasMore","setNotice","requestRef","versionRef","favoriteIds","cats","activeCategory","trimmedQuery","feedQuery","libraryKey","feedRef","loadPage","version","src","pageNum","safe","append","handleLoadMore","handleRetry","handleCategorySelect","handleSelect","handleToggleFavorite","Search","getStickersUrl","PREVIEW_SIZES","FULL_SIZES","FORMATS","ERROR_MESSAGE","categoriesCache","getStickerCustomerId","pickMedia","format","normalizeItem","toPage","pageParams","fetchTrendingStickers","searchStickers","fetchRecentStickers","fetchStickerCategories","previewUrl","shareSticker","toStickerAttachment","PER_PAGE","SEARCH_DEBOUNCE_MS","EMPTY_TEXT","requestFor","mode","StickerPicker","setMode","setActiveCategory","setCategories","stickers","setStickers","previewItem","setPreviewItem","gridRef","loadMoreRef","prevTabRef","loadStickers","more","loadMode","loadTerm","handleQueryChange","selectTab","nextMode","handleGridKeyDown","firstTop","isTabSelected","tabMode","shortcuts","findEmojiToken","cursor","face","RESULT_LIMIT","RECENT_POOL_LIMIT","recentValue","stripVariation","foldText","HighlightedShortcode","EmojiAutocomplete","suggestions","setSuggestions","selectedIndex","setSelectedIndex","dropdownRef","shortcodeStartRef","listId","useId","optionId","valueFor","recentList","textareaRef","cursorPos","pool","ranked","insertEmoji","textarea","end","onInsert","newPos","dismiss","display","suggestion","DEFAULT_GAME_TYPES","GAME_MENU","CircleDot","Anchor","Crosshair","RACE_CLASS_MENU","TANK_MAP_MENU","TANK_LIVES_MENU","MessageComposer","composerRef","pickerHeight","setPickerHeight","pickerAvailableHeight","setPickerAvailableHeight","pickerResizeRef","fileInputRef","gameMenuRef","gameButtonRef","popover","setPopover","raceMenu","setRaceMenu","raceTrack","setRaceTrack","tankMenu","setTankMenu","tankMap","setTankMap","autocompleteOpen","setAutocompleteOpen","handleAutocompleteClose","handleAutocompleteInsert","voice","onAddAttachment","sendingMedia","sendingTitle","canSend","editing","pickerKind","reply","composer","parent","resize","chooseGame","handleGameMenuKeyDown","fromGames","onCancelEdit","onStartEditLast","handlePaste","files","handleInputChange","newValue","caret","completed","attachmentError","onCancelReply","onRemoveAttachment","Square","onInviteGame","onOpenBattleshipPreview","gameInviteDisabled","onSendEffect","Clapperboard","Sticker","Send","hint","lives","gameTypes","Box","GripHorizontal","ChatGamePanel","keepMounted","canDismiss","setMinimized","ChevronUp","ChatWindow$1","setTextSize","dialogRef","setShowSidebar","battleshipPreview","setBattleshipPreview","isFullscreen","setFullscreen","wide","standalone","resizable","resizeHandleProps","listVisible","showingConversation","isMinimized","selectRoom","onSelectRoom","trapFocus","placement","theme","effectScope","effectIdentityScope","effectsConfig","headerType","Grip","headerSecondary","headerPresence","onToggleMaximize","installHelp","onDismissInstallHelp","ArrowLeft","gamePanelKey","BattleshipPreviewComponent","effectError","gameError","inputValue","onInputChange","installPrompt","hasWindow","notifyInstall","installUsers","removeInstallListeners","startChatApp","onPrompt","onInstalled","useChatInstall","installed","setInstalled","setAvailable","setInstallHelp","prompt","chatPopup","openChatWindow","windowName","registerChatWorker","swUrl","MAX_PREVIEW_BYTES","useChatController","installation","rawEffectsConfig","gamesFeatures","features","effectCooldowns","effectPending","setEffectError","useShallow","chatIdentity","effectConnection","websocketStatus","unreadRooms","rawPrivateRooms","rawKnownUsers","setReply","setEditing","setGameError","edits","chatState","setInputValue","setAttachments","sendingRef","objectUrls","setAttachmentError","attachmentRef","activeRoom","gameScope","gameKeys","gameMessages","hasLiveGame","gamePanels","handleSelectUser","recipientId","existingRoom","openPrivateChat","people","fetchGroups","presenceTrigger","searchUsers","userSearchQuery","urls","chatMessages","timeline","inferredType","selectChat","startEdit","cancelEdit","handleReact","handleSend","sendChatMessage","outgoingAttachments","quoted","handleAddAttachment","removeAttachment","peer","wait","setMyPresence","userSearchResults","userSearchStatus","setUserSearchQuery","opponentId","gameType","createGroup","chatUiStore","useChatUi","isChatEscapeTarget","useChatLayout","alwaysOpen","controlled","storeOpen","setMaximized","isControlled","onConfigOpenChange","canMinimize","minimize","restore","toggleMinimize","toggleMaximize","pwa","handleKey","POPUP_BLOCKED","portalTarget","ModalFrame","frameRef","trap","ChatWindow","layout","chat","floating","canDetach","shell","content","className","ChatPage","ChatButton","isPressed","pressed","iconSize","badgeClassName","running","call","args","nav","method","onFail","isAppBadgeRunning","startAppBadge","apply","retry","schedule","ChatNotifications","notifications","badge","MAX_BYTES","sessions","sessionFor","relayRequest","consumeRelayEvent","hydrateRelayMessage","closeRelay","sendRelayMessage","outgoing","chunk","WebRtcLab","MINICODE_CHAT_VERSION","loadBattleshipPreview"],"sources":["../src/config/normalizeConfig.js","../src/core/transport/createStandaloneTransport.js","../src/core/unread/unreadMessages.js","../src/core/extras/messageExtras.js","../src/notifications/desktopNotifications.js","../src/core/chat/createChatStore.js","../src/provider/hooks.js","../src/effects/autoPlay.js","../src/effects/effectAudio.js","../src/effects/protocol.js","../src/effects/backgroundEffects.js","../src/effects/BackgroundEffects.jsx","../src/provider/LiraChatProvider.jsx","../src/core/transport/chatTransport.js","../src/media/klipy/klipyCustomer.js","../src/media/klipy/klipy.js","../src/ui/hooks/useChatTextSize.js","../src/ui/hooks/useFocusTrap.js","../src/ui/hooks/useResizable.js","../src/ui/components/ChatHeader.jsx","../src/ui/components/ConversationItem.jsx","../src/ui/components/ConversationList.jsx","../src/ui/components/StatusMenu.jsx","../src/ui/components/ChatSidebar.jsx","../src/ui/components/ChatEmptyState.jsx","../src/effects/confetti/timeline.js","../src/effects/avalanche/timeline.js","../src/effects/catalog.js","../src/effects/thunder/thunderScene2d.js","../src/effects/thunder/ThunderEffect.jsx","../src/effects/confetti/ConfettiEffect.jsx","../src/effects/avalanche/AvalancheFallback.jsx","../src/effects/avalanche/AvalancheEffect.jsx","../src/effects/EffectPlayer.jsx","../src/effects/ChatEffects.jsx","../src/media/emoji/customEmojis.js","../src/media/emoji/customEmojiCatalog.js","../src/media/emoji/useCustomEmojis.js","../src/ui/components/MessageText.jsx","../src/ui/components/MediaPreview.jsx","../src/media/youtube/youtubeLinks.js","../src/ui/components/YouTubePreview.jsx","../src/media/emoji/emojiShortcodes.js","../src/media/emoji/emojiPreferences.js","../src/media/emoji/useEmojiData.js","../src/ui/components/EmojiPicker.jsx","../src/ui/components/ReactionPicker.jsx","../src/ui/chatPeopleContext.js","../src/ui/components/ReactionBar.jsx","../src/ui/components/MessageBubble.jsx","../src/games/shared/useGamePanelStore.js","../src/games/connect4/GameCard.jsx","../src/games/shared/ConnectedGameCard.jsx","../src/games/shared/GameTimelineEntry.jsx","../src/ui/components/MessageList.jsx","../src/ui/hooks/useVoiceRecorder.js","../src/media/gif-search/gifQueryExpansion.js","../src/media/gif-search/gifRelevance.js","../src/media/gif-search/gifLibrary.js","../src/media/gif-search/gifSearchEngine.js","../src/media/gif-search/gifCategories.js","../src/ui/components/GifCategoryBar.jsx","../src/ui/components/GifGrid.jsx","../src/ui/components/GifPicker.jsx","../src/media/klipy/klipyStickers.js","../src/ui/components/StickerPicker.jsx","../src/media/emoji/emojiAutocompleteToken.js","../src/ui/components/EmojiAutocomplete.jsx","../src/ui/components/MessageComposer.jsx","../src/games/shared/ChatGamePanel.jsx","../src/ui/components/ChatWindow.jsx","../src/pwa/chatApp.js","../src/ui/connected/useChatController.js","../src/ui/connected/chatUiStore.js","../src/ui/connected/useChatLayout.js","../src/ui/connected/ChatWindow.jsx","../src/ui/connected/ChatPage.jsx","../src/ui/connected/ChatButton.jsx","../src/notifications/appBadge.js","../src/ui/connected/ChatNotifications.jsx","../src/core/relay/fileRelay.js","../src/net/webrtc/index.js","../src/index.js"],"sourcesContent":["// Applies defaults to the public config schema (doc §3.2). Each section is\n// shallow-merged over its defaults; the result is frozen (one level deep).\n\nconst noop = () => {};\n\nexport const DEFAULT_CONFIG = Object.freeze({\n websocket: Object.freeze({\n url: null,\n reconnect: Object.freeze({ max: 3, baseMs: 1000, capMs: 10000 }),\n ping: false,\n legacyRoomIdRouting: true,\n }),\n webrtc: Object.freeze({ iceServers: undefined, iceTransportPolicy: 'all' }),\n auth: Object.freeze({ getToken: null, tokenParam: 'token' }),\n user: null,\n scope: null,\n features: Object.freeze({\n reactions: true, editing: true, replies: true, files: true, voice: true,\n gifs: true, stickers: true, youtube: true, presence: true, groups: true, privateChats: true,\n games: Object.freeze({ connect4: true, battleship: true, battleshipPreview: true, tanks: false, tanksLive: false, racingLive: false }),\n detach: Object.freeze({ path: '/chat', windowName: 'lira-independent-chat' }),\n install: true,\n }),\n theme: Object.freeze({ mode: 'auto', tokens: Object.freeze({}), fontSize: 14 }),\n media: Object.freeze({\n klipy: false,\n emoji: Object.freeze({ custom: [], lazy: true }),\n maxAttachmentBytes: 10 * 1024 * 1024,\n trustedMediaHosts: Object.freeze(['static.klipy.com', 'media.klipy.com', 'cdn.klipy.com']),\n }),\n notifications: Object.freeze({ desktop: true, previews: false, sound: true, appBadge: true }),\n effects: Object.freeze({ enabled: true, sound: true, backgroundSound: true, volume: 0.35, autoPlay: true, cooldownMs: 5000, maxAgeMs: 10000, allowGroups: false }),\n assets: Object.freeze({ baseUrl: null }),\n storage: Object.freeze({ prefix: 'lira', adapter: undefined }),\n locale: 'es',\n portalContainer: undefined,\n callbacks: Object.freeze({\n onError: noop, onOpenChange: noop, onOpenConversation: noop,\n onUnreadChange: noop, onConnectionChange: noop,\n }),\n});\n\nconst isPlainObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);\n\n/**\n * Normalizes the host user to `{ id, ids, name }` (strings; frozen). Accepts LIRA/Cognito-like\n * shapes: `id`/`user_id`/`sub` and `name`/`username`/`email`. Returns null without an id.\n */\nexport function normalizeUser(user) {\n if (!isPlainObject(user)) return null;\n const id = user.id ?? user.user_id ?? null;\n const ids = Array.isArray(user.ids) ? user.ids : [id, user.user_id, user.sub];\n const uniqueIds = [...new Set(ids.filter((value) => value != null && String(value) !== '').map(String))];\n const name = user.name || user.username || user.email || null;\n if (id == null && !uniqueIds.length) return null;\n return Object.freeze({ id: id == null ? uniqueIds[0] : String(id), ids: Object.freeze(uniqueIds), name });\n}\n\nconst SECTIONS = ['websocket', 'webrtc', 'auth', 'features', 'theme', 'media', 'notifications', 'effects', 'assets', 'storage', 'callbacks'];\nconst SCALARS = ['user', 'scope', 'locale', 'portalContainer'];\n\nfunction mergeSection(defaults, value) {\n if (value === false) return false; // e.g. features disabled wholesale\n if (!isPlainObject(value)) return defaults;\n const merged = { ...defaults };\n for (const [key, entry] of Object.entries(value)) if (entry !== undefined) merged[key] = entry;\n return Object.freeze(merged);\n}\n\nexport function normalizeConfig(config = {}) {\n const input = isPlainObject(config) ? config : {};\n const result = { ...input };\n for (const section of SECTIONS) result[section] = mergeSection(DEFAULT_CONFIG[section], input[section]);\n for (const key of SCALARS) result[key] = input[key] === undefined ? DEFAULT_CONFIG[key] : input[key];\n result.user = normalizeUser(result.user);\n // PWA / detached window: `pwa.path`/`pwa.windowName` win over `features.detach`.\n const detach = isPlainObject(result.features?.detach) ? result.features.detach : DEFAULT_CONFIG.features.detach;\n result.pwa = Object.freeze({ ...detach, ...(isPlainObject(input.pwa) ? input.pwa : {}) });\n // Nested objects that callers commonly pass partially.\n if (isPlainObject(result.media) && isPlainObject(input.media?.emoji)) {\n result.media = Object.freeze({ ...result.media, emoji: mergeSection(DEFAULT_CONFIG.media.emoji, input.media.emoji) });\n }\n if (isPlainObject(result.websocket) && isPlainObject(input.websocket?.reconnect)) {\n result.websocket = Object.freeze({ ...result.websocket, reconnect: Object.freeze({ ...DEFAULT_CONFIG.websocket.reconnect, ...input.websocket.reconnect }) });\n }\n if (isPlainObject(result.features) && isPlainObject(input.features?.games)) {\n result.features = Object.freeze({ ...result.features, games: Object.freeze({ ...DEFAULT_CONFIG.features.games, ...input.features.games }) });\n }\n if (isPlainObject(result.callbacks)) {\n const callbacks = { ...result.callbacks };\n for (const key of Object.keys(DEFAULT_CONFIG.callbacks)) if (typeof callbacks[key] !== 'function') callbacks[key] = noop;\n result.callbacks = Object.freeze(callbacks);\n }\n return Object.freeze(result);\n}\n","// Transporte WebSocket propio del paquete para backends distintos de LIRA.\n// Misma semántica que connectSocket de LIRA (backoff, isFatal, request/ACK de fileRelay).\n\n/** @typedef {import('./chatTransport.js').ChatTransport} ChatTransport */\n/** @typedef {import('./chatTransport.js').TransportStatus} TransportStatus */\n/** @typedef {import('./chatTransport.js').InboundFrame} InboundFrame */\n\nconst OPEN = 1;\nconst DEFAULT_TIMEOUT_MS = 15000;\n\nconst defaultIsFatal = (frame) =>\n frame?.type === 'ERROR' && /no esta habilitado/.test(frame?.data?.message ?? '');\n\nlet idCounter = 0;\nconst newId = () => {\n try {\n if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();\n } catch {\n /* fallback */\n }\n idCounter += 1;\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}-${idCounter}`;\n};\n\nconst withToken = (url, token, tokenParam) => {\n if (!token) return url;\n const re = new RegExp(`[?&]${tokenParam}=`);\n if (re.test(url)) return url;\n const sep = url.includes('?') ? '&' : '?';\n return `${url}${sep}${tokenParam}=${encodeURIComponent(token)}`;\n};\n\n/**\n * @param {{\n * url: string | (() => string | Promise<string>),\n * getToken?: () => (string | null | undefined | Promise<string | null | undefined>),\n * tokenParam?: string,\n * reconnect?: { max?: number, baseMs?: number, capMs?: number },\n * isFatal?: (frame: InboundFrame) => boolean,\n * ping?: false | { action?: string, everyMs: number },\n * identity?: () => { userId: string|null, scope: string },\n * WebSocketImpl?: typeof WebSocket,\n * }} opts\n * @returns {ChatTransport}\n */\nexport function createStandaloneTransport({\n url,\n getToken,\n tokenParam = 'token',\n reconnect = { max: 3, baseMs: 1000, capMs: 10000 },\n isFatal = defaultIsFatal,\n ping = false,\n identity = () => ({ userId: null, scope: '' }),\n WebSocketImpl = globalThis.WebSocket,\n} = {}) {\n const maxRetries = reconnect?.max ?? 3;\n const baseMs = reconnect?.baseMs ?? 1000;\n const capMs = reconnect?.capMs ?? 10000;\n const pingAction = ping ? ping.action ?? 'PING' : null;\n const pingEvery = ping ? ping.everyMs : 0;\n\n /** @type {WebSocket|null} */\n let socket = null;\n let connectionId = null;\n /** @type {TransportStatus} */\n let status = 'idle';\n let attempts = 0;\n let fatal = false;\n let voluntary = false;\n let connecting = null;\n let retryTimer = null;\n let pingTimer = null;\n\n const handlers = new Set();\n const statusListeners = new Set();\n const pending = new Map(); // request_id -> { resolve, reject, timer }\n\n const setStatus = (next) => {\n if (next === status) return;\n const prev = status;\n status = next;\n statusListeners.forEach((cb) => {\n try {\n cb(next, prev);\n } catch (err) {\n console.error('[chat] status listener error', err);\n }\n });\n };\n\n const rejectAll = (message) => {\n pending.forEach(({ reject, timer }) => {\n clearTimeout(timer);\n reject(new Error(message));\n });\n pending.clear();\n };\n\n const clearRetry = () => {\n if (retryTimer) clearTimeout(retryTimer);\n retryTimer = null;\n };\n\n const stopPing = () => {\n if (pingTimer) clearInterval(pingTimer);\n pingTimer = null;\n };\n\n const startPing = () => {\n stopPing();\n if (!pingAction || !(pingEvery > 0)) return;\n pingTimer = setInterval(() => send(pingAction), pingEvery);\n };\n\n const scheduleReconnect = () => {\n if (fatal || voluntary || attempts >= maxRetries) return;\n const delay = Math.min(capMs, 2 ** attempts * baseMs);\n attempts += 1;\n clearRetry();\n retryTimer = setTimeout(() => {\n retryTimer = null;\n connect().catch(() => {});\n }, delay);\n };\n\n const settle = (ev, body, frame) => {\n const entry = pending.get(body.request_id);\n if (!entry) return false;\n clearTimeout(entry.timer);\n pending.delete(body.request_id);\n if (ev === 'CHAT_ACK') {\n entry.resolve(frame);\n } else {\n const err = new Error(body.message || 'No se pudo enviar');\n if (body.code !== undefined) err.code = body.code;\n entry.reject(err);\n }\n return true;\n };\n\n const dispatch = (frame) => {\n const ev = frame?.event ?? frame?.type;\n const body = frame?.data ?? frame?.payload ?? {};\n if ((ev === 'CHAT_ACK' || ev === 'ERROR') && body?.request_id != null) {\n if (settle(ev, body, frame)) return;\n }\n if (pingAction && ev === 'PONG') return;\n for (const h of handlers) {\n try {\n if (h(frame) === true) return;\n } catch (err) {\n console.error('[chat] transport handler error', err);\n }\n }\n };\n\n const resolveUrl = async () => {\n const base = typeof url === 'function' ? await url() : url;\n if (!base) throw new Error('[chat] createStandaloneTransport: url vacía');\n const token = getToken ? await getToken() : null;\n return withToken(String(base), token, tokenParam);\n };\n\n function connect() {\n if (socket && (socket.readyState === OPEN || socket.readyState === 0)) return Promise.resolve();\n if (connecting) return connecting;\n if (!WebSocketImpl) return Promise.reject(new Error('[chat] WebSocket no disponible'));\n\n voluntary = false;\n fatal = false;\n clearRetry();\n setStatus('connecting');\n\n connecting = (async () => {\n let target;\n try {\n target = await resolveUrl();\n } catch (err) {\n setStatus('error');\n scheduleReconnect();\n throw err;\n }\n if (voluntary) return;\n\n await new Promise((resolve, reject) => {\n let opened = false;\n const ws = new WebSocketImpl(target);\n socket = ws;\n connectionId = newId();\n\n ws.onopen = () => {\n if (socket !== ws) return;\n opened = true;\n attempts = 0;\n setStatus('connected');\n startPing();\n resolve();\n };\n\n ws.onmessage = (msg) => {\n if (socket !== ws) return;\n let frame;\n try {\n frame = JSON.parse(msg.data);\n } catch {\n return;\n }\n if (isFatal && isFatal(frame)) fatal = true;\n dispatch(frame);\n };\n\n ws.onerror = () => {\n if (socket !== ws) return;\n setStatus('error');\n };\n\n ws.onclose = (evt) => {\n if (socket !== ws) return;\n socket = null;\n connectionId = null;\n stopPing();\n rejectAll('Conexión interrumpida. Reintenta el envío.');\n setStatus('disconnected');\n if (!opened) reject(new Error('[chat] no se pudo abrir el WebSocket'));\n if (evt?.code !== 1000) scheduleReconnect();\n };\n });\n })().finally(() => {\n connecting = null;\n });\n\n return connecting;\n }\n\n function close(code = 1000) {\n voluntary = true;\n clearRetry();\n stopPing();\n const ws = socket;\n socket = null;\n connectionId = null;\n rejectAll('Conexión cerrada');\n if (ws) {\n try {\n ws.close(code);\n } catch {\n /* ignore */\n }\n }\n setStatus('disconnected');\n }\n\n function send(action, payload) {\n if (!socket || socket.readyState !== OPEN) return false;\n try {\n socket.send(JSON.stringify(payload === undefined ? { action } : { action, payload }));\n return true;\n } catch {\n return false;\n }\n }\n\n function request(action, payload = {}, { timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {\n if (!socket || socket.readyState !== OPEN) return Promise.reject(new Error('Sin conexión'));\n const request_id = newId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(request_id);\n reject(new Error('El servidor no confirmó el envío. Conservamos el borrador.'));\n }, timeoutMs);\n pending.set(request_id, { resolve, reject, timer });\n if (!send(action, { ...payload, request_id })) {\n clearTimeout(timer);\n pending.delete(request_id);\n reject(new Error('Sin conexión'));\n }\n });\n }\n\n return {\n connect,\n close,\n send,\n request,\n onEvent(handler) {\n handlers.add(handler);\n return () => handlers.delete(handler);\n },\n getStatus: () => status,\n onStatus(cb) {\n statusListeners.add(cb);\n return () => statusListeners.delete(cb);\n },\n getConnectionId: () => connectionId,\n getIdentity: () => identity(),\n };\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\nconst PREFIX = 'lira-chat-unread:v1:';\nconst SEEN_LIMIT = 2000;\n/**\n * Clock skew: message timestamps come from the server while `connectedAt`/`now()` are client\n * clocks, so they are never compared with each other. The backend never replays history over\n * WebSocket: every dated frame received on an open socket is live. Id dedup (`seen`) plus the\n * per-room `readThrough` watermark (server time only) prevent double counting and reconnect\n * inflation. History-flagged and undated frames are still dropped.\n */\nconst record = (value) => value && typeof value === 'object' && !Array.isArray(value) ? value : {};\nconst safeTime = (value) => Number.isFinite(value) && value >= 0;\nexport const unreadStorageKey = (scope) => PREFIX + encodeURIComponent(scope);\nexport const unreadScope = (backend, userId) => userId == null ? null : JSON.stringify([backend, String(userId)]);\nconst dictionary = () => Object.create(null);\nconst empty = () => ({ unread: dictionary(), readThrough: dictionary(), seen: dictionary(), rooms: dictionary() });\n\n/** Merge by message identity and read watermark, including across tabs. No text is stored. */\nexport function mergeUnread(first = {}, second = {}) {\n first = record(first); second = record(second);\n const readThrough = dictionary();\n for (const source of [first, second]) {\n for (const [room, time] of Object.entries(record(source.readThrough))) {\n if (safeTime(time)) readThrough[room] = Math.max(readThrough[room] ?? 0, time);\n }\n }\n const unread = dictionary();\n const seen = dictionary();\n const rooms = dictionary();\n for (const source of [first, second]) {\n for (const [room, entries] of Object.entries(record(source.unread))) {\n for (const [id, time] of Object.entries(record(entries))) {\n if (safeTime(time) && time > (readThrough[room] ?? -1)) {\n if (!Object.hasOwn(unread, room)) Object.defineProperty(unread, room, { value: {}, enumerable: true, writable: true });\n Object.defineProperty(unread[room], id, { value: time, enumerable: true, configurable: true, writable: true });\n }\n }\n }\n for (const [id, time] of Object.entries(record(source.seen))) if (safeTime(time)) seen[id] = time;\n for (const [room, info] of Object.entries(record(source.rooms))) {\n if (info && typeof info.peerId === 'string') {\n Object.defineProperty(rooms, room, { value: { peerId: info.peerId, username: String(info.username ?? '').slice(0, 256) }, enumerable: true, configurable: true, writable: true });\n }\n }\n }\n const boundedSeen = Object.fromEntries(Object.entries(seen).sort((a, b) => b[1] - a[1]).slice(0, SEEN_LIMIT));\n return { unread, readThrough, seen: boundedSeen, rooms };\n}\nexport const unreadCounts = (ledger) => Object.fromEntries(Object.entries(ledger.unread).map(([room, messages]) => [room, Object.keys(messages).length]));\nexport const totalUnread = (state) => Object.values(state.counts).reduce((total, count) => total + count, 0);\n\nexport function normalizeChatMessage(envelope) {\n const body = record(envelope.data ?? envelope.payload);\n return { ...body, ...envelope,\n room_id: envelope.room_id ?? body.room_id, user_id: envelope.user_id ?? body.user_id,\n message: envelope.message ?? body.message, text: envelope.text ?? body.text,\n id: envelope.message_id ?? envelope.id ?? body.message_id ?? body.id,\n timestamp: envelope.timestamp ?? body.timestamp,\n };\n}\n// Synchronous compact fingerprint only for legacy messages without a server ID.\n// Persisting a fallback identifier must not persist the message body or file URL.\nfunction fingerprint(value) {\n let first = 2166136261; let second = 5381;\n for (let index = 0; index < value.length; index += 1) {\n first = Math.imul(first ^ value.charCodeAt(index), 16777619);\n second = Math.imul(second, 33) ^ value.charCodeAt(index);\n }\n return `${value.length}:${(first >>> 0).toString(16)}:${(second >>> 0).toString(16)}`;\n}\n// Django isoformat() may carry microseconds (\"…:00.123456+00:00\"); older Safari rejects >3 digits.\nexport function parseServerTime(value) {\n if (typeof value !== 'string') return NaN;\n return Date.parse(value.replace(/(\\.\\d{3})\\d+/, '$1'));\n}\nexport function unreadCandidate(envelope, ownIds, connectedAt) {\n const message = normalizeChatMessage(envelope);\n const text = message.message ?? message.text ?? '';\n const type = envelope.event ?? envelope.type;\n if (type !== 'CHAT_MESSAGE' || !message.room_id || message.user_id == null\n || ownIds.map(String).includes(String(message.user_id))\n || message.localOnly || message.optimistic || message.is_history || message.history || message.replay\n || message.kind === 'game' || message.content?.kind === 'game'\n || (typeof text === 'string' && (text.startsWith('LIRA_GAME_') || text.startsWith('LIRA_WEBRTC_')))) return null;\n if (!(typeof text === 'string' && text.trim()) && !message.attachments?.length && !message.attachment) return null;\n const time = parseServerTime(message.timestamp);\n // Undated frames cannot be proved live; nothing counts before the socket is open.\n if (!Number.isFinite(time) || !Number.isFinite(connectedAt)) return null;\n const room = String(message.room_id);\n const id = JSON.stringify([room, message.id ?? fingerprint(JSON.stringify([String(message.user_id), message.timestamp, text, message.attachments ?? message.attachment ?? null]))]);\n return { room, id, time, peerId: String(message.user_id), username: message.username ?? '' };\n}\n\nconst browserStorage = () => { try { return globalThis.localStorage; } catch { return null; } };\nexport function createUnreadStore({ storage = browserStorage } = {}) {\n const read = (scope) => {\n try { return mergeUnread(empty(), JSON.parse(storage()?.getItem(unreadStorageKey(scope)) ?? '{}')); }\n catch { return empty(); }\n };\n const save = (scope, ledger) => {\n try { storage()?.setItem(unreadStorageKey(scope), JSON.stringify(ledger)); } catch { /* Keep in-memory counts if storage is unavailable/full. */ }\n };\n const store = createStore((set, get) => {\n const commit = (ledger) => {\n const scope = get().scope;\n save(scope, ledger);\n set({ ledger, counts: unreadCounts(ledger) });\n };\n return {\n scope: null, ledger: empty(), counts: {}, visibleRoom: null,\n activateScope: (scope) => {\n if (scope === get().scope) return;\n const ledger = scope ? read(scope) : empty();\n set({ scope, ledger, counts: unreadCounts(ledger), visibleRoom: null });\n },\n receive: (message, { ownIds, connectedAt }) => {\n if (!get().scope) return false;\n const candidate = unreadCandidate(message, ownIds, connectedAt);\n if (!candidate) return false;\n const { room, id, time, peerId, username } = candidate;\n const ledger = mergeUnread(read(get().scope), get().ledger);\n if (Object.hasOwn(ledger.seen, id) || Object.hasOwn(ledger.unread[room] ?? {}, id)\n || time <= (ledger.readThrough[room] ?? -1)) {\n set({ ledger, counts: unreadCounts(ledger) });\n return false;\n }\n ledger.seen[id] = time;\n if (room.startsWith('private_')) ledger.rooms[room] = { peerId, username };\n // Watermarks track server time; the client clock only acts as a skew-tolerant floor so a\n // client running ahead never swallows later live messages once the room is hidden again.\n if (get().visibleRoom === room) ledger.readThrough[room] = Math.max(ledger.readThrough[room] ?? 0, time);\n else ledger.unread[room] = { ...ledger.unread[room], [id]: time };\n commit(mergeUnread(ledger));\n return true;\n },\n setVisibleRoom: (roomId) => {\n const room = roomId == null ? null : String(roomId);\n set({ visibleRoom: room });\n if (room !== null) get().markRead(room);\n },\n markRead: (roomId) => {\n if (!get().scope || roomId == null) return;\n const room = String(roomId);\n const ledger = mergeUnread(read(get().scope), get().ledger);\n const times = Object.values(ledger.unread[room] ?? {});\n ledger.readThrough[room] = times.reduce((latest, time) => Math.max(latest, time),\n ledger.readThrough[room] ?? 0);\n commit(mergeUnread(ledger));\n },\n syncStorage: () => {\n if (!get().scope) return;\n const ledger = mergeUnread(read(get().scope), get().ledger);\n set({ ledger, counts: unreadCounts(ledger) });\n if (get().visibleRoom !== null && get().counts[get().visibleRoom] > 0) get().markRead(get().visibleRoom);\n },\n };\n });\n let stopStorageSync = null;\n /** Cross-tab sync via `storage` events. Idempotent per store; returns `stop()`. */\n store.startStorageSync = () => {\n if (stopStorageSync) return stopStorageSync;\n if (typeof window === 'undefined') return () => {};\n const onStorage = (event) => {\n const scope = store.getState().scope;\n if (scope && event.key === unreadStorageKey(scope)) store.getState().syncStorage();\n };\n window.addEventListener('storage', onStorage);\n const stop = () => {\n window.removeEventListener('storage', onStorage);\n if (stopStorageSync === stop) stopStorageSync = null;\n };\n stopStorageSync = stop;\n return stop;\n };\n return store;\n}\nconst unreadStore = createUnreadStore();\n/** Backward-compatible singleton hook (with vanilla store API attached). */\nexport const useChatUnread = Object.assign((selector) => useStore(unreadStore, selector), {\n getState: unreadStore.getState, setState: unreadStore.setState, subscribe: unreadStore.subscribe,\n});\n/** Cross-tab sync via `storage` events. Idempotent; returns `stop()` which removes the listener. */\nexport function startUnreadStorageSync(store = unreadStore) {\n return (store === useChatUnread ? unreadStore : store).startStorageSync();\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n/**\n * Edits and reactions without backend support: they travel as ordinary\n * CHAT_MESSAGE frames with a versioned prefix (same idea as LIRA_GAME_V1:).\n * The backend stamps user_id, so authorship cannot be forged:\n * - an edit applies only when its author is the original message's author;\n * - a reaction is attributed to the author of the reaction frame.\n * Nothing is persisted server-side: clients that were offline never see them,\n * exactly like ordinary messages (the relay keeps no history).\n * Unread counters already ignore every \"LIRA_\" prefixed frame.\n */\nexport const EDIT_PREFIX = 'LIRA_EDIT_V1:';\nexport const REACT_PREFIX = 'LIRA_REACT_V1:';\nexport const MAX_EDIT_LENGTH = 9000;\nconst MAX_EMOJI_LENGTH = 32;\nconst MAX_TRACKED = 1000;\n\n// Stickers reuse the backend's GIF attachment contract ({kind:'gif', url, name});\n// the name prefix is the only field the backend keeps that can mark them.\nexport const STICKER_NAME_PREFIX = 'sticker:';\nexport const isStickerAttachment = (item) => typeof item?.name === 'string' && item.name.startsWith(STICKER_NAME_PREFIX);\nexport const stickerTitle = (item) => (isStickerAttachment(item) ? item.name.slice(STICKER_NAME_PREFIX.length) : item?.name) || 'Sticker';\n\nexport const isMessageAction = (text) => typeof text === 'string' && (text.startsWith(EDIT_PREFIX) || text.startsWith(REACT_PREFIX));\n\nexport const messageId = (message) => {\n const id = message?.message_id ?? message?.id;\n return id == null ? null : String(id);\n};\n\nexport const encodeEdit = ({ targetId, text }) => EDIT_PREFIX + JSON.stringify({ target_id: String(targetId), text: String(text).slice(0, MAX_EDIT_LENGTH) });\nexport const encodeReaction = ({ targetId, emoji, on }) => REACT_PREFIX + JSON.stringify({ target_id: String(targetId), emoji: String(emoji), on: Boolean(on) });\n\n/** { type: 'edit', targetId, text } | { type: 'react', targetId, emoji, on } | null */\nexport function parseMessageAction(text) {\n if (!isMessageAction(text)) return null;\n const edit = text.startsWith(EDIT_PREFIX);\n let data;\n try { data = JSON.parse(text.slice((edit ? EDIT_PREFIX : REACT_PREFIX).length)); } catch { return null; }\n if (!data || typeof data !== 'object' || typeof data.target_id !== 'string' || !data.target_id) return null;\n if (edit) {\n if (typeof data.text !== 'string' || !data.text.trim() || data.text.length > MAX_EDIT_LENGTH) return null;\n return { type: 'edit', targetId: data.target_id, text: data.text };\n }\n if (typeof data.emoji !== 'string' || !data.emoji || data.emoji.length > MAX_EMOJI_LENGTH) return null;\n return { type: 'react', targetId: data.target_id, emoji: data.emoji, on: data.on !== false };\n}\n\nconst bounded = (map) => {\n const keys = Object.keys(map);\n if (keys.length <= MAX_TRACKED) return map;\n const next = { ...map };\n keys.slice(0, keys.length - MAX_TRACKED).forEach((key) => { delete next[key]; });\n return next;\n};\n\n/**\n * edits: { [messageId]: { text, editedAt } }\n * reactions: { [messageId]: { [emoji]: string[] userIds } } (insertion order kept)\n */\nexport const createMessageExtrasStore = () => createStore((set, get) => ({\n edits: {},\n reactions: {},\n seen: {},\n /**\n * Applies one action frame. `original` is the target message (or null when it\n * never reached this client: the action is ignored). Returns true if applied.\n */\n apply: (frame, original) => {\n const text = frame?.message ?? frame?.text;\n const action = parseMessageAction(text);\n const author = frame?.user_id == null ? null : String(frame.user_id);\n const frameId = messageId(frame);\n if (!action || !author || !original) return false;\n if (frameId && get().seen[frameId]) return false;\n if (String(original.room_id) !== String(frame.room_id) || messageId(original) !== action.targetId) return false;\n const seen = frameId ? bounded({ ...get().seen, [frameId]: true }) : get().seen;\n if (action.type === 'edit') {\n if (String(original.user_id) !== author) return false;\n const previous = get().edits[action.targetId];\n if (previous && previous.editedAt && frame.timestamp && previous.editedAt > frame.timestamp) { set({ seen }); return false; }\n set({ seen, edits: bounded({ ...get().edits, [action.targetId]: { text: action.text, editedAt: frame.timestamp ?? null } }) });\n return true;\n }\n const current = get().reactions[action.targetId] ?? {};\n const users = (current[action.emoji] ?? []).filter((id) => id !== author);\n if (action.on) users.push(author);\n const nextForMessage = { ...current, [action.emoji]: users };\n if (!users.length) delete nextForMessage[action.emoji];\n set({ seen, reactions: bounded({ ...get().reactions, [action.targetId]: nextForMessage }) });\n return true;\n },\n reset: () => set({ edits: {}, reactions: {}, seen: {} }),\n}));\n\nconst messageExtrasStore = createMessageExtrasStore();\n/** Backward-compatible singleton hook (with vanilla store API attached). */\nexport const useChatMessageExtras = Object.assign((selector) => useStore(messageExtrasStore, selector), {\n getState: messageExtrasStore.getState, setState: messageExtrasStore.setState, subscribe: messageExtrasStore.subscribe,\n});\n\n/** Groups reactions for display: [{ emoji, count, mine, userIds }]. */\nexport function groupReactions(byEmoji, ownIds = []) {\n const own = new Set(ownIds.filter((id) => id != null).map(String));\n return Object.entries(byEmoji || {})\n .filter(([, users]) => users?.length)\n .map(([emoji, users]) => ({ emoji, count: users.length, mine: users.some((id) => own.has(String(id))), userIds: users }));\n}\n\n/** Last own, editable (has text, not a game/action/local-only) message of a list, or null. */\nexport function findLastOwnEditable(messages, ownIds) {\n const own = new Set((ownIds || []).filter((id) => id != null).map(String));\n for (let index = (messages?.length ?? 0) - 1; index >= 0; index -= 1) {\n const message = messages[index];\n const text = message?.message ?? message?.text;\n if (message?.gameKey || message?.localOnly || !messageId(message) || !own.has(String(message.user_id))) continue;\n if (typeof text === 'string' && text.trim() && !isMessageAction(text)) return message;\n }\n return null;\n}\n","import { randomUuid } from '../core/ids/randomUuid.js';\n// Separate from sound notifications: permission is requested only by the header button.\nconst preferenceKey = 'lira-chat-desktop';\nconst previewKey = 'lira-chat-desktop-previews';\nlet channel = null;\nconst seen = new Set();\nconst activeNotifications = new Set();\nconst pending = new Map();\nlet conversation = null;\nconst read = (key) => { try { return localStorage.getItem(key) === 'true'; } catch { return false; } };\nexport function desktopSettings() {\n const supported = typeof window !== 'undefined' && window.isSecureContext && 'Notification' in window;\n return { supported, permission: supported ? Notification.permission : 'unsupported', enabled: read(preferenceKey), previews: read(previewKey) };\n}\nexport function setDesktopPreviews(value) {\n try { localStorage.setItem(previewKey, String(value)); } catch { /* Unavailable storage leaves previews off. */ }\n window.dispatchEvent(new Event('lira-desktop-settings'));\n}\nexport async function toggleDesktopNotifications() {\n const settings = desktopSettings();\n if (!settings.supported) return;\n let enabled = false;\n if (!settings.enabled || settings.permission !== 'granted') {\n try { enabled = (await Notification.requestPermission()) === 'granted'; } catch { /* Browser declined. */ }\n }\n try { localStorage.setItem(preferenceKey, String(enabled)); } catch { /* No persistent opt-in. */ }\n window.dispatchEvent(new Event('lira-desktop-settings'));\n}\nexport function setDesktopConversation(value) { conversation = value; }\nconst isVisible = (scope, room) => conversation?.scope === scope && String(conversation.room) === String(room)\n && conversation.open && document.visibilityState === 'visible' && document.hasFocus();\nconst onChannelMessage = ({ data }) => {\n if (data?.type === 'visible-query' && isVisible(data.scope, data.room)) channel?.postMessage({ type: 'visible', id: data.id });\n if (data?.type === 'visible') pending.get(data.id)?.();\n if (data?.type === 'shown') seen.add(data.id);\n if (seen.size > 500) seen.delete(seen.values().next().value);\n};\nconst pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\nexport function clearDesktopNotifications() {\n activeNotifications.forEach((notification) => notification.close());\n activeNotifications.clear();\n conversation = null;\n}\nexport async function notifyDesktopMessage(message, { scope, room, id, onClick, connectedAt, isCurrent }) {\n const settings = desktopSettings();\n if (!settings.supported || !settings.enabled || settings.permission !== 'granted' || room == null || !id) return;\n // Live CHAT_MESSAGE events only. Reject stale replays, history and undated events.\n const time = Date.parse(message.timestamp);\n if (!Number.isFinite(time) || time < connectedAt || message.localOnly || message.optimistic || message.is_history || message.history) return;\n const key = `${scope}:${id}`;\n if (seen.has(key)) return;\n seen.add(key);\n if (seen.size > 500) seen.delete(seen.values().next().value);\n let visible = isVisible(scope, room);\n const query = randomUuid();\n pending.set(query, () => { visible = true; });\n channel?.postMessage({ type: 'visible-query', id: query, scope, room });\n await pause(150);\n pending.delete(query);\n if (visible || isVisible(scope, room) || !isCurrent()) return;\n const show = async () => {\n // Persist only identifiers, never message text. Shared across Dashboard and popup.\n const storageKey = `lira-chat-desktop-seen:${key}`;\n try {\n if (localStorage.getItem(storageKey)) return;\n localStorage.setItem(storageKey, String(Date.now()));\n // Bounded retention, also protects against replay after reload/reconnect.\n const keys = Object.keys(localStorage).filter((item) => item.startsWith('lira-chat-desktop-seen:'));\n if (keys.length > 500) keys.sort((a, b) => Number(localStorage.getItem(a)) - Number(localStorage.getItem(b))).slice(0, keys.length - 500).forEach((item) => localStorage.removeItem(item));\n } catch { return; } // Avoid duplicates when cross-window storage is unavailable.\n if (!isCurrent() || !desktopSettings().enabled || Notification.permission !== 'granted' || isVisible(scope, room)) return;\n // Do not expose private conversations or explicitly private content in system UI.\n const previews = read(previewKey) && !String(room).startsWith('private') && !message.private && !message.sensitive;\n const sender = String(message.username || 'Nuevo mensaje').replace(/\\s+/g, ' ').slice(0, 70);\n const body = previews ? String(message.message || message.text || 'Archivo adjunto').replace(/\\s+/g, ' ').slice(0, 140) : 'Tienes un nuevo mensaje en LIRA Chat';\n try {\n const notification = new Notification(previews ? sender : 'LIRA Chat', { body, tag: key, silent: true });\n activeNotifications.add(notification);\n notification.onclose = () => activeNotifications.delete(notification);\n notification.onclick = () => { notification.close(); if (isCurrent()) { window.focus(); onClick(); } };\n channel?.postMessage({ type: 'shown', id: key });\n } catch { /* Some browsers expose permission but do not support desktop constructors. */ }\n };\n try {\n if (navigator.locks) await navigator.locks.request(`lira-desktop:${key}`, show);\n else {\n // A shared notification tag and storage claim provide best-effort fallback.\n await pause(Math.random() * 100);\n await show();\n }\n } catch { /* Notifications must never interrupt WebSocket processing. */ }\n}\n\n// Remove displayed previews when privacy preferences or account state change.\nconst closeDisplayed = () => { activeNotifications.forEach((item) => item.close()); activeNotifications.clear(); };\nconst onStorage = (event) => { if (!event.key || event.key === preferenceKey || event.key === previewKey) closeDisplayed(); };\n\n// Ref-counted, idempotent: channel and listeners are created once; the last stop() tears them down.\nlet desktopUsers = 0;\nexport function startDesktopNotifications() {\n if (typeof window === 'undefined') return () => {};\n if (desktopUsers++ === 0) {\n channel = typeof BroadcastChannel === 'function' ? new BroadcastChannel('lira-chat-desktop') : null;\n channel?.addEventListener('message', onChannelMessage);\n window.addEventListener('lira-desktop-settings', closeDisplayed);\n window.addEventListener('storage', onStorage);\n }\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n if (--desktopUsers === 0) {\n window.removeEventListener('lira-desktop-settings', closeDisplayed);\n window.removeEventListener('storage', onStorage);\n channel?.removeEventListener('message', onChannelMessage);\n channel?.close();\n channel = null;\n }\n };\n}\n","import { createStore } from 'zustand/vanilla';\nimport { useChatUnread, normalizeChatMessage } from '../unread/unreadMessages.js';\nimport { isMessageAction, messageId, parseMessageAction, useChatMessageExtras } from '../extras/messageExtras.js';\nimport { chatGamesStore } from '../../games/shared/useChatGames.js';\nimport { GAME_PREFIX } from '../../games/shared/protocol.js';\nimport { isWebrtcMessage } from '../../net/webrtc/protocol.js';\nimport { rtcSignals } from '../../net/webrtc/rtcSignals.js';\nimport { notifyDesktopMessage, clearDesktopNotifications } from '../../notifications/desktopNotifications.js';\nimport { initChatSounds, requestNotification } from '../../notifications/chatSounds.js';\n\n// Chat domain store (messages, rooms, presence, user search) driven by a ChatTransport.\n// Moved from LIRA's useWebSocket.js (phase 9b). Wire format is frozen by test/contract.\n// The old \"same socket?\" checks are now \"same connection id?\" (transport.getConnectionId()).\n\nexport const MAX_CHAT_MESSAGES = 500;\nexport const PRESENCE_STATUSES = ['online', 'away', 'busy'];\nexport const MANUAL_STATUSES = ['auto', 'busy', 'invisible'];\nconst initialPresence = { status: 'online', manual: 'auto' };\nconst STALE_REPLY_MS = 15000;\nconst SEARCH_TIMEOUT_MS = 10000;\nconst PRESENCE_SYNC_MS = 30000;\nconst ACTIVITY_EVENTS = ['pointerdown', 'keydown', 'wheel', 'touchstart', 'focus'];\n\nconst initialChatState = () => ({\n chatMessages: [],\n chatState: {\n activeTab: 'chats', // 'chats' | 'users' | 'groups'\n currentChat: null, // { id, type: 'group' | 'private' } or null when nothing is selected\n availableGroups: [],\n },\n onlineUsers: [],\n presenceStatus: 'idle',\n userSearchResults: [],\n userSearchQuery: '',\n userSearchStatus: 'idle',\n privateRooms: {},\n knownUsers: {}, // user_id -> last known info, keeps private chat names after the user goes offline\n myPresence: { ...initialPresence }, // status: online | away | busy | invisible (from MY_STATUS); manual: auto | busy | invisible\n});\n\nexport const normalizeUsers = (users) => {\n const byId = new Map();\n for (const user of Array.isArray(users) ? users : []) {\n if (!user || typeof user !== 'object' || (user.user_id ?? user.id) == null) continue;\n const id = String(user.user_id ?? user.id);\n if (id) byId.set(id, { ...user, user_id: id });\n }\n return [...byId.values()];\n};\nconst rememberUsers = (known, users) => ({ ...known, ...Object.fromEntries(users.map((user) => [user.user_id, user])) });\n\nconst revokeBlobs = (message) => {\n for (const attachment of message?.attachments || []) {\n if (attachment.url?.startsWith('blob:')) URL.revokeObjectURL(attachment.url);\n }\n};\nexport const appendBounded = (items, item, limit) => {\n const nextItems = [...items, item];\n const fileBytes = (message) => (message.attachments || []).reduce((sum, file) => sum + (file.url?.startsWith('blob:') ? file.size || 0 : 0), 0);\n let retainedBytes = nextItems.reduce((sum, message) => sum + fileBytes(message), 0);\n while (nextItems.length > limit || retainedBytes > 64 * 1024 * 1024) {\n const removed = nextItems.shift();\n retainedBytes -= fileBytes(removed);\n revokeBlobs(removed);\n }\n return nextItems;\n};\n\n/**\n * @param {object} options\n * @param {import('../transport/chatTransport.js').ChatTransport} options.transport\n * @param {(roomId: string, message: string, attachments?: any[]) => Promise<void>} [options.sendMessage]\n * Defaults to a CHAT_MESSAGE request without attachments (hosts with file relay inject theirs).\n * @param {() => string[]} [options.getOwnIds] Every id form of the current user (id, user_id, sub).\n * @param {(room: string) => void} [options.onOpenChat] Desktop notification click (after selectChat).\n * @param {number} [options.maxMessages]\n */\nexport function createChatStore({\n transport,\n sendMessage,\n getOwnIds,\n onOpenChat,\n maxMessages = MAX_CHAT_MESSAGES,\n games = chatGamesStore,\n unread = useChatUnread,\n extras = useChatMessageExtras,\n} = {}) {\n const identity = () => transport.getIdentity?.() ?? { userId: null, scope: '' };\n const ownIds = () => (getOwnIds ? getOwnIds() : [identity().userId].filter((id) => id != null).map(String));\n const connectionId = () => transport.getConnectionId?.() ?? null;\n const isOpen = () => transport.getStatus?.() === 'connected';\n const send = (action, payload) => transport.send(action, payload);\n\n // Per-connection runtime state (the old WeakMaps keyed by socket).\n let session = null;\n const newSession = (id) => ({\n id, joinedRooms: new Set(), connectedAt: Date.now(),\n search: { active: null, queue: [], timer: null, deltas: new Map(), lastPresence: 0, stale: [] },\n presenceTimer: null, stopActivity: null,\n });\n const live = (s) => s && session === s && connectionId() === s.id && isOpen();\n\n return createStore((set, get) => {\n const pruneStale = (search) => {\n const now = Date.now();\n search.stale = search.stale.filter((item) => now - item.at < STALE_REPLY_MS);\n };\n\n // Releases the active slot (timeout / server error) and moves on to the next query.\n const releaseUserSearch = (s, { stale = false } = {}) => {\n const search = s.search;\n const query = search.active;\n if (query === null) return;\n clearTimeout(search.timer);\n search.timer = null;\n search.active = null;\n search.deltas.clear();\n if (stale) search.stale = [...search.stale, { query, at: Date.now() }].slice(-5);\n if (session !== s) return;\n if (!query) set({ presenceStatus: 'error' });\n else if (query === get().userSearchQuery) set({ userSearchStatus: 'error' });\n pumpUserSearch(s);\n };\n\n // The server does not echo query/request IDs. Serialize searches on each connection\n // and keep only the latest queued text query, separately from presence refreshes.\n const pumpUserSearch = (s) => {\n const search = s.search;\n if (search.active !== null || !search.queue.length || !live(s)) return;\n const query = search.queue.shift();\n search.active = query;\n search.deltas.clear();\n if (!query) set({ presenceStatus: 'loading' });\n else if (query === get().userSearchQuery) set({ userSearchStatus: 'loading' });\n send('SEARCH_USERS', { query });\n search.timer = setTimeout(() => {\n if (session !== s || search.active !== query) return;\n // Free the slot; the untagged late reply is discarded via search.stale.\n releaseUserSearch(s, { stale: true });\n }, SEARCH_TIMEOUT_MS);\n };\n\n // Activity detector, one per connection. Listeners only record input; ACTIVITY is\n // throttled to once a minute, except when leaving 'away' (sent right away).\n const startActivityTracker = (s) => {\n if (typeof window === 'undefined') return;\n // The connect itself counts as activity on the server.\n let lastSentAt = Date.now();\n let lastInputAt = lastSentAt;\n const sendActivity = () => {\n if (!live(s)) return;\n send('ACTIVITY', {});\n lastSentAt = Date.now();\n };\n const onInput = () => {\n lastInputAt = Date.now();\n if (get().myPresence.status === 'away' && lastInputAt - lastSentAt > 5000) sendActivity();\n };\n const onVisibility = () => { if (document.visibilityState === 'visible') onInput(); };\n const options = { passive: true };\n ACTIVITY_EVENTS.forEach((name) => window.addEventListener(name, onInput, options));\n document.addEventListener('visibilitychange', onVisibility, options);\n const interval = setInterval(() => {\n if (!live(s)) return;\n if (lastInputAt > lastSentAt && Date.now() - lastSentAt >= 60000) sendActivity();\n }, 15000);\n s.stopActivity = () => {\n clearInterval(interval);\n ACTIVITY_EVENTS.forEach((name) => window.removeEventListener(name, onInput, options));\n document.removeEventListener('visibilitychange', onVisibility, options);\n };\n };\n\n const endSession = () => {\n const s = session;\n if (!s) return;\n session = null;\n clearTimeout(s.search.timer);\n clearInterval(s.presenceTimer);\n s.stopActivity?.();\n };\n\n const startSession = () => {\n endSession();\n const s = newSession(connectionId());\n session = s;\n initChatSounds();\n s.presenceTimer = setInterval(() => { if (live(s)) get().searchUsers(''); }, PRESENCE_SYNC_MS);\n startActivityTracker(s);\n };\n\n const onStatus = (status, previous) => {\n if (status === 'connected') {\n if (!session || session.id !== connectionId()) startSession();\n return;\n }\n if (previous === 'connected' || session) {\n // Connection lost: search slots and presence belong to the old connection.\n get().resetUserSearch();\n endSession();\n games.getState().markDisconnected?.(identity().scope);\n }\n };\n\n const receiveMessage = (parsed) => {\n // Sound/notification only for incoming (not own, not optimistic) messages.\n const ids = ownIds();\n const ownId = identity().userId;\n const senderId = parsed.user_id ?? parsed.payload?.user_id ?? parsed.data?.user_id;\n const isIncoming = senderId != null && ownId != null && !ids.includes(String(senderId));\n // Register the private conversation even if PRIVATE_INVITED was missed (e.g. after reconnect).\n const roomKey = String(parsed.room_id ?? parsed.data?.room_id ?? parsed.payload?.room_id ?? '');\n const parts = roomKey.startsWith('private_') ? roomKey.slice('private_'.length).split('_') : [];\n if (parts.length === 2 && parts.includes(ownId)) {\n const otherId = parts.find((id) => id !== ownId);\n if (otherId && get().privateRooms[otherId] !== roomKey) {\n set((state) => ({ privateRooms: { ...state.privateRooms, [otherId]: roomKey } }));\n }\n }\n if (senderId != null && parsed.username && !get().knownUsers[String(senderId)]) {\n set((state) => ({ knownUsers: { ...state.knownUsers, [String(senderId)]: { user_id: String(senderId), username: parsed.username } } }));\n }\n const nested = parsed.data ?? parsed.payload;\n const gameMessage = nested && typeof nested === 'object' ? { ...nested, ...parsed,\n message: parsed.message ?? nested.message, text: parsed.text ?? nested.text,\n room_id: parsed.room_id ?? nested.room_id, user_id: senderId,\n } : parsed;\n const gameText = gameMessage.message ?? gameMessage.text;\n // Edit/reaction frames modify an earlier message; they are never shown or counted.\n if (isMessageAction(gameText)) {\n const targetId = parseMessageAction(gameText)?.targetId;\n const original = targetId && get().chatMessages.map((item) => {\n const body = item.data ?? item.payload;\n return body && typeof body === 'object' ? { ...item, ...body } : item;\n }).find((item) => messageId(item) === targetId);\n extras.getState().apply(gameMessage, original || null);\n return;\n }\n // WebRTC signaling (LIRA_WEBRTC_V1:) is routed to peer links, never shown or counted.\n if (isWebrtcMessage(gameText)) {\n rtcSignals.emit({ userId: String(senderId ?? ''), roomId: String(gameMessage.room_id ?? ''), text: gameText });\n return;\n }\n const scope = identity().scope;\n if (typeof gameText === 'string' && gameText.startsWith(GAME_PREFIX) && String(gameMessage.room_id ?? '').startsWith('private_')) {\n games.getState().ingest(gameMessage, { scope, currentUserId: ownId });\n return;\n }\n set((state) => ({ chatMessages: appendBounded(state.chatMessages, parsed, maxMessages) }));\n const connectedAt = session?.connectedAt ?? Infinity;\n const isOptimistic = parsed.localOnly === true;\n const liveIncoming = unread.getState().receive(parsed, { ownIds: ids, connectedAt });\n const msgId = parsed.message_id ?? parsed.id ?? `${parsed.room_id}:${senderId}:${parsed.timestamp}`;\n if (!isIncoming || isOptimistic || !liveIncoming) return;\n requestNotification(msgId);\n if ((parsed.event || parsed.type) !== 'CHAT_MESSAGE') return;\n const message = normalizeChatMessage(parsed);\n const room = message.room_id;\n const s = session;\n void notifyDesktopMessage(message, {\n scope, room,\n id: message.message_id ?? message.id ?? `${room}:${senderId}:${message.timestamp}`,\n connectedAt,\n isCurrent: () => session === s && identity().userId === ownId,\n onClick: () => {\n if (session !== s || identity().userId == null) return;\n get().selectChat(room, String(room).startsWith('private') ? 'private' : 'group');\n onOpenChat?.(room);\n },\n });\n };\n\n // Returns true when the frame belongs to the chat domain (consumed).\n const handleFrame = (parsed) => {\n if (!parsed || typeof parsed !== 'object') return false;\n const { event: eventType, data, payload, type } = parsed;\n const kind = parsed.event ?? parsed.type;\n\n if (eventType === 'GROUPS_LIST' || type === 'groups_list') {\n const groups = data || payload;\n set((state) => ({ chatState: { ...state.chatState, availableGroups: groups } }));\n // Public channels stay subscribed while viewing other chats. Private rooms\n // need no CHAT_JOIN: they arrive through the user_{id} group.\n const s = session;\n (Array.isArray(groups) ? groups : []).forEach((group) => {\n const roomId = group?.id;\n if (roomId == null || String(roomId).startsWith('private_') || !s || s.joinedRooms.has(roomId)) return;\n s.joinedRooms.add(roomId);\n send('CHAT_JOIN', { room_id: roomId });\n });\n return true;\n }\n\n if (parsed.room_id || eventType === 'CHAT_MESSAGE' || type === 'CHAT_MESSAGE') {\n receiveMessage(parsed);\n return true;\n }\n\n // Subscription acks are not messages.\n if (eventType === 'CHAT_JOINED' || eventType === 'CHAT_LEFT') return true;\n\n if (kind === 'SEARCH_RESULTS') {\n get().receiveUserSearch(parsed);\n return true;\n }\n\n if (kind === 'USER_ONLINE') {\n const source = parsed.user ?? data?.user ?? payload?.user;\n const user = normalizeUsers([source])[0];\n if (user) {\n if (session?.search.active === '') session.search.deltas.set(user.user_id, user);\n set((state) => ({\n onlineUsers: [...state.onlineUsers.filter((item) => item.user_id !== user.user_id), user],\n knownUsers: rememberUsers(state.knownUsers, [user]),\n }));\n }\n return true;\n }\n\n if (kind === 'USER_OFFLINE') {\n const rawId = parsed.user_id ?? data?.user_id ?? payload?.user_id;\n if (rawId != null) {\n const userId = String(rawId);\n if (session?.search.active === '') session.search.deltas.set(userId, null);\n set((state) => ({ onlineUsers: state.onlineUsers.filter((user) => user.user_id !== userId) }));\n }\n return true;\n }\n\n if (kind === 'MY_STATUS') {\n const body = { ...(data ?? payload ?? {}), ...parsed };\n set((state) => ({ myPresence: {\n status: [...PRESENCE_STATUSES, 'invisible'].includes(body.status) ? body.status : state.myPresence.status,\n manual: MANUAL_STATUSES.includes(body.manual) ? body.manual : state.myPresence.manual,\n } }));\n return true;\n }\n\n if (kind === 'USER_STATUS') {\n const body = { ...(data ?? payload ?? {}), ...parsed };\n if (body.user_id == null || !PRESENCE_STATUSES.includes(body.status)) return true;\n const userId = String(body.user_id);\n const { status } = body;\n // A presence snapshot in flight would otherwise overwrite this change.\n if (session?.search.active === '') {\n const pending = session.search.deltas.get(userId);\n const current = pending === undefined ? get().onlineUsers.find((user) => user.user_id === userId) : pending;\n if (current) session.search.deltas.set(userId, { ...current, status });\n }\n set((state) => {\n const known = state.knownUsers[userId];\n const index = state.onlineUsers.findIndex((user) => user.user_id === userId);\n if (index === -1 && !known) return state;\n const onlineUsers = index === -1 ? state.onlineUsers\n : state.onlineUsers.map((user, i) => (i === index ? { ...user, status } : user));\n return { onlineUsers, knownUsers: known ? { ...state.knownUsers, [userId]: { ...known, status } } : state.knownUsers };\n });\n return true;\n }\n\n if (eventType === 'PRIVATE_RESOLVED') {\n const { room_id, recipient_user_id } = data || payload || {};\n if (room_id && recipient_user_id) {\n set((state) => ({ privateRooms: { ...state.privateRooms, [recipient_user_id]: room_id } }));\n get().selectChat(room_id, 'private');\n }\n return true;\n }\n\n if (eventType === 'PRIVATE_INVITED') {\n const { room_id, from_user_id } = data || payload || {};\n if (room_id && from_user_id) {\n set((state) => ({ privateRooms: { ...state.privateRooms, [from_user_id]: room_id } }));\n }\n return true;\n }\n\n if (kind === 'ERROR') {\n const errorBody = data ?? payload ?? {};\n const errorAction = parsed.action ?? errorBody.action;\n if (session && (errorAction === 'SEARCH_USERS' || String(errorBody.message ?? '').includes('SEARCH_USERS'))) {\n // Replies are ordered per connection: the error belongs to the oldest pending request.\n pruneStale(session.search);\n if (session.search.stale.length) session.search.stale.shift();\n else releaseUserSearch(session);\n }\n return false; // the host still reports the error\n }\n\n return false;\n };\n\n let detach = null;\n\n return {\n ...initialChatState(),\n\n // Subscribes to the transport. Idempotent; returns detach().\n attach: () => {\n if (detach) return detach;\n const offEvent = transport.onEvent(handleFrame);\n const offStatus = transport.onStatus(onStatus);\n if (isOpen()) startSession();\n detach = () => {\n offEvent?.();\n offStatus?.();\n endSession();\n detach = null;\n };\n return detach;\n },\n handleFrame,\n\n // Logout / identity change: release browser-only files and private conversation state.\n reset: () => {\n get().resetUserSearch();\n endSession();\n if (isOpen()) startSession();\n clearDesktopNotifications();\n get().chatMessages.forEach(revokeBlobs);\n set(initialChatState());\n extras.getState().reset();\n },\n\n //////////////////// --- SEARCH USER --- ////////////////////\n setUserSearchQuery: (value) => {\n const query = String(value ?? '').trim().toLowerCase();\n if (query === get().userSearchQuery) return;\n if (session) session.search.queue = session.search.queue.filter((item) => item === '');\n set({ userSearchQuery: query, userSearchResults: [], userSearchStatus: query ? 'loading' : 'idle' });\n },\n\n searchUsers: (value = '') => {\n const s = session;\n if (!live(s)) return;\n const query = String(value).trim().toLowerCase();\n if (query && query !== get().userSearchQuery) return;\n const search = s.search;\n if (search.active === query || search.queue.includes(query)) return;\n if (!query && Date.now() - search.lastPresence < 500) return;\n if (query) search.queue = search.queue.filter((item) => item === '');\n search.queue.push(query);\n pumpUserSearch(s);\n },\n\n receiveUserSearch: (message) => {\n const s = session;\n if (!s) return;\n const search = s.search;\n const body = message.data ?? message.payload;\n const result = body && typeof body === 'object' ? { ...body, ...message } : message;\n // is_full_list true <=> presence ('') request; false <=> text query; absent = unknown.\n const kind = result.is_full_list === true ? 'presence' : result.is_full_list === false ? 'text' : null;\n const kindOf = (item) => (item === '' ? 'presence' : 'text');\n pruneStale(search);\n if (search.stale.length) {\n if (!kind || kindOf(search.stale[0].query) === kind) {\n search.stale.shift(); // Late reply of a timed-out request.\n return;\n }\n // Replies are ordered: a reply matching the active request means the stale ones were lost.\n if (search.active === null || kindOf(search.active) !== kind) return;\n search.stale = [];\n }\n const query = search.active;\n if (query === null) return; // Unsolicited/duplicate uncorrelated response.\n if (kind && kindOf(query) !== kind) return; // Does not belong to the active request.\n clearTimeout(search.timer);\n search.timer = null;\n search.active = null;\n if (!Array.isArray(result.users)) {\n set(query ? { userSearchStatus: 'error' } : { presenceStatus: 'error' });\n pumpUserSearch(s);\n return;\n }\n const users = normalizeUsers(result.users);\n if (query === '') {\n const presence = new Map(users.map((user) => [user.user_id, user]));\n for (const [id, user] of search.deltas) {\n if (user) presence.set(id, user);\n else presence.delete(id);\n }\n const onlineUsers = [...presence.values()];\n search.lastPresence = Date.now();\n set((state) => ({ onlineUsers, presenceStatus: 'ready', knownUsers: rememberUsers(state.knownUsers, onlineUsers) }));\n } else if (query === get().userSearchQuery) {\n set((state) => ({ userSearchResults: users, userSearchStatus: 'ready', knownUsers: rememberUsers(state.knownUsers, users) }));\n }\n search.deltas.clear();\n pumpUserSearch(s);\n },\n\n resetUserSearch: () => {\n if (session) {\n clearTimeout(session.search.timer);\n session.search = newSession(session.id).search;\n }\n set({ onlineUsers: [], presenceStatus: 'idle', userSearchResults: [], userSearchQuery: '', userSearchStatus: 'idle' });\n },\n //////////////////// --- SEARCH USER --- ////////////////////\n\n // Manual presence: 'auto' | 'busy' | 'invisible'. The effective status arrives via MY_STATUS.\n setMyPresence: (manual) => {\n if (!MANUAL_STATUSES.includes(manual) || !send('SET_STATUS', { status: manual })) return false;\n set((state) => ({ myPresence: { ...state.myPresence, manual } }));\n return true;\n },\n\n //////////////////// --- ACCIONES DE CHAT --- ////////////////////\n joinChat: (roomId) => { send('CHAT_JOIN', { room_id: roomId }); },\n leaveChat: (roomId) => { send('CHAT_LEAVE', { room_id: roomId }); },\n\n sendChatMessage: (roomId, message, attachments = []) => {\n if (sendMessage) return sendMessage(roomId, message, attachments);\n if (attachments.length) return Promise.reject(new Error('Este transporte no admite adjuntos.'));\n return transport.request('CHAT_MESSAGE', { room_id: roomId, message, attachments: [] }).then(() => undefined);\n },\n\n setChatTab: (tab) => set((state) => ({ chatState: { ...state.chatState, activeTab: tab } })),\n\n // Selecting from a notification/list is not a read until its panel is visible.\n selectChat: (id, type) => set((state) => ({ chatState: { ...state.chatState, currentChat: { id, type } } })),\n\n searchOnlineUsers: (query) => { get().setUserSearchQuery(query); get().searchUsers(query); },\n createGroup: (name) => { send('CREATE_GROUP', { name }); },\n fetchGroups: () => { send('FETCH_GROUPS'); },\n openPrivateChat: (recipientUserId) => { send('OPEN_PRIVATE', { recipient_user_id: recipientUserId }); },\n //////////////////// --- ACCIONES DE CHAT --- ////////////////////\n };\n });\n}\n","import { useCallback, useMemo, useSyncExternalStore } from 'react';\nimport { useStore } from 'zustand';\nimport { useChatContext } from './ChatContext.js';\n\nconst noopUnsubscribe = () => {};\nconst IDLE = 'idle';\n\nexport const useChatConfig = () => useChatContext().config;\nexport const useChatTransport = () => useChatContext().transport ?? null;\n\nconst identity = (state) => state;\n// Selector over the provider's chat domain store (createChatStore).\nexport function useChatStore(selector = identity) {\n const { chatStore } = useChatContext();\n if (!chatStore) throw new Error('LiraChatProvider sin chatStore: pasa `transport` o `chatStore`');\n return useStore(chatStore, selector);\n}\nexport const useChatStoreApi = () => useChatContext().chatStore ?? null;\n\n// getStatus() may return a string or `{ status, connectionId }`.\nconst readStatus = (transport) => {\n const raw = transport?.getStatus?.();\n if (raw && typeof raw === 'object') return raw.status ?? IDLE;\n return raw ?? IDLE;\n};\nconst readConnectionId = (transport) => {\n const raw = transport?.getStatus?.();\n if (raw && typeof raw === 'object' && 'connectionId' in raw) return raw.connectionId ?? null;\n if (typeof transport?.getConnectionId === 'function') return transport.getConnectionId() ?? null;\n return transport?.connectionId ?? null;\n};\n\nexport function useChatConnection() {\n const transport = useChatTransport();\n const subscribe = useCallback((notify) => {\n if (!transport?.onStatus) return noopUnsubscribe;\n const unsubscribe = transport.onStatus(notify);\n return typeof unsubscribe === 'function' ? unsubscribe : noopUnsubscribe;\n }, [transport]);\n const status = useSyncExternalStore(subscribe, () => readStatus(transport), () => IDLE);\n const connectionId = useSyncExternalStore(subscribe, () => readConnectionId(transport), () => null);\n return { status, connectionId };\n}\n\nconst sumCounts = (counts) => {\n if (!counts || typeof counts !== 'object') return 0;\n let total = 0;\n for (const value of Object.values(counts)) total += Number(value) || 0;\n return total;\n};\n\n// `stores.unread`: zustand vanilla store or bound hook (anything with getState/subscribe).\nexport function useChatUnreadTotal() {\n const unread = useChatContext().stores?.unread;\n const valid = Boolean(unread && typeof unread.getState === 'function' && typeof unread.subscribe === 'function');\n const subscribe = useCallback(\n (notify) => (valid ? unread.subscribe(notify) : noopUnsubscribe),\n [unread, valid],\n );\n const getSnapshot = () => (valid ? sumCounts(unread.getState()?.counts) : 0);\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Current chat identity: `{ userId, ids, name, scope }`. userId/scope come from\n * `transport.getIdentity()` when available, else from `config.user`/`config.scope`.\n * Re-evaluated on render (config changes and connection status changes re-render consumers).\n */\nexport function useChatIdentity() {\n const { config, transport } = useChatContext();\n const { status } = useChatConnection();\n const fromTransport = transport?.getIdentity?.() ?? null;\n const user = config?.user ?? null;\n const userId = fromTransport?.userId ?? user?.id ?? null;\n const scope = fromTransport?.scope || config?.scope || (userId == null ? '' : String(userId));\n const idsKey = (user?.ids ?? []).join('|');\n const ids = useMemo(() => {\n const list = [...(idsKey ? idsKey.split('|') : [])];\n if (userId != null && !list.includes(String(userId))) list.unshift(String(userId));\n return list;\n }, [idsKey, userId]);\n return { userId: userId == null ? null : String(userId), ids, name: user?.name ?? null, scope, status };\n}\n","// Pure rules for automatic playback of incoming effects (no React, testable in Node).\n// The sender clock (`sentAt`) is never compared with the receiver clock: any skew between\n// devices used to drop every received effect. Freshness comes from live arrival (local\n// clock only). Neither sender nor server clocks can be compared to the receiver clock.\n\nexport const SKEW_TOLERANCE_MS = 120000;\nexport const DEFAULT_MAX_AGE_MS = 10000;\nexport const DEFAULT_REPLAY_WINDOW_MS = 120000;\nexport const CLAIM_TTL_MS = 120000;\nexport const CLAIM_LIMIT = 100;\nexport const CLAIM_PREFIX = 'minicode-effects-seen:';\nexport const PRUNE_INTERVAL_MS = 30000;\n\n/** History, replays, optimistic and local echoes never auto-play. */\nexport const isLiveMessage = (message) => Boolean(message)\n && ![message, message.data, message.payload].some((body) => body &&\n (body.localOnly || body.history || body.is_history || body.replay || body.optimistic));\n\n/** Server-stamped time of a message (ISO string, possibly with microseconds, or epoch ms), or NaN. */\nexport function serverTimeOf(message) {\n const value = message?.timestamp ?? message?.data?.timestamp ?? message?.payload?.timestamp;\n if (Number.isFinite(value)) return value > 1e11 ? value : value * 1000;\n if (typeof value !== 'string' || !value) return NaN;\n return Date.parse(value.replace(/(\\.\\d{3})\\d+/, '$1'));\n}\n\n/**\n * Why an incoming effect must not auto-play, or null when it is fresh.\n * - `arrivedAt`: local time the frame was first seen (receiver clock).\n * - `connectedAt`: local time the socket opened, when known; earlier frames are not live.\n * - The timestamp carried by the sender/server is deliberately not a local freshness clock.\n */\nexport function effectSkipReason({ message, now = Date.now(), arrivedAt = now, connectedAt, maxAgeMs = DEFAULT_MAX_AGE_MS } = {}) {\n if (!isLiveMessage(message)) return 'history';\n if (Number.isFinite(connectedAt) && arrivedAt < connectedAt) return 'before-connect';\n if (now - arrivedAt > maxAgeMs) return 'stale-arrival';\n return null;\n}\nexport const isFreshEffect = (options) => effectSkipReason(options) === null;\n\nconst browserStorage = () => { try { return globalThis.localStorage ?? null; } catch { return null; } };\nconst validEntry = (entry, now) => Array.isArray(entry) && typeof entry[0] === 'string'\n && Number.isFinite(entry[1]) && Math.abs(now - entry[1]) < CLAIM_TTL_MS;\n\nfunction readClaims(storage, key, now) {\n try {\n const raw = JSON.parse(storage.getItem(key) || '[]');\n if (!Array.isArray(raw)) throw new Error('corrupted');\n return raw.filter((entry) => validEntry(entry, now)).slice(-CLAIM_LIMIT);\n } catch {\n try { storage.removeItem(key); } catch { /* Storage is optional. */ }\n return [];\n }\n}\n\n/** Best-effort same-origin claim so only one tab auto-plays an effect. Corrupted storage is reset. */\nexport function claimAutoEffect(scope, id, { storage = browserStorage(), now = Date.now() } = {}) {\n if (!storage) return true;\n const key = `${CLAIM_PREFIX}${scope}`;\n const recent = readClaims(storage, key, now);\n if (recent.some((entry) => entry[0] === id)) return false;\n try { storage.setItem(key, JSON.stringify([...recent, [id, now]].slice(-CLAIM_LIMIT))); } catch { /* Full or blocked storage. */ }\n return true;\n}\n\n/** Drops expired claims in every effects key; removes empty or corrupted keys. */\nexport function pruneEffectStorage({ storage = browserStorage(), now = Date.now() } = {}) {\n if (!storage) return;\n try {\n const keys = [];\n for (let index = 0; index < storage.length; index += 1) {\n const key = storage.key(index);\n if (key?.startsWith(CLAIM_PREFIX)) keys.push(key);\n }\n for (const key of keys) {\n const recent = readClaims(storage, key, now);\n if (recent.length) storage.setItem(key, JSON.stringify(recent));\n else storage.removeItem(key);\n }\n } catch { /* Storage is optional. */ }\n}\n\n/** Removes Map entries whose time (value, or `value[field]`) is older than `ttlMs`; caps the size. */\nexport function pruneTimes(map, { now = Date.now(), ttlMs, limit = Infinity, field } = {}) {\n for (const [key, value] of map) {\n const time = field ? value?.[field] : value;\n if (!Number.isFinite(time) || now - time > ttlMs) map.delete(key);\n }\n if (map.size > limit) [...map.keys()].slice(0, map.size - limit).forEach((key) => map.delete(key));\n return map;\n}\n\n/** `effects.debug: true` explains in the console why an incoming effect did not auto-play. */\nexport function debugEffect(config, reason, details) {\n if (config?.debug === true && typeof console !== 'undefined') console.debug(`[minicode-effects] ${reason}`, details ?? '');\n}\n","import { chatSoundUrl } from '../assets/chatAssets.js';\n\n// `level` scales the configured effects volume (clamped to 1) for cinematic recordings.\nconst RECORDINGS = new Map([\n ['pig-disco', { file: 'cerdito_disco_original.mp3' }],\n ['nudge', { file: 'nudge.mp3', level: 2.6 }],\n ['confetti', { file: 'confetti.mp3', level: 2 }],\n ['avalanche', { file: 'avalanche.mp3', level: 2 }],\n]);\n\nconst GESTURES = ['pointerdown', 'keydown', 'touchend'];\nlet unlocked = false;\nlet primedAudio = null;\nlet primeConsumers = 0;\nlet removeGestures = null;\nlet stopSharedPlayback = null;\nconst unlockListeners = new Set();\nconst markUnlocked = () => {\n if (unlocked) return;\n unlocked = true;\n removeGestures?.();\n unlockListeners.forEach((listener) => { try { listener(); } catch { /* Optional listener. */ } });\n};\n\n// 0.05 s of silent 8 kHz mono PCM: playing it inside a gesture unlocks HTML audio (Safari).\nfunction silentWavUrl() {\n const samples = 400;\n const bytes = new Uint8Array(44 + samples);\n const view = new DataView(bytes.buffer);\n const text = (offset, value) => [...value].forEach((char, index) => { bytes[offset + index] = char.charCodeAt(0); });\n text(0, 'RIFF'); view.setUint32(4, 36 + samples, true); text(8, 'WAVEfmt ');\n view.setUint32(16, 16, true); view.setUint16(20, 1, true); view.setUint16(22, 1, true);\n view.setUint32(24, 8000, true); view.setUint32(28, 8000, true); view.setUint16(32, 1, true); view.setUint16(34, 8, true);\n text(36, 'data'); view.setUint32(40, samples, true); bytes.fill(128, 44);\n let binary = '';\n bytes.forEach((byte) => { binary += String.fromCharCode(byte); });\n return `data:audio/wav;base64,${btoa(binary)}`;\n}\n\nexport const isEffectAudioUnlocked = () => unlocked;\n\n/** Notifies after playback actually succeeds, not merely after attempting it. */\nexport function subscribeEffectAudioUnlock(listener) {\n unlockListeners.add(listener);\n return () => unlockListeners.delete(listener);\n}\n\n/** Call directly inside a gesture. Reuse the same element for later recordings:\n * Safari's permission may be element-scoped; priming a disposable element does\n * not reliably unlock a new Audio() created by a subsequent React effect.\n */\nexport function unlockEffectAudio() {\n if (typeof window === 'undefined' || typeof Audio === 'undefined') return Promise.resolve(false);\n try {\n if (!primedAudio) {\n primedAudio = new Audio(silentWavUrl());\n primedAudio.volume = 0;\n }\n // If a recording is blocked, retry that actual recording in this gesture.\n if (!primedAudio.src) { primedAudio.src = silentWavUrl(); primedAudio.volume = 0; }\n const result = primedAudio.play();\n return Promise.resolve(result).then(() => { markUnlocked(); return true; }, () => false);\n } catch { return Promise.resolve(false); }\n}\n\n/** Arm gestures while at least one effects consumer is mounted. Failed attempts\n * remain armed, and the last unmount removes all listeners.\n */\nexport function primeEffectAudio() {\n if (typeof window === 'undefined') return undefined;\n primeConsumers++;\n if (!unlocked && !removeGestures) {\n const page = window;\n const onGesture = () => { void unlockEffectAudio(); };\n removeGestures = () => {\n GESTURES.forEach((name) => page.removeEventListener(name, onGesture, true));\n removeGestures = null;\n };\n GESTURES.forEach((name) => page.addEventListener(name, onGesture, { capture: true, passive: true }));\n }\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n if (--primeConsumers === 0) removeGestures?.();\n };\n}\n\n/**\n * Play an approved effect recording; return cleanup for close, mute or navigation.\n * `onPlaying(audio)` fires once playback really starts, so visuals can follow `audio.currentTime`.\n * `onBlocked(reason)` gets `'autoplay'` when the browser requires a user gesture first, else `'error'`.\n */\nexport function playEffectSound(effectId, { volume = 0.4, onBlocked, onPlaying } = {}) {\n const recording = RECORDINGS.get(effectId);\n if (!recording) return () => {};\n let audio;\n let stopped = false;\n let reported = false;\n const failed = (error) => {\n if (!stopped && !reported) { reported = true; onBlocked?.(error?.name === 'NotAllowedError' ? 'autoplay' : 'error'); }\n };\n const onError = () => failed();\n const playing = () => { if (!stopped) onPlaying?.(audio); };\n try {\n if (primedAudio) {\n stopSharedPlayback?.();\n audio = primedAudio;\n audio.src = chatSoundUrl(`effects/${recording.file}`);\n } else audio = new Audio(chatSoundUrl(`effects/${recording.file}`));\n audio.volume = Math.max(0, Math.min(1, (Number(volume) || 0) * (recording.level ?? 1)));\n audio.preload = 'auto';\n audio.addEventListener('error', onError);\n audio.addEventListener('playing', playing);\n audio.play()?.then(markUnlocked, failed);\n } catch { failed(); }\n const stop = () => {\n if (stopped) return;\n stopped = true;\n if (!audio) return;\n audio.removeEventListener('error', onError);\n audio.removeEventListener('playing', playing);\n audio.pause();\n audio.removeAttribute('src');\n audio.load();\n if (stopSharedPlayback === stop) stopSharedPlayback = null;\n };\n if (audio === primedAudio) stopSharedPlayback = stop;\n return stop;\n}\n","/** Text messages remain readable on clients without effects support. */\nexport const EFFECT_PREFIX = '[minicode-effect:v1]';\nconst COUNTDOWN_PREFIX = '[minicode-countdown:v1]';\nconst validCountdown = (value) => Number.isSafeInteger(value.endsAt) && Number.isFinite(new Date(value.endsAt).getTime()) && value.endsAt > value.sentAt && value.endsAt - value.sentAt <= 86400000 && typeof value.sound === 'boolean';\nconst IDS = new Set(['nudge', 'pig-disco', 'confetti', 'avalanche']);\nfunction createEffectId() {\n // Keep optional method calls out of parameter defaults: older consumer optimizers\n // can lose their receiver when lowering that syntax.\n const crypto = globalThis.crypto;\n if (crypto && typeof crypto.randomUUID === 'function') {\n try { return crypto.randomUUID(); } catch { /* Restricted browser context. */ }\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\nexport function encodeEffect({ effectId, id, sentAt = Date.now(), endsAt, sound = true }) {\n if (id === undefined) id = createEffectId();\n if (!IDS.has(effectId) || typeof id !== 'string' || !/^[\\w-]{1,100}$/.test(id) || !Number.isSafeInteger(sentAt) || sentAt <= 0) throw new Error('Efecto inválido');\n const label = { nudge: 'Zumbido', 'pig-disco': 'Cerdito disco', confetti: 'Confeti', avalanche: 'Avalancha' }[effectId];\n const event = { effectId, id, sentAt };\n if (endsAt !== undefined) {\n Object.assign(event, { endsAt, sound });\n if (!validCountdown(event)) throw new Error('Cuenta regresiva inválida (máximo 24 horas)');\n return `${COUNTDOWN_PREFIX}${JSON.stringify(event)}\\n⏳ Cuenta regresiva hasta ${new Date(endsAt).toISOString()} · una sorpresa al llegar a cero · abre este mensaje en un chat compatible.`;\n }\n return `${EFFECT_PREFIX}${JSON.stringify(event)}\\n✨ ${label} · abre este mensaje en un chat compatible para reproducirlo.`;\n}\nexport function decodeEffect(text) {\n if (typeof text !== 'string' || text.length > 1200) return null;\n const prefix = text.startsWith(COUNTDOWN_PREFIX) ? COUNTDOWN_PREFIX : text.startsWith(EFFECT_PREFIX) ? EFFECT_PREFIX : null;\n if (!prefix) return null;\n try {\n const value = JSON.parse(text.slice(prefix.length).split('\\n')[0]);\n if (!value || !IDS.has(value.effectId) || typeof value.id !== 'string' || !/^[\\w-]{1,100}$/.test(value.id) || !Number.isSafeInteger(value.sentAt) || value.sentAt <= 0) return null;\n if (prefix === COUNTDOWN_PREFIX && !validCountdown(value)) return null;\n return { effectId: value.effectId, id: value.id, sentAt: value.sentAt, ...(prefix === COUNTDOWN_PREFIX ? { endsAt: value.endsAt, sound: value.sound } : {}) };\n } catch { return null; }\n}\n\n/** A readable representation for quotes, clipboard and conversation previews. */\nexport function effectMessageText(text) {\n const effect = decodeEffect(text);\n if (!effect) return text;\n if (effect.endsAt) return `⏳ Cuenta regresiva · ${new Date(effect.endsAt).toLocaleString()} · una sorpresa al llegar a cero`;\n return `✨ ${{ nudge: 'Zumbido', 'pig-disco': 'Cerdito disco', confetti: 'Confeti', avalanche: 'Avalancha' }[effect.effectId]}`;\n}\n","// Coordination between the visible effect players (ChatEffects) and BackgroundEffects,\n// which plays only the recording of effects nobody can see: hidden tab, closed chat window\n// or another conversation. Module state is per page; claims in ChatEffects cover other tabs.\n\nimport { DEFAULT_REPLAY_WINDOW_MS } from './autoPlay.js';\n\nconst foreground = new Map(); // `${scope}\\n${room}` -> mounted visible players\nconst preferences = new Map(); // scope -> { sound, auto } chosen in the effects picker\nconst pending = new Map(); // scope -> Map(room -> effect missed there), replayed on return\n\nconst key = (scope, room) => `${scope}\\n${room}`;\n\n/** Marks a room as on screen; returns the cleanup for unmount or when it stops being visible. */\nexport function setForegroundRoom(scope, room) {\n const id = key(scope, room);\n foreground.set(id, (foreground.get(id) ?? 0) + 1);\n return () => {\n const count = (foreground.get(id) ?? 1) - 1;\n if (count > 0) foreground.set(id, count); else foreground.delete(id);\n };\n}\n\nexport function isForegroundRoom(scope, room) {\n return typeof document !== 'undefined' && document.visibilityState === 'visible' && foreground.has(key(scope, room));\n}\n\nexport function setEffectPreferences(scope, value) { preferences.set(scope, value); }\nexport function getEffectPreferences(scope) { return preferences.get(scope) ?? {}; }\n\nconst MISSED_LIMIT = 50;\n\n/**\n * Remembers an effect nobody saw (per room) so returning to that conversation replays its\n * animation once. Starting a new background recording stops the previous one in this scope.\n */\nexport function rememberBackgroundEffect(scope, effect) {\n let rooms = pending.get(scope);\n if (!rooms) pending.set(scope, rooms = new Map());\n if (effect.stop) rooms.forEach((entry) => { entry.stop?.(); entry.stop = null; });\n rooms.get(effect.room)?.stop?.();\n rooms.delete(effect.room);\n rooms.set(effect.room, { arrivedAt: Date.now(), ...effect });\n while (rooms.size > MISSED_LIMIT) {\n const first = rooms.keys().next().value;\n rooms.get(first)?.stop?.();\n rooms.delete(first);\n }\n}\n\n/**\n * Takes the effect missed in this room, stopping its recording. Its age is measured with the\n * local arrival time (never the sender clock); older than `windowMs` it is discarded.\n */\nexport function takeBackgroundEffect(scope, room, windowMs = DEFAULT_REPLAY_WINDOW_MS, now = Date.now()) {\n const rooms = pending.get(scope);\n const effect = rooms?.get(room);\n if (!effect) return null;\n rooms.delete(room);\n if (!rooms.size) pending.delete(scope);\n effect.stop?.();\n return now - effect.arrivedAt > windowMs ? null : effect;\n}\n\n/** Periodic cleanup of missed effects older than the replay window. */\nexport function pruneBackgroundEffects(windowMs = DEFAULT_REPLAY_WINDOW_MS, now = Date.now()) {\n for (const [scope, rooms] of pending) {\n for (const [room, effect] of rooms) {\n if (now - effect.arrivedAt > windowMs) { effect.stop?.(); rooms.delete(room); }\n }\n if (!rooms.size) pending.delete(scope);\n }\n}\n\n/** Test helper: forget all module state. */\nexport function resetBackgroundEffects() {\n foreground.clear();\n preferences.clear();\n pending.forEach((rooms) => rooms.forEach((effect) => effect.stop?.()));\n pending.clear();\n}\n","import { useEffect, useRef } from 'react';\nimport { useChatContext } from '../provider/ChatContext.js';\nimport { useChatIdentity } from '../provider/hooks.js';\nimport { isSoundEnabled } from '../notifications/chatSounds.js';\nimport { claimAutoEffect, debugEffect, effectSkipReason, pruneTimes, pruneEffectStorage, PRUNE_INTERVAL_MS } from './autoPlay.js';\nimport { playEffectSound, primeEffectAudio } from './effectAudio.js';\nimport { decodeEffect } from './protocol.js';\nimport { getEffectPreferences, isForegroundRoom, rememberBackgroundEffect, pruneBackgroundEffects } from './backgroundEffects.js';\n\n// Visible tabs get this long to claim an effect before a hidden one plays its sound.\nconst CLAIM_DELAY_MS = 300;\n\nconst field = (message, name) => message[name] ?? message.data?.[name] ?? message.payload?.[name];\n\n/**\n * Renders nothing. Plays the recording of incoming effects that no visible conversation\n * shows (hidden tab, closed chat, another room), like the new-message sound does.\n * Disabled with `effects.backgroundSound: false`.\n */\nexport default function BackgroundEffects() {\n const { config, chatStore } = useChatContext();\n const identity = useChatIdentity();\n const latest = useRef({ config, identity });\n latest.current = { config, identity };\n useEffect(() => primeEffectAudio(), []);\n useEffect(() => {\n if (!chatStore?.subscribe) return undefined;\n const seen = new WeakSet();\n const lastByRoom = new Map();\n const timers = new Set();\n const stops = new Set();\n const prune = setInterval(() => {\n pruneBackgroundEffects();\n pruneEffectStorage();\n pruneTimes(lastByRoom, { ttlMs: 120000, limit: 100 });\n }, PRUNE_INTERVAL_MS);\n (chatStore.getState().chatMessages ?? []).forEach((message) => seen.add(message));\n\n const consider = (message) => {\n const effects = latest.current.config?.effects;\n if (!effects || effects.enabled === false || effects.autoPlay === false) return;\n const event = decodeEffect(field(message, 'message') ?? field(message, 'text'));\n if (event?.endsAt) return;\n if (!event) return;\n const { scope, ids } = latest.current.identity;\n const senderId = field(message, 'user_id');\n const room = String(field(message, 'room_id') ?? '');\n const arrivedAt = Date.now();\n const reason = effectSkipReason({ message, arrivedAt, maxAgeMs: effects.maxAgeMs });\n if (senderId == null || ids.includes(String(senderId))) return;\n if (!room.startsWith('private_') && effects.allowGroups !== true) return;\n if (reason) { debugEffect(effects, reason, { id: event.id, room }); return; }\n if (Date.now() - (lastByRoom.get(room) ?? 0) < (effects.cooldownMs ?? 5000)) return;\n const timer = setTimeout(() => {\n timers.delete(timer);\n const picker = getEffectPreferences(scope);\n if (latest.current.identity.scope !== scope || latest.current.config?.effects?.enabled === false\n || latest.current.config?.effects?.autoPlay === false || picker.auto === false || isForegroundRoom(scope, room)) return;\n if (effectSkipReason({ message, arrivedAt, maxAgeMs: effects.maxAgeMs })) return;\n if (!claimAutoEffect(scope, event.id)) return;\n lastByRoom.set(room, Date.now());\n // Remember the animation even when background sound is disabled or muted.\n let stop = null;\n const current = latest.current.config?.effects;\n if (current?.backgroundSound !== false && current?.sound !== false && picker.sound !== false && isSoundEnabled()) {\n stop = playEffectSound(event.effectId, { volume: current?.volume ?? 0.35,\n onBlocked: (blocked) => debugEffect(current, `audio-${blocked}`, { id: event.id, room }) });\n stops.add(stop);\n const release = setTimeout(() => { timers.delete(release); stops.delete(stop); stop(); }, 60000);\n timers.add(release);\n }\n rememberBackgroundEffect(scope, { ...event, room, arrivedAt, stop });\n }, CLAIM_DELAY_MS);\n timers.add(timer);\n };\n\n const unsubscribe = chatStore.subscribe((state) => {\n const messages = state.chatMessages ?? [];\n // New messages are appended, so walk back until the first one already handled.\n for (let i = messages.length - 1; i >= 0 && !seen.has(messages[i]); i -= 1) {\n seen.add(messages[i]);\n consider(messages[i]);\n }\n });\n return () => {\n unsubscribe();\n timers.forEach(clearTimeout);\n clearInterval(prune);\n stops.forEach((stop) => stop());\n };\n }, [chatStore]);\n return null;\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { normalizeConfig } from '../config/normalizeConfig.js';\nimport { createStandaloneTransport } from '../core/transport/createStandaloneTransport.js';\nimport { createChatStore } from '../core/chat/createChatStore.js';\nimport BackgroundEffects from '../effects/BackgroundEffects.jsx';\nimport { ChatContext } from './ChatContext.js';\n\n// One provider = one chat instance. Options are read once; remount with `key` to change them.\nexport function LiraChatProvider({ config, transport: injectedTransport, stores, chatStore: injectedChatStore, children }) {\n const normalized = useMemo(() => normalizeConfig(config), [config]);\n // Latest config for the owned transport's identity (user/scope may change after login).\n const configRef = useRef(normalized);\n configRef.current = normalized;\n\n // Lazily owned transport: created once, only when none is injected and a URL is configured.\n const [ownedTransport] = useState(() => {\n if (injectedTransport || !normalized.websocket?.url) return null;\n const { websocket, auth } = normalized;\n return createStandaloneTransport({\n url: websocket.url,\n getToken: auth?.getToken,\n tokenParam: auth?.tokenParam,\n reconnect: websocket.reconnect,\n ping: websocket.ping,\n identity: () => {\n const { user, scope } = configRef.current;\n const userId = user?.id ?? null;\n return { userId, scope: scope ?? (userId == null ? '' : String(userId)) };\n },\n });\n });\n\n const transport = injectedTransport || ownedTransport;\n\n // Chat domain store: injected (host already attached it) or owned and attached here.\n const [ownedChatStore] = useState(() => (injectedChatStore || !transport ? null : createChatStore({ transport })));\n const chatStore = injectedChatStore || ownedChatStore;\n useEffect(() => (ownedChatStore ? ownedChatStore.getState().attach() : undefined), [ownedChatStore]);\n\n useEffect(() => {\n if (!ownedTransport) return undefined;\n ownedTransport.connect?.();\n return () => ownedTransport.close?.(); // never close an injected transport\n }, [ownedTransport]);\n\n const onConnectionChange = normalized.callbacks?.onConnectionChange;\n useEffect(() => {\n if (!transport?.onStatus || typeof onConnectionChange !== 'function') return undefined;\n const unsubscribe = transport.onStatus((status) => onConnectionChange(status));\n return typeof unsubscribe === 'function' ? unsubscribe : undefined;\n }, [transport, onConnectionChange]);\n\n const value = useMemo(() => ({ config: normalized, transport, chatStore, stores: stores ?? {} }), [normalized, transport, chatStore, stores]);\n\n return <ChatContext.Provider value={value}>{children}{chatStore && <BackgroundEffects />}</ChatContext.Provider>;\n}\n\nexport default LiraChatProvider;\n","// Contrato de transporte del chat (ver docs §2.3 y Anexo A §8.2).\n\n/**\n * @typedef {'idle'|'connecting'|'connected'|'disconnected'|'error'} TransportStatus\n */\n\n/**\n * @typedef {{ event?: string, type?: string, data?: any, payload?: any, [k: string]: any }} InboundFrame\n */\n\n/**\n * @typedef {Object} ChatTransport\n * @property {() => Promise<void>} connect\n * Abre la conexión (en el adaptador compartido delega en el host).\n * @property {(code?: number) => void} close\n * Cierre voluntario. El adaptador compartido NO cierra el socket del host.\n * @property {(action: string, payload?: object) => boolean} send\n * Fire-and-forget. Devuelve false si el socket no está OPEN; nunca lanza.\n * @property {(action: string, payload?: object, opts?: { timeoutMs?: number }) => Promise<InboundFrame>} request\n * Añade `request_id`, resuelve con CHAT_ACK y rechaza con ERROR correlado, timeout o cierre.\n * @property {(handler: (frame: InboundFrame) => boolean|void) => () => void} onEvent\n * El handler devuelve true si consumió el frame. Devuelve la función para desuscribirse.\n * @property {() => TransportStatus} getStatus\n * @property {(cb: (status: TransportStatus, prev: TransportStatus) => void) => () => void} onStatus\n * @property {() => string|null} getConnectionId\n * Cambia en cada reconexión.\n * @property {() => { userId: string|null, scope: string }} getIdentity\n * scope = `${backend}:${userId}`.\n */\n\nexport const TRANSPORT_STATUSES = Object.freeze(['idle', 'connecting', 'connected', 'disconnected', 'error']);\n\nconst REQUIRED_METHODS = [\n 'connect',\n 'close',\n 'send',\n 'request',\n 'onEvent',\n 'getStatus',\n 'onStatus',\n 'getConnectionId',\n 'getIdentity',\n];\n\n/**\n * Valida en desarrollo que `obj` cumple ChatTransport. Lanza con los miembros faltantes.\n * @param {any} obj\n * @returns {ChatTransport}\n */\nexport function assertTransport(obj) {\n if (!obj || typeof obj !== 'object') {\n throw new TypeError('[chat] transport inválido: se esperaba un objeto ChatTransport');\n }\n const missing = REQUIRED_METHODS.filter((name) => typeof obj[name] !== 'function');\n if (missing.length) {\n throw new TypeError(`[chat] transport inválido: faltan métodos ${missing.join(', ')}`);\n }\n return obj;\n}\n","const CUSTOMER_ID_KEY = 'lira-klipy-customer-id';\n\nlet memoryCustomerId = null;\n\nconst randomId = () => {\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n }\n } catch {\n // fall through\n }\n let hex = '';\n for (let i = 0; i < 32; i += 1) hex += Math.floor(Math.random() * 16).toString(16);\n return hex;\n};\n\n/** customer_id anónimo y estable por navegador, compartido por GIFs y stickers de KLIPY. */\nexport function getKlipyCustomerId() {\n try {\n const stored = localStorage.getItem(CUSTOMER_ID_KEY);\n if (stored) return stored;\n const id = memoryCustomerId || randomId();\n localStorage.setItem(CUSTOMER_ID_KEY, id);\n memoryCustomerId = id;\n return id;\n } catch {\n if (!memoryCustomerId) memoryCustomerId = randomId();\n return memoryCustomerId;\n }\n}\n","import { getKlipyCustomerId } from \"./klipyCustomer.js\";\n\n// Configuración del paquete: el host inyecta la app key vía configureKlipy(); nunca hardcodearla.\nconst config = { apiKey: \"\", locale: null, categoriesLocale: null };\nlet warnedMissingKey = false;\n\nexport function configureKlipy({ apiKey, locale, categoriesLocale } = {}) {\n if (apiKey !== undefined) config.apiKey = String(apiKey ?? \"\");\n if (locale !== undefined) config.locale = locale || null;\n if (categoriesLocale !== undefined) config.categoriesLocale = categoriesLocale || null;\n}\n\nconst getApiKey = () => {\n if (!config.apiKey && !warnedMissingKey && import.meta.env?.DEV) {\n warnedMissingKey = true;\n console.warn(\"[klipy] API key no configurada (configureKlipy): GIFs y stickers no cargarán.\");\n }\n return config.apiKey;\n};\n\n/** Raíz de la API calculada por request con la key configurada. */\nexport const getKlipyApiRoot = () => `https://api.klipy.com/api/v1/${getApiKey()}`;\nconst getBaseUrl = () => `${getKlipyApiRoot()}/gifs`;\n\nconst ERROR_MESSAGE = \"Error consultando KLIPY\";\nconst TRUSTED_HOSTS = new Set([\"static.klipy.com\", \"media.klipy.com\", \"cdn.klipy.com\"]);\nconst PREVIEW_SIZES = [\"sm\", \"xs\"];\nconst FULL_SIZES = [\"hd\", \"md\"];\n\n/**\n * Locale para trending/search. Según docs.klipy.com, `locale` en esos endpoints es\n * un código de país ISO 3166-1 alpha-2 (ejemplos de la doc: \"ge\", \"us\", \"uk\"), no un\n * código de idioma; por eso se usa \"do\" (República Dominicana) para usuarios es/LatAm.\n */\nexport const GIF_LOCALE = \"do\";\n\n/**\n * Locale para categorías. La doc de /gifs/categories exige formato xx_YY\n * (ISO 639-1 idioma + ISO 3166-1 alpha-2 país).\n */\nexport const GIF_CATEGORIES_LOCALE = \"es_DO\";\n\nexport const getKlipyLocale = () => config.locale || GIF_LOCALE;\nexport const getKlipyCategoriesLocale = () => config.categoriesLocale || GIF_CATEGORIES_LOCALE;\n\nconst categoriesCache = new Map();\n\nexport function isTrustedKlipyUrl(value) {\n if (typeof value !== \"string\" || !value) return false;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\"\n && !url.username\n && !url.password\n && TRUSTED_HOSTS.has(url.hostname.toLowerCase());\n } catch {\n return false;\n }\n}\n\nconst pickGif = (file, sizes) => {\n for (const size of sizes) {\n const media = file?.[size]?.gif;\n if (isTrustedKlipyUrl(media?.url)) return media;\n }\n return null;\n};\n\nconst toDimension = (value) => {\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : null;\n};\n\nconst normalizeItem = (item) => {\n if (!item || item.type === \"ad\") return null;\n const full = pickGif(item.file, FULL_SIZES);\n const preview = pickGif(item.file, PREVIEW_SIZES) || full;\n if (!full || !preview) return null;\n return {\n id: item.id,\n slug: item.slug,\n title: item.title || \"\",\n tags: Array.isArray(item.tags)\n ? item.tags.filter((tag) => typeof tag === \"string\" && tag.trim()).map((tag) => tag.trim())\n : [],\n preview: preview.url,\n url: full.url,\n width: toDimension(preview.width),\n height: toDimension(preview.height),\n };\n};\n\nconst request = async (path, params, signal) => {\n const query = params ? `?${new URLSearchParams(params)}` : \"\";\n const response = await fetch(`${getBaseUrl()}${path}${query}`, { signal });\n if (!response.ok) throw new Error(ERROR_MESSAGE);\n return response.json();\n};\n\nconst toPage = (json, perPage) => {\n const raw = Array.isArray(json?.data?.data) ? json.data.data : [];\n const items = raw.map(normalizeItem).filter(Boolean);\n const hasNext = json?.data?.has_next;\n return {\n items,\n hasMore: typeof hasNext === \"boolean\" ? hasNext : raw.length >= perPage,\n };\n};\n\nconst pageParams = (page, perPage) => ({\n page: String(page),\n per_page: String(perPage),\n});\n\n// trending/search: ISO 3166-1 alpha-2 (2 letras).\nconst withCountryLocale = (params, locale) => {\n const value = String(locale ?? \"\").trim();\n if (/^[a-z]{2}$/i.test(value)) params.locale = value.toLowerCase();\n return params;\n};\n\n// categories: xx_YY. Acepta GIF_LOCALE como alias del locale de categorías.\nconst toCategoriesLocale = (locale) => {\n const value = String(locale ?? \"\").trim();\n if (/^[a-z]{2}_[a-z]{2}$/i.test(value)) {\n const [lang, country] = value.split(\"_\");\n return `${lang.toLowerCase()}_${country.toUpperCase()}`;\n }\n if (value.toLowerCase() === getKlipyLocale().toLowerCase()) return getKlipyCategoriesLocale();\n return null;\n};\n\n/** API legacy: devuelve solo el array de items. */\nexport async function searchGifs(query = \"\", page = 1, signal) {\n const endpoint = query.trim() ? \"search\" : \"trending\";\n\n const params = new URLSearchParams({\n page: String(page),\n per_page: \"20\",\n });\n\n if (query.trim()) {\n params.set(\"q\", query.trim());\n }\n\n const response = await fetch(\n `${getBaseUrl()}/${endpoint}?${params}`, { signal }\n );\n\n if (!response.ok) {\n throw new Error(ERROR_MESSAGE);\n }\n\n const json = await response.json();\n\n return (json.data?.data || [])\n .filter(item => item.type !== \"ad\")\n .map(item => ({\n id: item.id,\n slug: item.slug,\n title: item.title,\n preview: item.file?.sm?.gif?.url,\n url: item.file?.hd?.gif?.url,\n }))\n .filter(item => item.url);\n}\n\nexport async function fetchTrendingGifs({ page = 1, perPage = 24, locale, signal } = {}) {\n const params = withCountryLocale({\n ...pageParams(page, perPage),\n customer_id: getKlipyCustomerId(),\n }, locale);\n const json = await request(\"/trending\", params, signal);\n return toPage(json, perPage);\n}\n\nexport async function searchGifsPage({ query, page = 1, perPage = 24, locale, signal } = {}) {\n const q = String(query ?? \"\").trim();\n if (!q) return fetchTrendingGifs({ page, perPage, locale, signal });\n const params = withCountryLocale({\n ...pageParams(page, perPage),\n q,\n customer_id: getKlipyCustomerId(),\n }, locale);\n const json = await request(\"/search\", params, signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchRecentGifs({ page = 1, perPage = 24, signal } = {}) {\n const customerId = encodeURIComponent(getKlipyCustomerId());\n const json = await request(`/recent/${customerId}`, pageParams(page, perPage), signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchGifCategories({ locale, signal } = {}) {\n const apiLocale = toCategoriesLocale(locale);\n const cacheKey = apiLocale || \"\";\n if (categoriesCache.has(cacheKey)) return categoriesCache.get(cacheKey);\n const json = await request(\"/categories\", apiLocale ? { locale: apiLocale } : null, signal);\n const list = Array.isArray(json?.data?.categories) ? json.data.categories : [];\n const categories = list\n .map((entry) => {\n const category = String(entry?.category ?? \"\").trim();\n const query = String(entry?.query ?? category).trim();\n if (!category || !query) return null;\n const preview = isTrustedKlipyUrl(entry?.preview_url) ? entry.preview_url : null;\n return { category, query, preview };\n })\n .filter(Boolean);\n categoriesCache.set(cacheKey, categories);\n return categories;\n}\n\n/** Registra el share (POST /gifs/share/{slug}). Nunca rechaza. */\nexport async function shareGif(slug, { query } = {}) {\n if (!slug) return false;\n try {\n const body = { customer_id: getKlipyCustomerId() };\n const q = String(query ?? \"\").trim();\n if (q) body.q = q;\n const response = await fetch(`${getBaseUrl()}/share/${encodeURIComponent(slug)}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n","import { useEffect, useState } from 'react';\nconst key = 'lira-chat-text-size';\nconst normalize = (value) => { const size = Number(value); return Number.isFinite(size) && size >= 13 && size <= 20 ? size : 14; };\nconst read = () => { try { return normalize(localStorage.getItem(key)); } catch { return 14; } };\nexport default function useChatTextSize() {\n const [size, setSize] = useState(read);\n useEffect(() => {\n const sync = (event) => { if (event.type === 'lira-chat-size') setSize(normalize(event.detail)); else if (!event.key || event.key === key) setSize(read()); };\n window.addEventListener('storage', sync);\n window.addEventListener('lira-chat-size', sync);\n return () => { window.removeEventListener('storage', sync); window.removeEventListener('lira-chat-size', sync); };\n }, []);\n const update = (value) => {\n const next = normalize(value); setSize(next);\n try { localStorage.setItem(key, String(next)); } catch { /* Keep session preference. */ }\n window.dispatchEvent(new CustomEvent('lira-chat-size', { detail: next }));\n };\n return [size, update];\n}\n","import { useCallback, useEffect } from 'react';\n\nconst FOCUSABLE = 'button:not(:disabled), input:not(:disabled), textarea:not(:disabled), summary, [tabindex=\"0\"]';\n\n/**\n * Focus management for a dialog-like container.\n * - `autoFocus`: while true, focuses the first control and restores the previously focused element when it turns false/unmounts.\n * - `active`: while true, Tab/Shift+Tab cycle inside `ref`.\n * Returns an `onKeyDown` handler to attach to the container.\n */\nexport default function useFocusTrap(ref, { active = false, autoFocus = false } = {}) {\n useEffect(() => {\n if (!autoFocus) return undefined;\n const previous = document.activeElement;\n ref.current?.querySelector('button, input, textarea')?.focus();\n return () => { if (previous?.isConnected) previous.focus(); };\n }, [autoFocus, ref]);\n\n return useCallback((event) => {\n if (!active || event.key !== 'Tab' || !ref.current) return;\n const nodes = [...ref.current.querySelectorAll(FOCUSABLE)].filter((node) => node.getClientRects().length);\n const first = nodes[0]; const last = nodes[nodes.length - 1];\n if (!first) { event.preventDefault(); return; }\n if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }\n else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }\n }, [active, ref]);\n}\n","import { useRef, useState } from 'react';\n\nconst DEFAULT_INITIAL = { width: 420, height: 740 };\nconst DEFAULT_MIN = { width: 360, height: 380 };\nconst RESIZE_KEYS = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];\n\n/**\n * Top-left resize handle for an element anchored bottom-right.\n * `targetRef` points at the resized element (used to read its current rect); defaults to the handle's parent.\n * Max size is bound to the viewport (vw - 48 × vh - 80).\n */\nexport default function useResizable({ initial = DEFAULT_INITIAL, min = DEFAULT_MIN, enabled = true, targetRef } = {}) {\n const startRef = useRef(null);\n const [size, setSize] = useState(initial);\n const [isResizing, setResizing] = useState(false);\n\n const targetRect = (event) => (targetRef?.current ?? event.currentTarget.parentElement).getBoundingClientRect();\n const constrainSize = (width, height) => ({\n width: Math.min(Math.max(min.width, width), window.innerWidth - 48),\n height: Math.min(Math.max(min.height, height), window.innerHeight - 80),\n });\n const onPointerDown = (event) => {\n if (!enabled || event.button !== 0) return;\n event.preventDefault();\n const rect = targetRect(event);\n startRef.current = { x: event.clientX, y: event.clientY, width: rect.width, height: rect.height };\n event.currentTarget.setPointerCapture(event.pointerId);\n setResizing(true);\n };\n const onPointerMove = (event) => {\n const start = startRef.current;\n if (!start) return;\n setSize(constrainSize(start.width + start.x - event.clientX, start.height + start.y - event.clientY));\n };\n const endResize = (event) => {\n startRef.current = null;\n setResizing(false);\n if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n };\n const onLostPointerCapture = () => { startRef.current = null; setResizing(false); };\n const onKeyDown = (event) => {\n if (!enabled || !RESIZE_KEYS.includes(event.key)) return;\n event.preventDefault();\n const rect = targetRect(event);\n const step = event.shiftKey ? 40 : 10;\n setSize(constrainSize(rect.width + (event.key === 'ArrowLeft' ? step : event.key === 'ArrowRight' ? -step : 0),\n rect.height + (event.key === 'ArrowUp' ? step : event.key === 'ArrowDown' ? -step : 0)));\n };\n\n return {\n size,\n isResizing,\n handleProps: {\n onPointerDown, onPointerMove, onPointerUp: endResize, onPointerCancel: endResize,\n onLostPointerCapture, onKeyDown,\n },\n };\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useRef } from 'react';\nimport { Minimize2, Maximize2, X, PanelLeft, Hash, ExternalLink, Download, Volume2, VolumeX, Bell, BellOff, RotateCcw } from 'lucide-react';\nimport { desktopSettings, toggleDesktopNotifications, setDesktopPreviews } from '../../notifications/desktopNotifications';\nimport { isSoundEnabled, toggleSound } from '../../notifications/chatSounds';\n\nconst PRESENCE_TEXT = { online: 'En línea', away: 'Ausente', busy: 'Ocupado' };\n\nexport default function ChatHeader({\n onDetach, onInstall, textSize, onTextSizeChange,\n title,\n subtitle,\n type = 'group',\n secondary,\n presence,\n onClose,\n onMinimize,\n onMaximize,\n onRestore,\n isMaximized,\n onToggleSidebar,\n showSidebar,\n}) {\n const isPrivate = type === 'private';\n const presenceText = presence ? PRESENCE_TEXT[presence] || PRESENCE_TEXT.online : 'Desconectado';\n const privateSubtitle = [presenceText, secondary].filter(Boolean).join(' · ');\n const notificationRef = useRef(null);\n useEffect(() => {\n const closeOutside = (event) => {\n if (!notificationRef.current?.contains(event.target)) notificationRef.current?.removeAttribute('open');\n };\n document.addEventListener('pointerdown', closeOutside);\n return () => document.removeEventListener('pointerdown', closeOutside);\n }, []);\n const [desktop, setDesktop] = useState(desktopSettings);\n useEffect(() => {\n const sync = () => setDesktop(desktopSettings());\n window.addEventListener('storage', sync);\n window.addEventListener('lira-desktop-settings', sync);\n window.addEventListener('focus', sync);\n return () => { window.removeEventListener('storage', sync); window.removeEventListener('lira-desktop-settings', sync); window.removeEventListener('focus', sync); };\n }, []);\n const [soundEnabled, setSoundEnabled] = useState(() => isSoundEnabled());\n\n const handleToggleSound = () => {\n const next = toggleSound();\n setSoundEnabled(next);\n };\n\n // Sync with other windows via storage event\n useEffect(() => {\n const onStorage = (e) => {\n if (e.key === 'lira-chat-sound') {\n setSoundEnabled(e.newValue !== 'false');\n }\n };\n window.addEventListener('storage', onStorage);\n return () => window.removeEventListener('storage', onStorage);\n }, []);\n\n return (\n <div className=\"chat-header\">\n <div className=\"chat-header-left\">\n <button type=\"button\" className=\"chat-btn chat-sidebar-toggle\" onClick={onToggleSidebar} aria-expanded={showSidebar} aria-label=\"Mostrar conversaciones\" title=\"Conversaciones\"><PanelLeft size={19} /></button>\n <div className={`chat-header-avatar chat-header-avatar--${isPrivate ? 'private' : 'group'}${isPrivate && presence ? ` chat-header-avatar--presence-${presence}` : ''}`} aria-hidden=\"true\">\n {isPrivate ? (title || '?').charAt(0).toUpperCase() : <Hash size={22} />}\n </div>\n <div className=\"chat-header-info\">\n <div className=\"chat-header-title\" title={title}>{title}</div>\n {isPrivate\n ? <div className=\"chat-header-subtitle\" title={privateSubtitle}>{privateSubtitle}</div>\n : <div className=\"chat-header-subtitle\">{subtitle === 'connected' ? 'En línea · tu espacio para conectar' : 'Tu espacio para conectar'}</div>}\n </div>\n </div>\n <div className=\"chat-header-actions\">\n <details ref={notificationRef} className=\"chat-text-settings chat-notification-settings\" onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault(); event.stopPropagation();\n notificationRef.current?.removeAttribute('open');\n notificationRef.current?.querySelector('summary')?.focus();\n }\n }}>\n <summary aria-label=\"Notificaciones de escritorio\" title=\"Notificaciones de escritorio\">{desktop.enabled && desktop.permission === 'granted' ? <Bell size={16} /> : <BellOff size={16} />}</summary>\n <div className=\"chat-notification-panel\" role=\"group\" aria-label=\"Ajustes de notificaciones\">\n <div className=\"chat-notification-heading\">\n <span className=\"chat-notification-icon\" aria-hidden=\"true\"><Bell size={18} /></span>\n <div><strong>Notificaciones</strong><span>Recibe avisos en tu escritorio</span></div>\n <span className={`chat-notification-status ${desktop.enabled && desktop.permission === 'granted' ? 'is-enabled' : ''}`}>{desktop.enabled && desktop.permission === 'granted' ? 'Activas' : 'Inactivas'}</span>\n </div>\n <button type=\"button\" className=\"chat-notification-toggle\" disabled={!desktop.supported || desktop.permission === 'denied'} aria-pressed={desktop.enabled && desktop.permission === 'granted'} onClick={() => { void toggleDesktopNotifications().then(() => setDesktop(desktopSettings())); }}>\n {desktop.enabled && desktop.permission === 'granted' ? <BellOff size={16} aria-hidden=\"true\" /> : <Bell size={16} aria-hidden=\"true\" />}\n {desktop.enabled && desktop.permission === 'granted' ? 'Desactivar notificaciones' : 'Activar notificaciones'}\n </button>\n <label className=\"chat-notification-preview\">\n <span className=\"chat-notification-preview-copy\"><strong>Mostrar vista previa</strong><small>Incluye el nombre y el mensaje. Los chats privados siempre se ocultan.</small></span>\n <input type=\"checkbox\" role=\"switch\" checked={desktop.previews} onChange={(event) => setDesktopPreviews(event.target.checked)} />\n </label>\n {(!desktop.supported || desktop.permission === 'denied') && <p className=\"chat-notification-notice\" role=\"status\">{desktop.supported ? 'Permiso bloqueado. Actívalo en los ajustes del navegador.' : 'Notificaciones no disponibles en este navegador.'}</p>}\n </div>\n </details>\n <details className=\"chat-text-settings\">\n <summary aria-label=\"Tamaño del texto del chat\" title=\"Tamaño del texto\">Aa</summary>\n <div className=\"chat-text-settings-panel\" role=\"group\" aria-label=\"Tamaño del texto\">\n <button type=\"button\" className=\"chat-btn\" disabled={textSize <= 13} onClick={() => onTextSizeChange(textSize - 1)} aria-label=\"Reducir texto\">A−</button>\n <output aria-live=\"polite\">{textSize}px</output>\n <button type=\"button\" className=\"chat-btn\" disabled={textSize >= 20} onClick={() => onTextSizeChange(textSize + 1)} aria-label=\"Aumentar texto\">A+</button>\n <button type=\"button\" className=\"chat-btn\" onClick={() => onTextSizeChange(14)} aria-label=\"Restablecer tamaño\" title=\"Restablecer tamaño\"><RotateCcw size={16} aria-hidden=\"true\" /></button>\n </div>\n </details>\n <button\n type=\"button\"\n className=\"chat-btn\"\n onClick={handleToggleSound}\n aria-label={soundEnabled ? 'Silenciar sonidos' : 'Activar sonidos'}\n aria-pressed={soundEnabled}\n title={soundEnabled ? 'Silenciar sonidos' : 'Activar sonidos'}\n >\n {soundEnabled ? <Volume2 size={16} /> : <VolumeX size={16} />}\n </button>\n {onDetach && <button type=\"button\" className=\"chat-btn\" onClick={onDetach} aria-label=\"Abrir en ventana independiente\" title=\"Abrir en ventana independiente\"><ExternalLink size={16} /></button>}\n {onInstall && <button type=\"button\" className=\"chat-btn\" onClick={onInstall} aria-label=\"Instalar LIRA Chat\" title=\"Instalar LIRA Chat\"><Download size={16} /></button>}\n {onMinimize && <button type=\"button\" className=\"chat-btn\" onClick={onMinimize} aria-label=\"Minimizar\" title=\"Minimizar\">\n <Minimize2 size={14} />\n </button>}\n {onMaximize && (isMaximized ? (\n <button type=\"button\" className=\"chat-btn\" onClick={onRestore} aria-label=\"Restaurar\" title=\"Restaurar\">\n <Maximize2 size={14} />\n </button>\n ) : (\n <button type=\"button\" className=\"chat-btn\" onClick={onMaximize} aria-label=\"Maximizar\" title=\"Maximizar\">\n <Maximize2 size={14} />\n </button>\n ))}\n {onClose && <button type=\"button\" className=\"chat-btn\" onClick={onClose} aria-label=\"Cerrar\" title=\"Cerrar\">\n <X size={14} />\n </button>}\n </div>\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { Hash, User } from 'lucide-react';\n\nconst PRESENCE_TEXT = { online: 'En línea', away: 'Ausente', busy: 'Ocupado' };\n\nexport default function ConversationItem({ conv, onSelect, selected }) {\n const isPerson = conv.type === 'private' || conv.type === 'user';\n const unread = conv.unread || 0;\n const typeClass = isPerson ? `conv-item--${conv.type}` : 'conv-item--group';\n const preview = conv.lastMessage || (isPerson ? conv.secondary || '' : 'Canal');\n const statusHidden = conv.statusText && conv.online;\n const presence = conv.online ? conv.presence || 'online' : null;\n const presenceText = presence ? PRESENCE_TEXT[presence] || PRESENCE_TEXT.online : '';\n\n return (\n <button\n type=\"button\"\n aria-pressed={selected === true}\n aria-label={`${isPerson ? `Conversación privada con ${conv.name}` : `Canal ${conv.name}`}${presenceText ? `, ${presenceText.toLocaleLowerCase()}` : ''}${unread > 0 ? `, ${unread} mensajes no leídos` : ''}`}\n className={`conv-item ${typeClass} ${conv.online ? `conv-item--online conv-item--presence-${presence}` : ''} ${selected === true ? 'conv-item--active' : ''} ${unread > 0 ? 'conv-item--unread' : ''}`}\n onClick={() => onSelect?.(conv)}\n >\n <div className=\"conv-avatar\" aria-hidden=\"true\">\n {isPerson ? (\n <span className=\"conv-avatar-private\">{conv.avatar || <User size={16} />}</span>\n ) : (\n <Hash size={16} className=\"conv-icon-hash\" />\n )}\n </div>\n <div className=\"conv-info\">\n <div className=\"conv-name\">\n <span className=\"conv-name-text\" title={conv.secondary || conv.name}>{conv.name}</span>\n {unread > 0 && <span className=\"conv-unread-badge\" aria-label={`${unread} mensajes no leídos`}>{unread > 99 ? '99+' : unread}</span>}\n </div>\n {conv.statusText ? (\n statusHidden ? <>\n <span className=\"sr-only\">{presenceText || conv.statusText}</span>\n {conv.secondary && <div className=\"conv-preview\">{conv.secondary}</div>}\n </> : <div className=\"conv-preview\">{conv.statusText}</div>\n ) : preview && <div className=\"conv-preview\">{preview}</div>}\n </div>\n <div className=\"conv-meta\">{conv.time || ''}</div>\n </button>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { MessageCircle } from 'lucide-react';\nimport ConversationItem from './ConversationItem';\n\nexport default function ConversationList({ conversations, onSelect, selectedId }) {\n if (!conversations || conversations.length === 0) {\n return (\n <div className=\"chat-empty\">\n <MessageCircle size={32} aria-hidden=\"true\" />\n <p>No hay conversaciones</p>\n </div>\n );\n }\n return (\n <div className=\"chat-conversation-list\">\n {conversations.map((conv) => (\n <ConversationItem\n key={conv.id}\n conv={conv}\n selected={selectedId === conv.id}\n onSelect={() => onSelect?.(conv)}\n />\n ))}\n </div>\n );\n}","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport { Check } from 'lucide-react';\n\nconst PRESENCE_LABELS = { online: 'En línea', away: 'Ausente', busy: 'Ocupado', invisible: 'Invisible' };\n\n// Own-status control shown from the user's avatar in the sidebar header.\nexport default function StatusMenu({ name, presence, onChange }) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef(null);\n const buttonRef = useRef(null);\n const status = presence?.status || 'online';\n const manual = presence?.manual || 'auto';\n const autoLabel = status === 'away' ? 'Ausente' : 'En línea';\n const options = [\n { value: 'auto', label: 'Automático', hint: autoLabel, dot: manual === 'auto' && status === 'away' ? 'away' : 'online' },\n { value: 'busy', label: 'Ocupado', dot: 'busy' },\n { value: 'invisible', label: 'Invisible', hint: 'Apareces desconectado', dot: 'invisible' },\n ];\n\n useEffect(() => {\n if (!open) return undefined;\n const closeOutside = (event) => { if (!rootRef.current?.contains(event.target)) setOpen(false); };\n document.addEventListener('pointerdown', closeOutside);\n rootRef.current?.querySelector('[aria-checked=\"true\"]')?.focus();\n return () => document.removeEventListener('pointerdown', closeOutside);\n }, [open]);\n\n const close = () => { setOpen(false); buttonRef.current?.focus(); };\n const onKeyDown = (event) => {\n if (event.key === 'Escape' && open) {\n event.preventDefault(); event.stopPropagation();\n close();\n return;\n }\n if (!open || !['ArrowDown', 'ArrowUp'].includes(event.key)) return;\n event.preventDefault();\n const items = [...rootRef.current.querySelectorAll('[role=\"menuitemradio\"]')];\n const index = items.indexOf(document.activeElement);\n items[(index + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length]?.focus();\n };\n const select = (value) => { onChange?.(value); close(); };\n const label = PRESENCE_LABELS[status] || PRESENCE_LABELS.online;\n\n return (\n <div ref={rootRef} className=\"chat-status-menu\" onKeyDown={onKeyDown}>\n <button ref={buttonRef} type=\"button\" className={`chat-own-avatar chat-own-avatar--${status}`}\n aria-haspopup=\"menu\" aria-expanded={open} aria-label={`Tu estado: ${label}. Cambiar estado`} title={`Tu estado: ${label}`}\n onClick={() => setOpen((value) => !value)}>\n <span aria-hidden=\"true\">{(name || '?').charAt(0).toUpperCase()}</span>\n </button>\n {open && <div className=\"chat-status-panel\" role=\"menu\" aria-label=\"Estado de presencia\">\n {options.map((option) => (\n <button key={option.value} type=\"button\" role=\"menuitemradio\" aria-checked={manual === option.value}\n className={`chat-status-option ${manual === option.value ? 'is-current' : ''}`} onClick={() => select(option.value)}>\n <span className={`chat-presence-dot chat-presence-dot--${option.dot}`} aria-hidden=\"true\" />\n <span className=\"chat-status-option-text\"><strong>{option.label}</strong>{option.hint && <small>{option.hint}</small>}</span>\n {manual === option.value && <Check size={14} aria-hidden=\"true\" />}\n </button>\n ))}\n </div>}\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useMemo, useState } from 'react';\nimport ConversationItem from './ConversationItem';\nimport ConversationList from './ConversationList';\nimport StatusMenu from './StatusMenu';\n\nconst userIdOf = (user) => String(user?.user_id ?? user?.id);\nconst displayName = (user, id) => user?.name || user?.username || `Usuario ${String(id ?? '').slice(0, 8)}`;\nconst PRESENCE_TEXT = { online: 'En línea', away: 'Ausente', busy: 'Ocupado' };\nconst secondaryOf = (user, name) => (user?.username && user.username !== name ? user.username : undefined);\n\nfunction buildConversations({ rooms = [], privateRooms = {}, users = [], onlineUsers = [], unreadCounts = {}, knownUsers = {}, presenceById = new Map() }) {\n const convs = [];\n \n // Add rooms (canales)\n rooms.forEach((room) => {\n const unread = unreadCounts[room.id] || 0;\n convs.push({\n id: room.id,\n type: 'group',\n name: room.name,\n avatar: null,\n unread,\n lastMessage: room.lastMessage,\n time: room.time,\n });\n });\n \n // Add private conversations from privateRooms map\n Object.entries(privateRooms).forEach(([userId, roomId]) => {\n if (convs.some(c => c.id === roomId)) return; // avoid duplicates\n const unread = unreadCounts[roomId] || 0;\n // Find user info from onlineUsers or users\n const user = knownUsers[userId] || [...users, ...onlineUsers].find(u => userIdOf(u) === String(userId));\n const name = displayName(user, userId);\n convs.push({\n id: roomId,\n type: 'private',\n name,\n secondary: secondaryOf(user, name),\n presence: presenceById.get(String(userId)) || null,\n online: presenceById.has(String(userId)),\n avatar: user ? name.charAt(0).toUpperCase() : null,\n unread,\n lastMessage: null,\n time: null,\n });\n });\n \n // Sort: unread first, then by last activity (simplified)\n convs.sort((a, b) => (b.unread || 0) - (a.unread || 0));\n return convs;\n}\n\nexport default function ChatSidebar({ \n rooms = [], \n users = [], \n onlineUsers = [],\n privateRooms = {},\n selectedId,\n onSelect,\n onSelectUser,\n onSearch,\n searchResults = [], searchStatus = 'idle', searchQuery = '', presenceStatus = 'idle',\n onCreateGroup,\n unreadCounts = {},\n knownUsers = {},\n currentUserId,\n currentUserIds = [],\n currentUserName,\n myPresence,\n onSetPresence,\n}) {\n const [query, setQuery] = useState(searchQuery);\n const [groupName, setGroupName] = useState('');\n const [creating, setCreating] = useState(false);\n useEffect(() => { onSearch?.(query); }, [query, onSearch, searchQuery]);\n const selfIds = new Set([...(currentUserIds || []), currentUserId].filter((id) => id != null).map(String));\n const isSelf = (user) => [user?.user_id, user?.id].some((id) => id != null && selfIds.has(String(id)));\n // Offline users are absent from onlineUsers; a missing status means plain online.\n const presenceById = useMemo(() => new Map(onlineUsers.map((user) => [userIdOf(user), user.status || 'online'])), [onlineUsers]);\n const peers = onlineUsers.filter((user) => !isSelf(user));\n const found = searchResults.filter((user) => !isSelf(user));\n const onlySelf = onlineUsers.length === 1 && isSelf(onlineUsers[0]);\n const renderUser = (user, connected) => {\n const id = userIdOf(user);\n const explicitOnline = user.is_online ?? user.online;\n const presence = presenceById.get(id) || (connected || explicitOnline === true ? user.status || 'online' : null);\n const online = presence != null;\n const label = online ? PRESENCE_TEXT[presence] || PRESENCE_TEXT.online : explicitOnline === false ? 'Desconectado' : 'Estado no disponible';\n const name = displayName(user, id);\n return <ConversationItem key={id} conv={{ id, type: 'user', name, secondary: secondaryOf(user, name), online, presence,\n avatar: name.charAt(0).toUpperCase(), statusText: label }}\n selected={String(privateRooms[id]) === String(selectedId) && selectedId != null}\n onSelect={() => onSelectUser?.(user)} />;\n };\n\n const conversations = useMemo(() => buildConversations({ rooms, privateRooms, users, onlineUsers, unreadCounts, knownUsers, presenceById }),\n [rooms, privateRooms, users, onlineUsers, unreadCounts, knownUsers, presenceById]);\n\n const matches = (item) => `${item.name || ''} ${item.secondary || ''}`.toLocaleLowerCase().includes(query.toLocaleLowerCase());\n\n const handleSelect = (conv) => {\n if (conv.noRoom) {\n onSelectUser?.({ user_id: conv.id });\n return;\n }\n onSelect?.(conv.id);\n };\n\n return (\n <aside className=\"chat-sidebar\" aria-label=\"Conversaciones\">\n <div className=\"chat-sidebar-header\">\n {onSetPresence && <StatusMenu name={currentUserName} presence={myPresence} onChange={onSetPresence} />}\n <div className=\"chat-sidebar-title\">Conversaciones</div>\n <button type=\"button\" className=\"chat-btn\" title=\"Crear grupo\" aria-label=\"Crear grupo\" onClick={() => setCreating(!creating)}>+</button>\n </div>\n {creating && <form className=\"chat-group-form\" onSubmit={(event) => { event.preventDefault(); if (groupName.trim()) { onCreateGroup?.(groupName.trim()); setGroupName(''); setCreating(false); } }}>\n <label className=\"sr-only\" htmlFor=\"chat-group-name\">Nombre del grupo</label>\n <input id=\"chat-group-name\" value={groupName} onChange={(event) => setGroupName(event.target.value)} placeholder=\"Nombre del grupo\" required maxLength={100} />\n <button type=\"submit\" disabled={!groupName.trim()}>Crear</button>\n </form>}\n <div className=\"chat-sidebar-search\"><input aria-label=\"Buscar conversaciones y usuarios\" type=\"search\" placeholder=\"Buscar...\" value={query} onChange={(event) => { setQuery(event.target.value); onSearch?.(event.target.value); }} /></div>\n <div className=\"chat-sidebar-content\">\n <ConversationList conversations={conversations.filter(matches)} onSelect={handleSelect} selectedId={selectedId} />\n <section className=\"chat-user-section\" aria-label=\"Usuarios conectados\">\n <h3>Usuarios conectados</h3>\n {peers.map((user) => renderUser(user, true))}\n {!peers.length && <p className=\"chat-user-status\" role=\"status\">{presenceStatus === 'loading' ? 'Consultando usuarios…'\n : presenceStatus === 'error' ? 'El servidor no respondió a la consulta de usuarios.'\n : onlySelf ? 'El servidor solo devolvió tu usuario. No envió otros usuarios conectados.'\n : presenceStatus === 'ready' ? 'El servidor no devolvió otros usuarios conectados.' : 'Esperando lista de usuarios…'}</p>}\n </section>\n {query.trim() && <section className=\"chat-user-section\" aria-label=\"Usuarios encontrados\">\n <h3>Usuarios encontrados</h3>\n {found.map((user) => renderUser(user, false))}\n <p className=\"chat-user-status\" role=\"status\">{searchStatus === 'loading' ? 'Buscando usuarios…'\n : searchStatus === 'error' ? 'No se pudo completar la búsqueda. Comprueba tu conexión.'\n : !found.length ? 'No se encontraron otros usuarios.' : ''}</p>\n </section>}\n </div>\n </aside>\n );\n}","import { MessageCircle } from 'lucide-react';\n\nexport default function ChatEmptyState() {\n return (\n <div className=\"chat-empty-state\">\n <MessageCircle size={40} aria-hidden=\"true\" />\n <h3>Selecciona una conversación</h3>\n <p>Elige un canal o chat privado para empezar a conversar.</p>\n </div>\n );\n}\n","/**\n * Timing for the Confeti effect, in ms from the start of `effects/confetti.mp3`.\n * Cues match the recording's low-band hits (5450 is the riser into the final blast);\n * recalibrate them whenever the mix changes.\n */\nexport const CONFETTI_DURATION_MS = 7000;\n// Without a playing recording the visuals wait this long so both starts line up.\nexport const AUDIO_WAIT_MS = 400;\nexport const CONFETTI_CUES = Object.freeze([\n { at: 300, kind: 'cannons', power: 0.9 },\n { at: 1200, kind: 'left', power: 0.7 },\n { at: 1950, kind: 'right', power: 0.8 },\n { at: 2750, kind: 'rain', power: 0.6 },\n { at: 3400, kind: 'balloons', power: 0.9 },\n { at: 4550, kind: 'sky', power: 0.75 },\n { at: 5450, kind: 'swirl', power: 0.5 },\n { at: 5700, kind: 'finale', power: 1 },\n]);\n","/**\n * Timing for the Avalancha effect, in ms from the start of `effects/avalanche.mp3`.\n * The recording was produced against these cues (loudest hits measured at 250, 2300\n * and 3800 ms); recalibrate them whenever the mix changes.\n */\nexport const AVALANCHE_DURATION_MS = 7000;\n// Without a playing recording the visuals wait this long so both starts line up.\nexport const AUDIO_WAIT_MS = 400;\nexport const AVALANCHE_CUES = Object.freeze([\n { at: 250, kind: 'confetti', power: 0.8 },\n { at: 600, kind: 'money', power: 0.7 },\n { at: 1400, kind: 'cars', power: 0.8 },\n { at: 2300, kind: 'tanks', power: 0.9 },\n { at: 3100, kind: 'coins', power: 0.8 },\n { at: 3800, kind: 'mix', power: 1 },\n { at: 4800, kind: 'cars', power: 0.6 },\n { at: 5500, kind: 'finale', power: 1 },\n]);\n","import { THUNDER_DURATION_MS } from './thunder/timeline.js';\nimport { CONFETTI_DURATION_MS } from './confetti/timeline.js';\nimport { AVALANCHE_DURATION_MS } from './avalanche/timeline.js';\n\n/** Original, bundled effects. No remote assets or audio services are required. */\nexport const EFFECT_CATALOG = Object.freeze([\n { id: 'nudge', label: 'Zumbido', emoji: '⚡', durationMs: THUNDER_DURATION_MS, description: 'Una tormenta eléctrica con rayos, chispas y trueno.' },\n { id: 'pig-disco', label: 'Cerdito disco', emoji: '🐷', durationMs: 5200, description: 'Un cerdito original bailando su propia melodía.' },\n { id: 'confetti', label: 'Confeti', emoji: '🎉', durationMs: CONFETTI_DURATION_MS, description: 'Una fiesta 3D de confeti, globos, regalos y serpentinas.' },\n { id: 'avalanche', label: 'Avalancha', emoji: '🚀', durationMs: AVALANCHE_DURATION_MS, description: 'Una avalancha 3D de dinero, carros, tanques y confeti.' },\n]);\nexport function getChatEffect(id) { return EFFECT_CATALOG.find((effect) => effect.id === id); }\nexport const getEffect = getChatEffect;\n","// Canvas 2D storm used when `three` or WebGL is unavailable. Same API as thunderScene3d.\nimport { BOLT_LIFE_S, boltFlicker } from './timeline.js';\n\nconst rand = (min, max) => min + Math.random() * (max - min);\n\nfunction jagged(x1, y1, x2, y2, passes, spread) {\n let points = [[x1, y1], [x2, y2]];\n for (let pass = 0; pass < passes; pass += 1) {\n const next = [points[0]];\n for (let i = 1; i < points.length; i += 1) {\n const [ax, ay] = points[i - 1];\n const [bx, by] = points[i];\n const length = Math.hypot(bx - ax, by - ay);\n next.push([(ax + bx) / 2 + rand(-0.5, 0.5) * length * spread, (ay + by) / 2 + rand(-0.1, 0.1) * length * spread], [bx, by]);\n }\n points = next;\n }\n return points;\n}\n\nexport function createThunderScene2d(canvas) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Canvas 2D no disponible');\n let width = 1;\n let height = 1;\n let flash = 0;\n const bolts = [];\n const sparks = [];\n\n const path = (points) => {\n ctx.beginPath();\n points.forEach(([x, y], index) => (index ? ctx.lineTo(x, y) : ctx.moveTo(x, y)));\n };\n\n return {\n strike(power = 1, x = 0) {\n const startX = width * (0.5 + x * 0.35) + rand(-30, 30);\n const endX = startX + rand(-width * 0.2, width * 0.2);\n const endY = height * rand(0.65, 0.95);\n const main = jagged(startX, -10, endX, endY, 6, 0.4);\n const branches = Array.from({ length: 2 + Math.round(power * 2) }, () => {\n const [bx, by] = main[Math.floor(rand(0.15, 0.7) * main.length)];\n return jagged(bx, by, bx + rand(-90, 90), by + rand(60, 160), 4, 0.45);\n });\n bolts.push({ main, branches, power, age: 0 });\n for (let i = 0; i < 70 * power; i += 1) {\n sparks.push({ x: endX, y: endY, vx: rand(-260, 260), vy: rand(-320, -40), life: rand(0.4, 1), max: 1 });\n }\n flash = Math.max(flash, power);\n },\n render(dt) {\n flash = Math.max(0, flash - dt * 3.2);\n ctx.clearRect(0, 0, width, height);\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n for (let i = bolts.length - 1; i >= 0; i -= 1) {\n const bolt = bolts[i];\n bolt.age += dt;\n if (bolt.age >= BOLT_LIFE_S) { bolts.splice(i, 1); continue; }\n const opacity = boltFlicker(bolt.age);\n [[bolt.main, 1], ...bolt.branches.map((branch) => [branch, 0.45])].forEach(([points, scale]) => {\n path(points);\n ctx.shadowColor = '#8fb4ff';\n ctx.shadowBlur = 24;\n ctx.strokeStyle = `rgba(127,168,255,${0.45 * opacity})`;\n ctx.lineWidth = 9 * scale * (0.6 + bolt.power);\n ctx.stroke();\n ctx.shadowBlur = 0;\n ctx.strokeStyle = `rgba(255,255,255,${opacity})`;\n ctx.lineWidth = 2.2 * scale * (0.6 + bolt.power);\n ctx.stroke();\n });\n }\n for (let i = sparks.length - 1; i >= 0; i -= 1) {\n const spark = sparks[i];\n spark.life -= dt;\n if (spark.life <= 0) { sparks.splice(i, 1); continue; }\n spark.vy += 520 * dt;\n spark.x += spark.vx * dt;\n spark.y += spark.vy * dt;\n const t = spark.life / spark.max;\n ctx.fillStyle = `rgba(255,${Math.round(150 + 105 * t)},${Math.round(90 + 165 * t)},${t})`;\n ctx.fillRect(spark.x, spark.y, 2.5, 2.5);\n }\n if (flash > 0) {\n ctx.fillStyle = `rgba(185,200,255,${flash * 0.18})`;\n ctx.fillRect(0, 0, width, height);\n }\n },\n resize(nextWidth, nextHeight) {\n const ratio = Math.min(2, window.devicePixelRatio || 1);\n width = nextWidth;\n height = nextHeight;\n canvas.width = Math.round(width * ratio);\n canvas.height = Math.round(height * ratio);\n ctx.setTransform(ratio, 0, 0, ratio, 0, 0);\n },\n dispose() {\n bolts.length = 0;\n sparks.length = 0;\n },\n };\n}\n","import React, { useEffect, useRef } from 'react';\nimport { AUDIO_WAIT_MS, THUNDER_CUES } from './timeline.js';\nimport { createThunderScene2d } from './thunderScene2d.js';\n\nconst SHAKE_STEPS = 9;\n\nfunction shake(target, power) {\n if (!target?.animate) return null;\n const frames = Array.from({ length: SHAKE_STEPS }, (_, step) => {\n const k = power * (1 - step / SHAKE_STEPS);\n return { transform: `translate(${(Math.random() - 0.5) * 22 * k}px, ${(Math.random() - 0.5) * 14 * k}px) rotate(${(Math.random() - 0.5) * 1.6 * k}deg)` };\n });\n frames.push({ transform: 'none' });\n return target.animate(frames, { duration: 420 + power * 260, easing: 'ease-out' });\n}\n\n/**\n * Storm scene for the Zumbido effect. `clockRef.current()` returns the recording's\n * playback time in ms once it plays, so strikes land on the audio's transients.\n */\nexport default function ThunderEffect({ clockRef, targetRef, waitForAudio = true }) {\n const hostRef = useRef(null);\n const flashRef = useRef(null);\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return undefined;\n const reducedMotion = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n const mountedAt = performance.now();\n const animations = new Set();\n let scene = null;\n let canvas = null;\n let disposed = false;\n let frame = 0;\n let next = 0;\n let last = mountedAt;\n\n const track = (animation) => {\n if (!animation) return;\n animations.add(animation);\n animation.onfinish = () => animations.delete(animation);\n };\n // A canvas that failed to get a WebGL context cannot switch to 2D, so each scene gets its own.\n const mount = (factory) => {\n scene?.dispose();\n canvas?.remove();\n canvas = document.createElement('canvas');\n canvas.className = 'lira-thunder-canvas';\n host.prepend(canvas);\n scene = factory(canvas, { reducedMotion });\n scene.resize(host.clientWidth || 1, host.clientHeight || 1);\n };\n const fallback = () => {\n try { mount(createThunderScene2d); } catch { scene = null; }\n };\n import('./thunderScene3d.js')\n .then(({ createThunderScene }) => { if (!disposed) mount(createThunderScene); })\n .catch(() => { if (!disposed) fallback(); });\n\n const elapsed = () => {\n const audioTime = clockRef?.current?.();\n if (audioTime != null) return audioTime;\n const wall = performance.now() - mountedAt;\n return waitForAudio ? wall - AUDIO_WAIT_MS : wall;\n };\n const fire = ({ power, x }) => {\n scene?.strike(power, x);\n track(flashRef.current?.animate?.([{ opacity: reducedMotion ? 0.12 : 0.7 * power }, { opacity: 0 }], { duration: 420, easing: 'cubic-bezier(.1,.7,.3,1)' }));\n if (!reducedMotion) track(shake(targetRef?.current, power));\n };\n const tick = (now) => {\n const dt = Math.min(0.05, (now - last) / 1000);\n last = now;\n const time = elapsed();\n while (next < THUNDER_CUES.length && time >= THUNDER_CUES[next].at) fire(THUNDER_CUES[next++]);\n try { scene?.render(dt); } catch { fallback(); }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => scene?.resize(host.clientWidth || 1, host.clientHeight || 1));\n observer?.observe(host);\n return () => {\n disposed = true;\n cancelAnimationFrame(frame);\n observer?.disconnect();\n animations.forEach((animation) => animation.cancel());\n scene?.dispose();\n canvas?.remove();\n };\n }, [clockRef, targetRef, waitForAudio]);\n return <div ref={hostRef} className=\"lira-thunder\" aria-hidden=\"true\"><div ref={flashRef} className=\"lira-thunder-flash\" /></div>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { AUDIO_WAIT_MS, CONFETTI_CUES } from './timeline.js';\n\nconst prefersReducedMotion = () => typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n/**\n * 3D party for the Confeti effect. `clockRef.current()` returns the recording's playback\n * time in ms once it plays, so bursts land on the audio's hits. Reduced motion, missing\n * `three` or WebGL render `fallback` (the CSS confetti) instead.\n */\nexport default function ConfettiEffect({ clockRef, waitForAudio = true, fallback = null }) {\n const hostRef = useRef(null);\n const flashRef = useRef(null);\n const [useFallback, setUseFallback] = useState(prefersReducedMotion);\n useEffect(() => {\n const host = hostRef.current;\n if (useFallback || !host) return undefined;\n const mountedAt = performance.now();\n const animations = new Set();\n let scene = null;\n let canvas = null;\n let disposed = false;\n let frame = 0;\n let next = 0;\n let last = mountedAt;\n let lastTime = -Infinity;\n\n const onContextLost = (event) => { event.preventDefault(); setUseFallback(true); };\n const track = (animation) => {\n if (!animation) return;\n animations.add(animation);\n animation.onfinish = () => animations.delete(animation);\n };\n import('./confettiScene3d.js')\n .then(({ createConfettiScene }) => {\n if (disposed) return;\n canvas = document.createElement('canvas');\n canvas.className = 'lira-confetti3d-canvas';\n canvas.addEventListener('webglcontextlost', onContextLost);\n host.prepend(canvas);\n scene = createConfettiScene(canvas);\n scene.resize(host.clientWidth || 1, host.clientHeight || 1);\n })\n .catch(() => { if (!disposed) setUseFallback(true); });\n\n const elapsed = () => {\n const audioTime = clockRef?.current?.();\n if (audioTime != null) return audioTime;\n const wall = performance.now() - mountedAt;\n return waitForAudio ? wall - AUDIO_WAIT_MS : wall;\n };\n const fire = ({ kind, power }) => {\n scene?.burst(kind, power);\n const peak = kind === 'finale' ? 0.55 : 0.18 * power;\n track(flashRef.current?.animate?.([{ opacity: peak }, { opacity: 0 }], { duration: kind === 'finale' ? 700 : 380, easing: 'ease-out' }));\n };\n const tick = (now) => {\n const dt = Math.min(0.05, (now - last) / 1000);\n last = now;\n if (scene) {\n const time = elapsed();\n // A late scene (slow import or shader compile) or a restarted recording resyncs\n // to the audio instead of replaying every overdue burst at once.\n if (lastTime === -Infinity || time < lastTime - 500) {\n next = CONFETTI_CUES.findIndex((cue) => cue.at >= time - 250);\n if (next < 0) next = CONFETTI_CUES.length;\n }\n lastTime = time;\n while (next < CONFETTI_CUES.length && time >= CONFETTI_CUES[next].at) fire(CONFETTI_CUES[next++]);\n try { scene.render(dt); } catch { setUseFallback(true); return; }\n }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => scene?.resize(host.clientWidth || 1, host.clientHeight || 1));\n observer?.observe(host);\n return () => {\n disposed = true;\n cancelAnimationFrame(frame);\n observer?.disconnect();\n animations.forEach((animation) => animation.cancel());\n canvas?.removeEventListener('webglcontextlost', onContextLost);\n scene?.dispose();\n canvas?.remove();\n };\n }, [clockRef, waitForAudio, useFallback]);\n if (useFallback) return fallback;\n return <div ref={hostRef} className=\"lira-confetti3d\" aria-hidden=\"true\"><div ref={flashRef} className=\"lira-confetti3d-flash\" /></div>;\n}\n","import React from 'react';\nimport { AVALANCHE_CUES } from './timeline.js';\n\n// Deterministic PRNG (mulberry32) so every client builds the same pile.\nconst seeded = (seed) => () => {\n seed = (seed + 0x6d2b79f5) | 0;\n let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n};\n\n// s: size factor, hop: bounce height (% of the host), dur: fall+bounce ms, spin/tilt: degrees.\nconst KINDS = {\n bill: { glyph: '💵', s: 1, hop: 4, dur: 1500, spin: 40, tilt: 18 },\n bag: { glyph: '💰', s: 1.1, hop: 5, dur: 1250, spin: 25, tilt: 10 },\n coin: { glyph: '🪙', s: 0.75, hop: 9, dur: 1100, spin: 60, tilt: 25 },\n race: { glyph: '🏎️', s: 1.45, hop: 3.5, dur: 1050, spin: 14, tilt: 6 },\n car: { glyph: '🚗', s: 1.4, hop: 3.5, dur: 1050, spin: 14, tilt: 6 },\n suv: { glyph: '🚙', s: 1.4, hop: 3, dur: 1050, spin: 12, tilt: 5 },\n tank: { glyph: '', s: 1.3, hop: 2, dur: 1000, spin: 10, tilt: 4 },\n helmet: { glyph: '🪖', s: 1.05, hop: 4, dur: 1150, spin: 30, tilt: 14 },\n party: { glyph: '🎉', s: 0.85, hop: 6, dur: 1600, spin: 50, tilt: 25 },\n star: { glyph: '⭐', s: 0.8, hop: 7, dur: 1650, spin: 90, tilt: 30 },\n};\n// Pieces per cue at power 1, cycling through `kinds`.\nconst CUE_MIX = {\n confetti: { base: 6, kinds: ['party', 'star'] },\n money: { base: 10, kinds: ['bill', 'bag', 'bill'] },\n cars: { base: 5, kinds: ['race', 'car', 'suv'] },\n tanks: { base: 4, kinds: ['tank', 'helmet'] },\n coins: { base: 8, kinds: ['coin'] },\n mix: { base: 6, kinds: ['bill', 'race', 'bag', 'party', 'coin', 'car'] },\n finale: { base: 8, kinds: ['bill'] },\n};\nconst LAND = 0.58; // fraction of `dur` where the first impact happens (matches the keyframes)\nconst BINS = 20;\n\nfunction buildLayout() {\n const rand = seeded(0x5eed7a1c);\n const range = (min, max) => min + rand() * (max - min);\n const pieces = [];\n const gusts = [];\n let tanks = 0;\n AVALANCHE_CUES.forEach((cue, cueIndex) => {\n const mix = CUE_MIX[cue.kind];\n if (!mix) return;\n const count = Math.max(1, Math.round(mix.base * cue.power));\n const spread = cue.kind === 'finale' ? 520 : 380;\n for (let i = 0; i < count; i += 1) {\n const type = KINDS[mix.kinds[i % mix.kinds.length]];\n const at = Math.round(cue.at + (i * spread) / count + range(0, 60));\n if (cue.kind === 'finale') {\n gusts.push({ id: `g${i}`, glyph: type.glyph, at, dur: Math.round(range(1100, 1450)), y: range(6, 58).toFixed(1), dy: range(12, 34).toFixed(1), rot: Math.round(range(-35, 35)), s: range(0.9, 1.15).toFixed(2) });\n continue;\n }\n const s = type.s * range(0.92, 1.08);\n pieces.push({\n id: `p${cueIndex}-${i}`,\n glyph: type.glyph,\n tank: type === KINDS.tank ? (tanks++ % 2 ? 'red' : 'green') : '',\n s,\n at,\n dur: Math.round(type.dur * range(0.9, 1.1)),\n hop: type.hop,\n x: range(6, 94),\n r0: Math.round(range(-type.spin, type.spin)),\n r1: Math.round(range(-type.tilt, type.tilt)),\n flip: rand() < 0.5 ? -1 : 1,\n });\n }\n });\n // Rough heightmap: later landings rest on earlier ones (units = base piece size).\n const heights = new Array(BINS).fill(0);\n [...pieces].sort((a, b) => a.at + a.dur * LAND - (b.at + b.dur * LAND)).forEach((piece) => {\n const half = piece.s * 6; // piece ≈ 12%·s of the host width\n const from = Math.max(0, Math.floor(((piece.x - half) / 100) * BINS));\n const to = Math.min(BINS - 1, Math.floor(((piece.x + half) / 100) * BINS));\n let base = 0;\n for (let b = from; b <= to; b += 1) base = Math.max(base, heights[b]);\n base = Math.min(base, 1.8);\n for (let b = from; b <= to; b += 1) heights[b] = base + piece.s * 0.45;\n piece.pile = base / piece.s; // em of the piece's own font size\n });\n const finale = AVALANCHE_CUES.find((cue) => cue.kind === 'finale')?.at ?? Infinity;\n pieces.forEach((piece) => {\n // The finale gust blows left to right, so the left side of the pile goes first.\n piece.clearAt = Math.round(finale + 250 + piece.x * 4);\n piece.x = piece.x.toFixed(1);\n piece.s = piece.s.toFixed(2);\n piece.pile = piece.pile.toFixed(2);\n });\n const flashes = AVALANCHE_CUES\n .filter((cue) => cue.kind === 'tanks' || cue.kind === 'finale')\n .map((cue) => ({ id: `f${cue.at}`, at: cue.at, peak: cue.kind === 'finale' ? 0.5 : 0.3 * cue.power, dur: cue.kind === 'finale' ? 760 : 480 }));\n return { pieces, gusts, flashes };\n}\n\nconst LAYOUT = buildLayout();\n\n/**\n * CSS-only Avalancha: big emoji (and CSS tanks) fall with weight, bounce and pile up,\n * then the finale gust sweeps them away. `startMs` is the timeline time when this took\n * over (cues already passed start mid-flight via negative delays). `still` = static pile.\n */\nexport default function AvalancheFallback({ startMs = 0, still = false }) {\n const ms = (at) => `${Math.round(at - startMs)}ms`;\n return <div className={`lira-avalanche-fallback${still ? ' lira-avalanche-fallback--still' : ''}`} aria-hidden=\"true\">\n {LAYOUT.pieces.map((p) => <span key={p.id} className=\"lira-avalanche-fb-col\" style={{ left: `${p.x}%`, '--delay': ms(p.at), '--dur': `${p.dur}ms`, '--hop': `-${p.hop}%`, '--clear': ms(p.clearAt) }}>\n <span className={p.tank ? `lira-avalanche-fb-piece lira-avalanche-fb-tank lira-avalanche-fb-tank--${p.tank}` : 'lira-avalanche-fb-piece'} style={{ '--s': p.s, '--pile': `${p.pile}em`, '--r0': `${p.r0}deg`, '--r1': `${p.r1}deg`, '--flip': p.flip }}>{p.glyph}</span>\n </span>)}\n {!still && LAYOUT.gusts.map((g) => <span key={g.id} className=\"lira-avalanche-fb-gust\" style={{ '--s': g.s, '--delay': ms(g.at), '--dur': `${g.dur}ms`, '--dy': `${g.dy}%` }}>\n <span className=\"lira-avalanche-fb-bill\" style={{ top: `${g.y}%`, '--rot': `${g.rot}deg` }}>{g.glyph}</span>\n </span>)}\n {!still && LAYOUT.flashes.filter((f) => f.at >= startMs).map((f) => <span key={f.id} className=\"lira-avalanche-fb-flash\" style={{ '--delay': ms(f.at), '--dur': `${f.dur}ms`, '--peak': f.peak }} />)}\n </div>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { AUDIO_WAIT_MS, AVALANCHE_CUES } from './timeline.js';\nimport AvalancheFallback from './AvalancheFallback.jsx';\nimport './avalanche.css';\n\nconst prefersReducedMotion = () => typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nconst flashOf = ({ kind, power }) => {\n if (kind === 'finale') return { peak: 0.6, duration: 760 };\n if (kind === 'tanks') return { peak: 0.34 * power, duration: 480 };\n return { peak: 0.16 * power, duration: 380 };\n};\n\n/**\n * 3D Avalancha (money, cars, tanks, confetti). `clockRef.current()` returns the recording's\n * playback time in ms once it plays, so bursts land on the audio's hits. Reduced motion,\n * missing `three`/WebGL or a lost context render the built-in CSS fallback instead.\n */\nexport default function AvalancheEffect({ clockRef, waitForAudio = true }) {\n const hostRef = useRef(null);\n const flashRef = useRef(null);\n const [still] = useState(prefersReducedMotion);\n // Timeline ms at which the 2D fallback took over; null while 3D runs.\n const [fallbackAt, setFallbackAt] = useState(null);\n const fallback = still || fallbackAt != null;\n useEffect(() => {\n const host = hostRef.current;\n if (fallback || !host) return undefined;\n const mountedAt = performance.now();\n const animations = new Set();\n let scene = null;\n let canvas = null;\n let disposed = false;\n let frame = 0;\n let next = 0;\n let last = mountedAt;\n let lastTime = -Infinity;\n\n const elapsed = () => {\n const audioTime = clockRef?.current?.();\n if (audioTime != null) return audioTime;\n const wall = performance.now() - mountedAt;\n return waitForAudio ? wall - AUDIO_WAIT_MS : wall;\n };\n const toFallback = () => { if (!disposed) setFallbackAt((at) => at ?? elapsed()); };\n const onContextLost = (event) => { event.preventDefault(); toFallback(); };\n const track = (animation) => {\n if (!animation) return;\n animations.add(animation);\n animation.onfinish = () => animations.delete(animation);\n };\n import('./avalancheScene3d.js')\n .then(({ createAvalancheScene }) => {\n if (disposed) return;\n canvas = document.createElement('canvas');\n canvas.className = 'lira-avalanche-canvas';\n canvas.addEventListener('webglcontextlost', onContextLost);\n host.prepend(canvas);\n scene = createAvalancheScene(canvas);\n scene.resize(host.clientWidth || 1, host.clientHeight || 1);\n })\n .catch(toFallback);\n\n const fire = (cue) => {\n scene?.burst(cue.kind, cue.power);\n const { peak, duration } = flashOf(cue);\n track(flashRef.current?.animate?.([{ opacity: peak }, { opacity: 0 }], { duration, easing: 'ease-out' }));\n };\n const tick = (now) => {\n const dt = Math.min(0.05, (now - last) / 1000);\n last = now;\n if (scene) {\n const time = elapsed();\n // A late scene (slow import or shader compile) or a restarted recording resyncs\n // to the audio instead of replaying every overdue burst at once.\n if (lastTime === -Infinity || time < lastTime - 500) {\n next = AVALANCHE_CUES.findIndex((cue) => cue.at >= time - 250);\n if (next < 0) next = AVALANCHE_CUES.length;\n }\n lastTime = time;\n while (next < AVALANCHE_CUES.length && time >= AVALANCHE_CUES[next].at) fire(AVALANCHE_CUES[next++]);\n try { scene.render(dt); } catch { toFallback(); return; }\n }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => scene?.resize(host.clientWidth || 1, host.clientHeight || 1));\n observer?.observe(host);\n return () => {\n disposed = true;\n cancelAnimationFrame(frame);\n observer?.disconnect();\n animations.forEach((animation) => animation.cancel());\n canvas?.removeEventListener('webglcontextlost', onContextLost);\n scene?.dispose();\n canvas?.remove();\n };\n }, [clockRef, waitForAudio, fallback]);\n if (fallback) return <AvalancheFallback startMs={fallbackAt ?? 0} still={still} />;\n return <div ref={hostRef} className=\"lira-avalanche\" aria-hidden=\"true\"><div ref={flashRef} className=\"lira-avalanche-flash\" /></div>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { getChatEffect } from './catalog';\nimport { playEffectSound, unlockEffectAudio } from './effectAudio';\nimport ThunderEffect from './thunder/ThunderEffect.jsx';\nimport ConfettiEffect from './confetti/ConfettiEffect.jsx';\nimport AvalancheEffect from './avalanche/AvalancheEffect.jsx';\nimport './effects.css';\n\nconst CONFETTI = Array.from({ length: 220 }, (_, index) => ({\n left: `${((index * 61.8034) % 100).toFixed(2)}%`,\n top: `${(index * 43) % 100}%`,\n color: ['#ff72ad', '#9380ff', '#ffd65c', '#37d7b0', '#6fcaff', '#ff9b59'][index % 6],\n width: `${6 + (index * 7) % 8}px`,\n height: `${8 + (index * 11) % 14}px`,\n duration: `${2.2 + (index % 13) * .1}s`,\n delay: `${-((index * 137) % 3000) / 1000}s`,\n drift: `${((index * 23) % 180) - 90}px`,\n}));\n\nfunction Pig() {\n return <svg className=\"lira-effect-pig\" viewBox=\"0 0 240 250\" role=\"img\" aria-label=\"Cerdito bailarín original\">\n <ellipse cx=\"120\" cy=\"232\" rx=\"60\" ry=\"8\" fill=\"#392169\" opacity=\".2\" />\n <g className=\"lira-effect-pig-body\">\n <path d=\"M64 154Q27 136 31 111M176 154Q213 136 209 111\" fill=\"none\" stroke=\"#f58fab\" strokeWidth=\"17\" strokeLinecap=\"round\" />\n <path d=\"M94 193L86 222M146 193L154 222\" fill=\"none\" stroke=\"#f58fab\" strokeWidth=\"20\" strokeLinecap=\"round\" />\n <ellipse cx=\"120\" cy=\"158\" rx=\"49\" ry=\"51\" fill=\"#fbabc2\" />\n <path d=\"M83 61L72 22Q104 27 108 53M132 53Q137 27 168 22L157 66\" fill=\"#fbabc2\" stroke=\"#e27598\" strokeWidth=\"4\" strokeLinejoin=\"round\" />\n <ellipse cx=\"120\" cy=\"87\" rx=\"58\" ry=\"49\" fill=\"#ffc2d4\" />\n <path d=\"M81 80H109L105 94H87ZM131 80H159L153 94H135Z\" fill=\"#2d2148\" />\n <path d=\"M109 84H131\" stroke=\"#2d2148\" strokeWidth=\"5\" />\n <ellipse cx=\"120\" cy=\"106\" rx=\"23\" ry=\"16\" fill=\"#f18eac\" />\n <ellipse cx=\"111\" cy=\"106\" rx=\"3.8\" ry=\"5\" fill=\"#a54670\" /><ellipse cx=\"129\" cy=\"106\" rx=\"3.8\" ry=\"5\" fill=\"#a54670\" />\n <path d=\"M109 129Q120 138 131 129\" stroke=\"#a54670\" strokeWidth=\"3\" fill=\"none\" strokeLinecap=\"round\" />\n <path d=\"M94 153L120 177L146 153\" fill=\"none\" stroke=\"#fff3b5\" strokeWidth=\"6\" />\n <circle cx=\"120\" cy=\"178\" r=\"8\" fill=\"#ffd65c\" />\n </g>\n </svg>;\n}\n\nconst confettiFallback = CONFETTI.map((piece, index) => <i key={index} className={`lira-effect-confetti-piece lira-effect-confetti-piece--${index % 3}`} style={{ left: piece.left, '--static-top': piece.top, '--color': piece.color, width: piece.width, height: piece.height, '--duration': piece.duration, '--delay': piece.delay, '--drift': piece.drift }} />);\n\n// Scene per effect id; getChatEffect gates unknown ids before this renders.\nfunction EffectScene({ id, clockRef, targetRef, sound }) {\n switch (id) {\n case 'pig-disco':\n return <><div className=\"lira-effect-disco-ball\" /><Pig /><span className=\"lira-effect-note\">♪</span><span className=\"lira-effect-note lira-effect-note-two\">♫</span></>;\n case 'nudge':\n return <ThunderEffect clockRef={clockRef} targetRef={targetRef} waitForAudio={sound} />;\n case 'avalanche':\n return <AvalancheEffect clockRef={clockRef} waitForAudio={sound} />;\n default:\n return <ConfettiEffect clockRef={clockRef} waitForAudio={sound} fallback={confettiFallback} />;\n }\n}\n\nexport function EffectPlayer({ effectId, onClose, onReplay, sound = true, volume = 0.4, targetRef }) {\n const effect = getChatEffect(effectId);\n const closeRef = useRef(onClose);\n const clockRef = useRef(null);\n const [blocked, setBlocked] = useState(false);\n const [attempt, setAttempt] = useState(0);\n const [fallDistance, setFallDistance] = useState(900);\n useEffect(() => {\n const target = targetRef?.current;\n const update = () => setFallDistance((target?.clientHeight || 800) + 100);\n update();\n if (!target || typeof ResizeObserver === 'undefined') return undefined;\n const observer = new ResizeObserver(update);\n observer.observe(target);\n return () => observer.disconnect();\n }, [targetRef]);\n closeRef.current = onClose;\n useEffect(() => {\n if (!effect) return undefined;\n const timer = setTimeout(() => closeRef.current?.(), effect.durationMs);\n const onKey = (event) => { if (event.key === 'Escape') closeRef.current?.(); };\n document.addEventListener('keydown', onKey);\n return () => { clearTimeout(timer); document.removeEventListener('keydown', onKey); };\n }, [effect, attempt]);\n useEffect(() => {\n setBlocked(false);\n clockRef.current = null;\n if (!sound || !effect) return undefined;\n const stop = playEffectSound(effect.id, {\n volume,\n onBlocked: (reason) => setBlocked(reason || 'error'),\n onPlaying: (audio) => { clockRef.current = () => audio.currentTime * 1000; },\n });\n return () => { clockRef.current = null; stop(); };\n }, [effect, sound, volume, attempt]);\n // Autoplay blocked: this click is the user gesture that unlocks audio; replay from the start.\n const enableSound = () => {\n unlockEffectAudio();\n if (onReplay) onReplay(); else setAttempt((value) => value + 1);\n };\n if (!effect) return null;\n const player = <div className={`lira-effect-player lira-effect-${effect.id}`} role=\"region\" aria-label={`Efecto: ${effect.label}`} style={{ '--confetti-fall': `${fallDistance}px`, '--effect-duration': `${effect.durationMs}ms` }}>\n <div className=\"lira-effect-scene\" aria-hidden=\"true\">\n <EffectScene key={attempt} id={effect.id} clockRef={clockRef} targetRef={targetRef} sound={sound} />\n </div>\n <div className=\"lira-effect-caption\" role=\"status\">{effect.label}{blocked === 'autoplay'\n ? <button type=\"button\" className=\"lira-effect-unlock\" onClick={enableSound}>🔊 Activar sonidos</button>\n : blocked && <small>No se pudo reproducir el sonido</small>}</div>\n <button className=\"lira-effect-close\" type=\"button\" aria-label=\"Cerrar efecto\" onClick={onClose}>×</button>\n </div>;\n return targetRef?.current\n ? createPortal(player, targetRef.current)\n : <div className=\"lira-effect-standalone\">{player}</div>;\n}\nexport default EffectPlayer;\n","/* eslint-disable react/prop-types */\nimport { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { EFFECT_CATALOG } from './catalog.js';\nimport { ArrowUpRight, Check, Loader2, PartyPopper, Play, Rocket, Sparkles, Volume2, VolumeX, X, Zap } from 'lucide-react';\nimport EffectPlayer from './EffectPlayer.jsx';\nimport { isSoundEnabled, subscribeSoundPreference } from '../notifications/chatSounds.js';\nimport { decodeEffect } from './protocol.js';\nimport { setEffectPreferences, setForegroundRoom, takeBackgroundEffect } from './backgroundEffects.js';\nimport { claimAutoEffect, debugEffect, effectSkipReason, DEFAULT_REPLAY_WINDOW_MS, pruneTimes } from './autoPlay.js';\nimport { primeEffectAudio } from './effectAudio.js';\nexport { claimAutoEffect } from './autoPlay.js';\nconst EffectsContext = createContext(null);\nconst subscribeVisibility = (listener) => {\n document.addEventListener('visibilitychange', listener);\n return () => document.removeEventListener('visibilitychange', listener);\n};\nconst isPageVisible = () => document.visibilityState === 'visible';\nexport function ChatEffects({ children, roomId, scope, identityScope = scope, messages = [], currentUserIds = [], config = {}, visible = true, targetRef }) {\n const globalSound = useSyncExternalStore(subscribeSoundPreference, isSoundEnabled, () => false);\n const pageVisible = useSyncExternalStore(subscribeVisibility, isPageVisible, () => false);\n const [active, setActive] = useState(null);\n const [sound, setSound] = useState(config.sound !== false);\n const [auto, setAuto] = useState(config.autoPlay !== false);\n const ledger = useRef({ room: null, seen: new Set(), since: Date.now() });\n const playing = useRef(false);\n const playbackId = useRef(0);\n const lastAuto = useRef(new Map());\n const play = (effectId, { replace = false, sound: eventSound = true } = {}) => {\n if (config.enabled === false || (playing.current && !replace) || !EFFECT_CATALOG.some((item) => item.id === effectId)) return;\n playing.current = true; setActive({ effectId, key: ++playbackId.current, sound: eventSound });\n };\n useEffect(() => { setSound(config.sound !== false); setAuto(config.autoPlay !== false); }, [config.sound, config.autoPlay]);\n useEffect(() => primeEffectAudio(), []);\n useEffect(() => {\n const room = `${scope}:${roomId}`;\n const changed = ledger.current.room !== room;\n if (changed) { ledger.current = { room, seen: new Set(), since: Date.now() }; playing.current = false; setActive(null); }\n for (const message of messages) {\n const effect = decodeEffect(message.message ?? message.text);\n if (!effect || effect.endsAt || ledger.current.seen.has(effect.id)) continue;\n ledger.current.seen.add(effect.id);\n let reason = effectSkipReason({ message, arrivedAt: Date.now(), maxAgeMs: config.maxAgeMs });\n reason ||= changed ? 'initial-snapshot' : config.enabled === false ? 'disabled' : !auto ? 'automatic-off'\n : !visible || document.visibilityState !== 'visible' ? 'not-visible'\n : message.user_id == null ? 'missing-author' : currentUserIds.includes(String(message.user_id)) ? 'own-message'\n : Date.now() - (lastAuto.current.get(room) ?? 0) < (config.cooldownMs ?? 5000) ? 'cooldown' : null;\n if (!reason && !claimAutoEffect(identityScope, effect.id)) reason = 'already-claimed';\n if (reason) { debugEffect(config, reason, { id: effect.id, roomId }); continue; }\n lastAuto.current.set(room, Date.now());\n play(effect.effectId, { replace: true });\n }\n pruneTimes(lastAuto.current, { ttlMs: 120000, limit: 100 });\n // Bound dedup memory; initial snapshots are never replayed automatically.\n if (ledger.current.seen.size > 5000) ledger.current.seen = new Set([...ledger.current.seen].slice(-2500));\n }, [messages, roomId, scope, auto, visible, config.enabled, config.maxAgeMs, config.cooldownMs, config.debug, identityScope, currentUserIds]);\n useEffect(() => { if (!visible || config.enabled === false) { playing.current = false; setActive(null); } }, [visible, config.enabled]);\n useEffect(() => { setEffectPreferences(identityScope, { sound, auto }); }, [identityScope, sound, auto]);\n // While on screen, BackgroundEffects leaves this room alone; an effect it played while the\n // tab was hidden or the chat closed replays here with its animation if it is still recent.\n useEffect(() => {\n if (!visible || !pageVisible || config.enabled === false || roomId == null) return undefined;\n const release = setForegroundRoom(identityScope, String(roomId));\n const missed = takeBackgroundEffect(identityScope, String(roomId), DEFAULT_REPLAY_WINDOW_MS);\n if (missed && auto) play(missed.effectId, { replace: true });\n return release;\n }, [visible, pageVisible, config.enabled, roomId, identityScope, auto]);\n // Only arm future deadlines while this conversation is visible. Expired history stays quiet.\n useEffect(() => {\n if (!visible || !pageVisible || config.enabled === false || !auto) return undefined;\n const timers = [];\n for (const message of messages) {\n const event = decodeEffect(message.message ?? message.text);\n if (!event?.endsAt || event.endsAt <= Date.now() || message.localOnly || message.optimistic) continue;\n timers.push(setTimeout(() => {\n if (document.visibilityState !== 'visible' || Date.now() - event.endsAt > 1500) return;\n const room = `${scope}:${roomId}`;\n if (Date.now() - (lastAuto.current.get(room) ?? 0) < (config.cooldownMs ?? 5000)) return;\n if (!claimAutoEffect(identityScope, `countdown-${event.id}`)) return;\n lastAuto.current.set(room, Date.now());\n play(event.effectId, { replace: true, sound: event.sound });\n }, event.endsAt - Date.now()));\n }\n return () => timers.forEach(clearTimeout);\n }, [messages, roomId, scope, identityScope, visible, pageVisible, auto, config.enabled, config.cooldownMs]);\n const changeSound = (value) => {\n setSound(value);\n config.onPreferencesChange?.({ sound: value });\n };\n const changeAuto = (value) => {\n setAuto(value);\n config.onPreferencesChange?.({ autoPlay: value });\n };\n return <EffectsContext.Provider value={config.enabled === false ? null : { play, sound, setSound: changeSound, auto, setAuto: changeAuto, sessionKey: `${scope}:${roomId}` }}>\n {children}\n {active && visible && <EffectPlayer key={active.key} effectId={active.effectId} sound={active.sound && sound && globalSound} volume={config.volume ?? .35} targetRef={targetRef} onReplay={() => play(active.effectId, { replace: true, sound: active.sound })} onClose={() => { playing.current = false; setActive(null); }} />}\n </EffectsContext.Provider>;\n}\nfunction CountdownCard({ effect, item, context }) {\n const [now, setNow] = useState(Date.now);\n const mountedBeforeEnd = useRef(Date.now() < effect.endsAt);\n useEffect(() => {\n let timer;\n const tick = () => {\n const current = Date.now();\n setNow(current);\n if (current >= effect.endsAt + 1000) clearInterval(timer);\n };\n tick();\n if (Date.now() < effect.endsAt + 1000) timer = setInterval(tick, 250);\n return () => clearInterval(timer);\n }, [effect.endsAt]);\n const seconds = Math.max(0, Math.ceil((effect.endsAt - now) / 1000));\n const done = seconds === 0;\n const burst = done && mountedBeforeEnd.current && now - effect.endsAt < 900;\n return <div className={`chat-effect-card chat-countdown${seconds > 0 && seconds <= 10 ? ' is-urgent' : ''}${burst ? ' is-burst' : ''}`}>\n <span aria-hidden=\"true\">{done ? item.emoji : '⏳'}</span>\n <strong>{done ? 'Cuenta finalizada' : 'Se viene una sorpresa…'}</strong>\n <time className=\"chat-countdown__clock\" dateTime={new Date(effect.endsAt).toISOString()} aria-label={done ? 'Cuenta finalizada' : `${seconds} segundos restantes`}>{done ? '¡Tiempo!' : `${String(Math.floor(seconds / 60)).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}`}</time>\n <p>{done ? `${item.emoji} ${item.label}` : 'El efecto se revela al llegar a cero.'}</p>\n {done && <button type=\"button\" className=\"chat-btn\" disabled={!context} onClick={() => context?.play(effect.effectId, { sound: effect.sound })}>Reproducir efecto</button>}\n </div>;\n}\nexport function EffectCard({ effect }) {\n const context = useContext(EffectsContext);\n const item = EFFECT_CATALOG.find((entry) => entry.id === effect.effectId);\n if (effect.endsAt) return <CountdownCard key={effect.id} effect={effect} item={item} context={context} />;\n return <div className=\"chat-effect-card\"><span aria-hidden=\"true\">{item.emoji}</span><strong>{item.label}</strong><p>{item.description}</p><button type=\"button\" className=\"chat-btn\" disabled={!context} onClick={() => context?.play(effect.effectId)}>Reproducir efecto</button></div>;\n}\nexport function EffectPicker({ onSend, disabled, onClose }) {\n const context = useContext(EffectsContext);\n const [countdown, setCountdown] = useState(false);\n const [duration, setDuration] = useState('300');\n const [customDuration, setCustomDuration] = useState(false);\n const [customValue, setCustomValue] = useState('5');\n const [customUnit, setCustomUnit] = useState(60);\n const [finalEffect, setFinalEffect] = useState('pig-disco');\n const [countdownSound, setCountdownSound] = useState(true);\n const [sending, setSending] = useState(null);\n const [feedback, setFeedback] = useState(null);\n const pending = useRef(false);\n const mounted = useRef(true);\n const pickerRef = useRef(null);\n const latestContext = useRef(context);\n latestContext.current = context;\n useEffect(() => { setFeedback(null); }, [context?.sessionKey]);\n useEffect(() => {\n mounted.current = true;\n const closeOutside = (event) => {\n if (!pickerRef.current?.contains(event.target) && !event.target.closest?.('[aria-label=\"Efectos y zumbidos\"], .lira-effect-player')) onClose();\n };\n document.addEventListener('pointerdown', closeOutside);\n return () => { mounted.current = false; document.removeEventListener('pointerdown', closeOutside); };\n }, [onClose]);\n const durationSeconds = customDuration ? Number(customValue) * customUnit : Number(duration);\n const validDuration = Number.isSafeInteger(durationSeconds) && durationSeconds >= 1 && durationSeconds <= 86400;\n const selectedEffect = EFFECT_CATALOG.find((item) => item.id === finalEffect);\n const durationLabel = durationSeconds >= 60 && durationSeconds % 60 === 0 ? `${durationSeconds / 60} min` : `${durationSeconds} s`;\n const send = async (item, timed = false) => {\n if (disabled || pending.current || !context || (timed && !validDuration)) return;\n const sessionKey = context.sessionKey;\n pending.current = true;\n setSending(item.id);\n setFeedback(null);\n try {\n const result = await onSend(item.id, timed ? { durationMs: durationSeconds * 1000, sound: countdownSound } : undefined);\n if (!mounted.current || latestContext.current?.sessionKey !== sessionKey) return;\n if (!result?.ok) {\n setFeedback({ error: true, text: result?.error || 'No se pudo enviar. Inténtalo de nuevo.' });\n return;\n }\n setFeedback({ id: item.id, text: timed ? 'Cuenta regresiva enviada' : `${item.label} enviado` });\n if (!timed) latestContext.current.play(item.id, { replace: true });\n } catch (error) {\n if (mounted.current && latestContext.current?.sessionKey === sessionKey) setFeedback({ error: true, text: error.message || 'No se pudo enviar.' });\n } finally {\n pending.current = false;\n if (mounted.current) setSending(null);\n }\n };\n return <div ref={pickerRef} className={`chat-effects-picker${countdown ? ' chat-effects-picker--countdown' : ''}`} role=\"dialog\" aria-label=\"Efectos y zumbidos\">\n <div className=\"chat-effects-picker__header\">\n <div><strong><Sparkles size={15} aria-hidden=\"true\" /> Efectos y zumbidos</strong><p>Un toque para alegrar el chat.</p></div>\n <button type=\"button\" className=\"chat-effects-picker__close\" onClick={onClose} aria-label=\"Cerrar efectos\"><X size={16} /></button>\n </div>\n {!countdown && <div className=\"chat-effects-picker__list\" aria-label=\"Elige un efecto para enviarlo\">\n {EFFECT_CATALOG.map((item) => {\n const sent = feedback?.id === item.id;\n const Icon = { nudge: Zap, confetti: PartyPopper, avalanche: Rocket }[item.id] ?? null;\n const subtitle = { nudge: 'Llama su atención', 'pig-disco': 'Ponle ritmo a la conversación', confetti: 'Celebra una buena noticia', avalanche: 'Lanza una lluvia de premios' }[item.id];\n return <button key={item.id} type=\"button\" className={`chat-effects-picker__item chat-effects-picker__item--${item.id}${sent ? ' is-sent' : ''}`}\n disabled={disabled || sending !== null || !context} onClick={() => send(item)} aria-label={`Enviar ${item.label}`} aria-busy={sending === item.id}>\n <span className=\"chat-effects-picker__icon\" aria-hidden=\"true\">{Icon ? <Icon size={21} /> : item.emoji}</span>\n <span className=\"chat-effects-picker__copy\"><strong>{item.label}</strong><small>{subtitle}</small></span>\n <span className=\"chat-effects-picker__action\" aria-hidden=\"true\">{sending === item.id ? <Loader2 size={17} className=\"chat-effects-picker__spinner\" /> : sent ? <Check size={17} /> : <ArrowUpRight size={17} />}</span>\n </button>;\n })}\n </div>}\n <button type=\"button\" className={countdown ? 'chat-countdown-back' : 'chat-effects-picker__item'} aria-expanded={countdown} onClick={() => { setCountdown(!countdown); setFeedback(null); }}>\n {countdown ? '← Volver a efectos' : <><span className=\"chat-effects-picker__icon\" aria-hidden=\"true\">⏳</span><span className=\"chat-effects-picker__copy\"><strong>Cuenta regresiva</strong><small>Una sorpresa cuando llegue a cero</small></span></>}\n </button>\n {countdown && <form className=\"chat-countdown-form\" onSubmit={(event) => { event.preventDefault(); send(selectedEffect, true); }}>\n <div className=\"chat-countdown-form__body\">\n <div className=\"chat-countdown-form__title\"><span aria-hidden=\"true\">⏳</span><div><strong>Cuenta regresiva</strong><p>Elige cuándo y cómo sorprender.</p></div></div>\n <fieldset><legend>Duración</legend><div className=\"chat-countdown-choices chat-countdown-choices--duration\">\n {[['30', '30 s'], ['60', '1 min'], ['300', '5 min'], ['600', '10 min']].map(([value, label]) => <button key={value} type=\"button\" aria-pressed={!customDuration && duration === value} onClick={() => { setDuration(value); setCustomDuration(false); }}>{label}</button>)}\n <button type=\"button\" aria-pressed={customDuration} onClick={() => setCustomDuration(true)}>Otra</button>\n </div></fieldset>\n {customDuration && <div className=\"chat-countdown-custom\">\n <label>Tiempo<input autoFocus type=\"number\" min=\"1\" max={86400 / customUnit} step=\"1\" required value={customValue} onChange={(event) => setCustomValue(event.target.value)} /></label>\n <div className=\"chat-countdown-choices\" role=\"group\" aria-label=\"Unidad de tiempo\">{[[1, 'Segundos'], [60, 'Minutos']].map(([unit, label]) => <button key={unit} type=\"button\" aria-pressed={customUnit === unit} onClick={() => setCustomUnit(unit)}>{label}</button>)}</div>\n <small>Hasta 24 horas.</small>\n </div>}\n <fieldset><legend>Efecto al terminar</legend><div className=\"chat-countdown-choices chat-countdown-choices--effects\">\n {EFFECT_CATALOG.map((item) => <button key={item.id} type=\"button\" aria-pressed={finalEffect === item.id} onClick={() => setFinalEffect(item.id)}><span aria-hidden=\"true\">{item.emoji}</span><span>{item.id === 'pig-disco' ? 'Cerdito' : item.label}</span>{finalEffect === item.id && <Check size={12} aria-hidden=\"true\" />}</button>)}\n </div></fieldset>\n <div className=\"chat-countdown-tools\">\n <button className=\"chat-countdown-sound\" type=\"button\" role=\"switch\" aria-checked={countdownSound} onClick={() => setCountdownSound(!countdownSound)}>{countdownSound ? <Volume2 size={16} /> : <VolumeX size={16} />} Sonido<span className=\"chat-effects-picker__switch\" aria-hidden=\"true\" /></button>\n <button className=\"chat-countdown-preview\" type=\"button\" disabled={!context || sending !== null} onClick={() => context?.play(finalEffect, { replace: true, sound: countdownSound })}><Play size={14} aria-hidden=\"true\" /> Probar efecto</button>\n </div>\n </div>\n <div className=\"chat-countdown-form__footer\"><button className=\"chat-countdown-send\" type=\"submit\" disabled={disabled || sending !== null || !context || !validDuration}>\n {sending ? <><Loader2 size={16} className=\"chat-effects-picker__spinner\" aria-hidden=\"true\" /> Enviando…</> : <><span>Enviar cuenta{validDuration ? ` · ${durationLabel}` : ''}</span><span aria-hidden=\"true\">{selectedEffect.emoji}</span></>}\n </button></div>\n </form>}\n {context && !countdown && <div className=\"chat-effects-picker__preferences\">\n <button type=\"button\" role=\"switch\" aria-checked={context.sound} aria-label=\"Sonido de efectos\" onClick={() => context.setSound(!context.sound)}>\n {context.sound ? <Volume2 size={14} /> : <VolumeX size={14} />}<span>Sonido</span><span className=\"chat-effects-picker__switch\" aria-hidden=\"true\" />\n </button>\n <button type=\"button\" role=\"switch\" aria-checked={context.auto} aria-label=\"Reproducir nuevos efectos automáticamente\" title=\"Reproducir los efectos recibidos automáticamente\" onClick={() => context.setAuto(!context.auto)}>\n <Play size={13} /><span>Automático</span><span className=\"chat-effects-picker__switch\" aria-hidden=\"true\" />\n </button>\n </div>}\n <p className={`chat-effects-picker__feedback${feedback?.error ? ' is-error' : ''}`} role=\"status\" aria-live=\"polite\">\n {feedback && !feedback.error && <Check size={13} aria-hidden=\"true\" />}{feedback?.text || 'Los recibidos se pueden volver a reproducir.'}\n </p>\n </div>;\n}\n","// Add only real, approved bundled assets here. No placeholder catalog.\nexport const customEmojis = [];\n","// Custom catalog is provider-scoped: never mutate the global Unicode index.\nexport const CUSTOM_EMOJI_MAX_BYTES = 256 * 1024;\nexport const CUSTOM_EMOJI_LIMIT = 100;\nexport const CUSTOM_EMOJI_NAME = /^[a-z0-9_+-]{1,32}$/;\nconst rasterData = /^data:image\\/(png|gif|jpeg|webp);base64,[a-z0-9+/]+=*$/i;\nexport function isCustomEmojiUrl(value) {\n if (typeof value !== 'string' || value.length > 360000 || /[\\u0000-\\u0020\\\\]/.test(value)) return false;\n if (rasterData.test(value)) return true;\n if (/^\\/(?!\\/)/.test(value) || /^\\.\\.?\\//.test(value)) return true;\n try {\n const url = new URL(value);\n if (url.protocol === 'blob:') {\n if (url.pathname.startsWith('null/')) return true;\n const origin = new URL(url.pathname);\n return ['https:', 'http:'].includes(origin.protocol) && !origin.username && !origin.password;\n }\n return ['https:', 'http:'].includes(url.protocol) && !url.username && !url.password;\n } catch { return false; }\n}\nexport function normalizeCustomEmojis(input) {\n if (!Array.isArray(input)) return [];\n const names = new Set();\n return input.slice(0, CUSTOM_EMOJI_LIMIT).flatMap((item) => {\n if (!item || typeof item.shortcode !== 'string' || !CUSTOM_EMOJI_NAME.test(item.shortcode) || names.has(item.shortcode) || !isCustomEmojiUrl(item.url)) return [];\n names.add(item.shortcode);\n return [{ shortcode: item.shortcode, url: item.url, label: String(item.label || item.shortcode).slice(0, 100),\n emoji: `:${item.shortcode}:`, shortcodes: [item.shortcode], source: 'custom', category: 'custom' }];\n });\n}\nexport function searchCustomEmojis(records, query) {\n const folded = (value) => String(value).normalize('NFD').replace(/\\p{M}/gu, '').toLowerCase();\n const q = folded(query).replace(/^:|:$/g, '').trim();\n return records.filter((item) => folded(`${item.shortcode} ${item.label}`).includes(q));\n}\n","import { useContext, useMemo } from 'react';\nimport { ChatContext } from '../../provider/ChatContext.js';\nimport { customEmojis } from './customEmojis.js';\nimport { normalizeCustomEmojis } from './customEmojiCatalog.js';\nexport function useCustomEmojis() {\n const context = useContext(ChatContext);\n const catalog = context?.config?.media?.emoji?.custom;\n return useMemo(() => normalizeCustomEmojis(catalog ?? customEmojis), [catalog]);\n}\n","/* eslint-disable react/prop-types */\nimport { useState } from 'react';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nfunction InlineEmoji({ item }) {\n const [failed, setFailed] = useState(false);\n return failed ? `:${item.shortcode}:` : <img className=\"chat-inline-emoji\" src={item.url} alt={`:${item.shortcode}:`} title={item.label} onError={() => setFailed(true)} />;\n}\nexport default function MessageText({ text }) {\n const customEmojis = useCustomEmojis();\n return String(text).split(/(:[a-z0-9_+-]+:)/g).map((part, index) => {\n const item = customEmojis.find((emoji) => `:${emoji.shortcode}:` === part);\n return item ? <InlineEmoji key={`${index}-${item.url}`} item={item} /> : part;\n });\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Download, File, FileText, FileSpreadsheet, FileArchive, X, Play, Pause, Mic, AlertCircle } from 'lucide-react';\nimport { isStickerAttachment, stickerTitle } from '../../core/extras/messageExtras';\n\nconst safeUrl = (value) => {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n return ['https:', 'blob:'].includes(url.protocol) && !url.username && !url.password ? url.href : undefined;\n } catch { return undefined; }\n};\n\nconst fileSize = (size) => Number.isFinite(size) && size >= 0\n ? (size < 1024 * 1024 ? `${Math.ceil(size / 1024)} KB` : `${(size / (1024 * 1024)).toFixed(1)} MB`)\n : '';\n\nconst clock = (seconds) => {\n if (!Number.isFinite(seconds)) return '0:00';\n return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, '0')}`;\n};\n\nfunction VoicePlayer({ url, onError }) {\n const audioRef = useRef(null);\n const [playing, setPlaying] = useState(false);\n const [position, setPosition] = useState(0);\n const [duration, setDuration] = useState(0);\n const [playError, setPlayError] = useState('');\n const updateDuration = () => {\n const audio = audioRef.current;\n if (!audio) return;\n const value = Number.isFinite(audio.duration) ? audio.duration\n : audio.buffered.length ? audio.buffered.end(audio.buffered.length - 1) : 0;\n if (value > 0) setDuration(value);\n };\n return <div className=\"chat-audio-player\">\n <audio ref={audioRef} src={url} preload=\"metadata\" onError={onError}\n onLoadedMetadata={updateDuration} onDurationChange={updateDuration} onProgress={updateDuration} onLoadedData={updateDuration}\n onTimeUpdate={() => setPosition(audioRef.current.currentTime)}\n onPlay={() => setPlaying(true)} onPause={() => setPlaying(false)} onEnded={() => { setPlaying(false); updateDuration(); }} />\n <button type=\"button\" className=\"chat-audio-toggle\" aria-label={playing ? 'Pausar audio' : 'Reproducir audio'} onClick={async () => {\n if (playing) audioRef.current.pause();\n else { try { setPlayError(''); await audioRef.current.play(); } catch { setPlayError('No se pudo reproducir. Descarga el audio para escucharlo.'); } }\n }}>{playing ? <Pause size={19} /> : <Play size={19} />}</button>\n <div className=\"chat-audio-track\">\n <span className=\"chat-audio-title\"><Mic size={13} /> Mensaje de voz</span>\n <input type=\"range\" min=\"0\" max={duration || 1} step=\"0.1\" value={Math.min(position, duration || 1)} disabled={!duration}\n aria-label=\"Posición del audio\" aria-valuetext={`${clock(position)} de ${clock(duration)}`}\n onChange={(event) => { audioRef.current.currentTime = Number(event.target.value); setPosition(Number(event.target.value)); }} />\n <span className=\"chat-audio-time\">{clock(position)}{duration > 0 ? ` / ${clock(duration)}` : ''}</span>\n {playError && <small role=\"status\">{playError}</small>}\n </div>\n </div>;\n}\n\nfunction AttachmentCard({ item, onRemove, history, onExpand }) {\n const [failed, setFailed] = useState(false);\n const url = safeUrl(item.preview) || safeUrl(item.url);\n const mime = typeof item.type === 'string' ? item.type.toLowerCase() : '';\n const kind = item.kind || mime.split('/')[0];\n const sticker = isStickerAttachment(item);\n const name = sticker ? stickerTitle(item) : (item.name || 'Archivo adjunto');\n const visual = kind === 'image' || kind === 'gif';\n const available = Boolean(url) && !failed;\n const extension = name.includes('.') ? name.split('.').pop().slice(0, 8).toUpperCase() : 'ARCHIVO';\n const Icon = /zip|compressed|archive/.test(mime) ? FileArchive : /sheet|excel|csv/.test(mime) ? FileSpreadsheet : /pdf|text|word|document/.test(mime) ? FileText : File;\n const cardType = !available ? 'unavailable' : visual ? 'visual' : kind === 'audio' ? 'audio' : kind === 'video' ? 'video' : 'file';\n if (sticker && history) {\n return <div className={`chat-media-card chat-attachment--sticker chat-media-card--${available ? 'visual' : 'unavailable'}`}>\n {available ? <button type=\"button\" className=\"chat-media-image\" aria-label={`Ampliar sticker ${name}`} onClick={() => onExpand({ url, name })}>\n <img className=\"chat-sticker-image\" src={url} alt={name} loading=\"lazy\" onError={() => setFailed(true)} />\n <span className=\"sr-only ui-sr-only\">Sticker</span>\n </button> : <>\n <div className=\"chat-file-icon\"><AlertCircle size={24} /></div>\n <div className=\"chat-media-card-meta\">\n <span className=\"chat-file-name\" title={name}>{name}</span>\n <small>Archivo no disponible en esta ventana</small>\n </div>\n </>}\n </div>;\n }\n return <div className={`chat-media-card chat-media-card--${cardType}`}>\n {available && visual ? <button type=\"button\" className=\"chat-media-image\" aria-label={`Ampliar ${name}`} onClick={() => onExpand({ url, name })}>\n <img src={url} alt={name} loading=\"lazy\" onError={() => setFailed(true)} />\n {kind === 'gif' && <span className=\"chat-gif-label\">{sticker ? 'Sticker' : 'GIF'}</span>}\n </button> : available && kind === 'video' ? <video className=\"chat-attachment-video\" src={url} controls preload=\"metadata\" aria-label={name} onError={() => setFailed(true)} />\n : available && kind === 'audio' ? <VoicePlayer url={url} onError={() => setFailed(true)} />\n : <div className=\"chat-file-icon\">{available ? <Icon size={25} /> : <AlertCircle size={24} />}</div>}\n <div className=\"chat-media-card-meta\">\n <span className=\"chat-file-name\" title={name}>{history && kind === 'audio' ? 'Audio' : name}</span>\n <small>{!available ? 'Archivo no disponible en esta ventana' : [!visual && kind !== 'audio' && kind !== 'video' ? extension : '', item.size > 0 ? fileSize(item.size) : ''].filter(Boolean).join(' · ')}</small>\n </div>\n {available && <a className=\"chat-file-download\" href={url} download={name} target=\"_blank\" rel=\"noopener noreferrer\" title=\"Descargar archivo\" aria-label={`Descargar ${name}`}><Download size={17} /></a>}\n {onRemove && <button type=\"button\" className=\"chat-attachment-remove\" aria-label={`Quitar ${name}`} onClick={onRemove}><X size={14} /></button>}\n </div>;\n}\n\nexport default function MediaPreview({ items = [], onRemove, history = false }) {\n const [activeImage, setActiveImage] = useState(null);\n const closeRef = useRef(null);\n\n useEffect(() => {\n if (!activeImage) return undefined;\n const previousFocus = document.activeElement;\n closeRef.current?.focus();\n const onKeyDown = (event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopImmediatePropagation();\n setActiveImage(null);\n }\n if (event.key === 'Tab') {\n event.preventDefault();\n closeRef.current?.focus();\n }\n };\n document.addEventListener('keydown', onKeyDown, true);\n return () => {\n document.removeEventListener('keydown', onKeyDown, true);\n if (previousFocus?.isConnected) previousFocus.focus();\n };\n }, [activeImage]);\n\n if (!Array.isArray(items) || !items.length) return null;\n\n return <>\n <div className={`chat-media-grid ${history ? 'chat-media-grid--history' : 'chat-media-grid--draft'}`}>\n {items.map((item, index) => item && typeof item === 'object' ?\n <AttachmentCard key={`${item.id || index}:${item.url || item.preview || ''}`} item={item} history={history}\n onRemove={onRemove ? () => onRemove(index) : undefined} onExpand={setActiveImage} /> : null)}\n </div>\n {activeImage && createPortal(<div className=\"mc-chat-portal chat-media-viewer\" role=\"dialog\" aria-modal=\"true\" aria-label={activeImage.name} onClick={(event) => { event.stopPropagation(); setActiveImage(null); }}>\n <div className=\"chat-media-viewer-content\" onClick={(event) => event.stopPropagation()}>\n <button ref={closeRef} type=\"button\" aria-label=\"Cerrar imagen\" onClick={() => setActiveImage(null)}><X aria-hidden=\"true\" /></button>\n <img src={activeImage.url} alt={activeImage.name} />\n </div>\n </div>, document.body)}\n </>;\n}\n","const VIDEO_ID = /^[A-Za-z0-9_-]{11}$/;\nconst HOSTS = new Set(['youtube.com', 'www.youtube.com', 'm.youtube.com', 'music.youtube.com', 'youtube-nocookie.com', 'www.youtube-nocookie.com']);\nfunction seconds(value) {\n if (!value) return 0;\n if (/^\\d+$/.test(value)) return Math.min(Number(value), 604800);\n const parts = /^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/.exec(value);\n return parts ? Math.min(Number(parts[1] || 0) * 3600 + Number(parts[2] || 0) * 60 + Number(parts[3] || 0), 604800) : 0;\n}\nexport function parseYouTubeUrl(value) {\n if (typeof value !== 'string' || /[\\s\\\\]/.test(value)) return null;\n try {\n const url = new URL(/^[a-z][a-z\\d+.-]*:/i.test(value) ? value : `https://${value}`);\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password || url.port) return null;\n const host = url.hostname.toLowerCase();\n const parts = url.pathname.split('/').filter(Boolean);\n let id;\n if (host === 'youtu.be' || host === 'www.youtu.be') id = parts.length === 1 ? parts[0] : null;\n else if (HOSTS.has(host)) {\n if (url.pathname === '/watch') id = url.searchParams.get('v');\n else if (['shorts', 'embed', 'live'].includes(parts[0]) && parts.length === 2) id = parts[1];\n }\n if (!VIDEO_ID.test(id ?? '')) return null;\n const start = seconds(url.searchParams.get('start') || url.searchParams.get('t') || new URLSearchParams(url.hash.slice(1)).get('t'));\n const suffix = start ? `&start=${start}` : '';\n return { id, start, watchUrl: `https://www.youtube.com/watch?v=${id}${start ? `&t=${start}s` : ''}`,\n embedUrl: `https://www.youtube-nocookie.com/embed/${id}?playsinline=1${suffix}` };\n } catch { return null; }\n}\n/** At most one player per message; never embed arbitrary user-provided HTML or hosts. */\nexport function findYouTubeVideo(text) {\n if (typeof text !== 'string') return null;\n const candidates = text.matchAll(/(?:^|[\\s(<])((?:https?:\\/\\/|www\\.|(?:youtube\\.com|youtu\\.be)\\/)[^\\s<>\"']+)/gi);\n for (const [, candidate] of candidates) {\n const video = parseYouTubeUrl(candidate.replace(/[).,!?;:\\]}]+$/, ''));\n if (video) return video;\n }\n return null;\n}\n","import { useContext, useMemo } from 'react';\nimport { ChatContext } from '../../provider/ChatContext.js';\nimport { findYouTubeVideo } from '../../media/youtube/youtubeLinks.js';\nimport '../styles/YouTubePreview.css';\n\nexport default function YouTubePreview({ text }) {\n const context = useContext(ChatContext);\n const video = useMemo(() => findYouTubeVideo(text), [text]);\n if (!video || context?.config?.features === false || context?.config?.features?.youtube === false) return null;\n return <div className=\"chat-youtube-preview\">\n <iframe key={`${video.id}:${video.start}`} src={video.embedUrl} title={`Video de YouTube (${video.id})`}\n loading=\"lazy\" referrerPolicy=\"strict-origin-when-cross-origin\"\n allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen\" allowFullScreen />\n <a href={video.watchUrl} target=\"_blank\" rel=\"noopener noreferrer\">Abrir en YouTube ↗</a>\n </div>;\n}\n","import { customEmojis } from './customEmojis';\n\n// emojibase-data (~1.4 MB of JSON) is loaded on demand with dynamic import() so it lands in its own\n// chunks instead of the main bundle. Until it arrives the sync API below answers from the custom\n// emojis and the legacy EMOJI_SHORTCUTS only; subscribeEmojiData/useEmojiDataReady notify when ready.\nconst loadSources = () => Promise.all([\n import('emojibase-data/en/compact.json'),\n import('emojibase-data/es/compact.json'),\n import('emojibase-data/en/shortcodes/github.json'),\n import('emojibase-data/en/shortcodes/emojibase.json'),\n import('emojibase-data/en/shortcodes/iamcal.json'),\n import('emojibase-data/es/messages.json'),\n]).then((modules) => modules.map((mod) => mod.default ?? mod));\n\n// Historical LIRA shortcuts are compatibility aliases, not a second emoji catalog.\nexport const EMOJI_SHORTCUTS = {\n // Smileys & Emotion\n grin: '😀',\n smile: '😄',\n smiley: '😃',\n grinning: '😀',\n joy: '😂',\n rofl: '🤣',\n laugh: '😂',\n lol: '😂',\n sweat_smile: '😅',\n sweat: '😅',\n blush: '😊',\n innocent: '😇',\n angel: '😇',\n wink: '😉',\n relieved: '😌',\n heart_eyes: '😍',\n kissing_heart: '😘',\n kissing: '😗',\n kissing_smiling_eyes: '😙',\n kissing_closed_eyes: '😚',\n yum: '😋',\n stuck_out_tongue: '😛',\n stuck_out_tongue_winking_eye: '😜',\n stuck_out_tongue_closed_eyes: '😝',\n zany_face: '🤪',\n face_with_raised_eyebrow: '🤨',\n monocle_face: '🧐',\n nerd_face: '🤓',\n sunglasses: '😎',\n disguised_face: '🥸',\n star_struck: '🤩',\n partying_face: '🥳',\n smirk: '😏',\n unamused: '😒',\n disappointed: '😞',\n pensive: '😔',\n worried: '😟',\n confused: '😕',\n slightly_frowning_face: '🙁',\n frowning_face: '☹️',\n open_mouth: '😮',\n hushed: '😯',\n astonished: '😲',\n flushed: '😳',\n fearful: '😨',\n cold_sweat: '😰',\n disappointed_relieved: '😥',\n cry: '😢',\n sob: '😭',\n scream: '😱',\n confounded: '😖',\n persevere: '😣',\n weary: '😩',\n tired_face: '😫',\n angry: '😠',\n rage: '😡',\n face_with_symbols_on_mouth: '🤬',\n mask: '😷',\n face_with_thermometer: '🤒',\n face_with_head_bandage: '🤕',\n nauseated_face: '🤢',\n vomiting_face: '🤮',\n sneezing_face: '🤧',\n hot_face: '🥵',\n cold_face: '🥶',\n woozy_face: '🥴',\n dizzy_face: '😵',\n exploding_head: '🤯',\n cowboy_hat_face: '🤠',\n clown_face: '🤡',\n lying_face: '🤥',\n shushing_face: '🤫',\n thinking_face: '🤔',\n zipper_mouth_face: '🤐',\n face_with_raised_eyebrow: '🤨',\n neutral_face: '😐',\n expressionless: '😑',\n no_mouth: '😶',\n smirking_face: '😏',\n unamused_face: '😒',\n rolling_eyes: '🙄',\n grimacing_face: '😬',\n lying_face: '🤥',\n \n // Hearts\n heart: '❤️',\n red_heart: '❤️',\n orange_heart: '🧡',\n yellow_heart: '💛',\n green_heart: '💚',\n blue_heart: '💙',\n purple_heart: '💜',\n brown_heart: '🤎',\n black_heart: '🖤',\n white_heart: '🤍',\n broken_heart: '💔',\n heart_exclamation: '❣️',\n two_hearts: '💕',\n revolving_hearts: '💞',\n heartbeat: '💓',\n sparkling_heart: '💖',\n growing_heart: '💗',\n cupid: '💘',\n gift_heart: '💝',\n heart_decoration: '💟',\n \n // Hands & Gestures\n thumbsup: '👍',\n thumbs_down: '👎',\n clap: '👏',\n pray: '🙏',\n handshake: '🤝',\n fist: '👊',\n left_facing_fist: '🤛',\n right_facing_fist: '🤜',\n punch: '👊',\n wave: '👋',\n raised_hand: '✋',\n vulcan_salute: '🖖',\n ok_hand: '👌',\n pinched_fingers: '🤌',\n pinching_hand: '🤏',\n victory_hand: '✌️',\n crossed_fingers: '🤞',\n love_you_gesture: '🤟',\n sign_of_the_horns: '🤘',\n call_me_hand: '🤙',\n backhand_index_pointing_left: '👈',\n backhand_index_pointing_right: '👉',\n backhand_index_pointing_up: '👆',\n middle_finger: '🖕',\n backhand_index_pointing_down: '👇',\n index_pointing_up: '☝️',\n raised_back_of_hand: '🤚',\n palm_down_hand: '🫳',\n palm_up_hand: '🫴',\n writing_hand: '✍️',\n nail_care: '💅',\n selfie: '🤳',\n flexed_biceps: '💪',\n mechanical_arm: '🦾',\n mechanical_leg: '🦿',\n \n // Common Objects & Symbols\n fire: '🔥',\n star: '⭐',\n star2: '🌟',\n sparkles: '✨',\n dizzy: '💫',\n boom: '💥',\n collision: '💥',\n anger: '💢',\n sweat_drops: '💦',\n dash: '💨',\n hole: '🕳️',\n bomb: '💣',\n speech_balloon: '💬',\n thought_balloon: '💭',\n zzz: '💤',\n \n // Misc\n check: '✅',\n white_check_mark: '✅',\n heavy_check_mark: '✔️',\n x: '❌',\n negative_squared_cross_mark: '❎',\n '100': '💯',\n hundred: '💯',\n ok: '🆗',\n new: '🆕',\n cool: '🆒',\n free: '🆓',\n vs: '🆚',\n copyright: '©️',\n registered: '®️',\n tm: '™️',\n \n // Activities\n soccer: '⚽',\n basketball: '🏀',\n football: '🏈',\n baseball: '⚾',\n tennis: '🎾',\n volleyball: '🏐',\n rugby_football: '🏉',\n pool_8ball: '🎱',\n ping_pong: '🏓',\n badminton: '🏸',\n goal_net: '🥅',\n golf: '⛳',\n fishing_pole_and_fish: '🎣',\n running: '🏃',\n running_shirt_with_sash: '🏃‍♂️',\n dancer: '💃',\n man_dancing: '🕺',\n dancer_woman: '💃',\n dancer_man: '🕺',\n levitate: '🕴️',\n \n // Food & Drink\n pizza: '🍕',\n hamburger: '🍔',\n fries: '🍟',\n hotdog: '🌭',\n sandwich: '🥪',\n taco: '🌮',\n burrito: '🌯',\n stuffed_flatbread: '🥙',\n falafel: '🧆',\n egg: '🥚',\n cooking: '🍳',\n shallow_pan_of_food: '🥘',\n pot_of_food: '🍲',\n bowl_with_spoon: '🥣',\n green_salad: '🥗',\n popcorn: '🍿',\n butter: '🧈',\n salt: '🧂',\n canned_food: '🥫',\n bento: '🍱',\n rice_cracker: '🍘',\n rice_ball: '🍙',\n rice: '🍚',\n curry: '🍛',\n ramen: '🍜',\n spaghetti: '🍝',\n sweet_potato: '🍠',\n oden: '🍢',\n sushi: '🍣',\n fried_shrimp: '🍤',\n fish_cake: '🍥',\n moon_cake: '🥮',\n dango: '🍡',\n dumpling: '🥟',\n fortune_cookie: '🥠',\n takeout_box: '🥡',\n crab: '🦀',\n lobster: '🦞',\n shrimp: '🍤',\n squid: '🦑',\n oyster: '🦪',\n icecream: '🍦',\n shaved_ice: '🍧',\n ice_cream: '🍨',\n doughnut: '🍩',\n cookie: '🍪',\n birthday: '🎂',\n cake: '🍰',\n cupcake: '🧁',\n pie: '🥧',\n chocolate_bar: '🍫',\n candy: '🍬',\n lollipop: '🍭',\n custard: '🍮',\n honey_pot: '🍯',\n baby_bottle: '🍼',\n milk_glass: '🥛',\n coffee: '☕',\n tea: '🍵',\n sake: '🍶',\n bottle_with_popping_cork: '🍾',\n wine_glass: '🍷',\n cocktail_glass: '🍸',\n tropical_drink: '🍹',\n beer: '🍺',\n beer_mug: '🍻',\n clinking_glasses: '🥂',\n tumbler_glass: '🥃',\n cup_with_straw: '🥤',\n beverage_box: '🧃',\n mate: '🧉',\n ice_cube: '🧊',\n \n // Animals\n dog: '🐶',\n cat: '🐱',\n mouse: '🐭',\n hamster: '🐹',\n rabbit: '🐰',\n fox_face: '🦊',\n bear: '🐻',\n panda_face: '🐼',\n koala: '🐨',\n tiger: '🐯',\n lion: '🦁',\n cow: '🐮',\n pig: '🐷',\n pig_nose: '🐽',\n frog: '🐸',\n monkey_face: '🐵',\n see_no_evil: '🙈',\n hear_no_evil: '🙉',\n speak_no_evil: '🙊',\n monkey: '🐒',\n chicken: '🐔',\n penguin: '🐧',\n bird: '🐦',\n baby_chick: '🐤',\n hatching_chick: '🐣',\n hatched_chick: '🐥',\n duck: '🦆',\n eagle: '🦅',\n owl: '🦉',\n bat: '🦇',\n wolf: '🐺',\n boar: '🐗',\n horse: '🐴',\n unicorn: '🦄',\n bee: '🐝',\n bug: '🐛',\n butterfly: '🦋',\n snail: '🐌',\n lady_beetle: '🐞',\n ant: '🐜',\n mosquito: '🦟',\n microbe: '🦠',\n \n // Weather & Nature\n sunny: '☀️',\n cloud: '☁️',\n cloud_with_lightning: '⛈️',\n cloud_with_rain: '🌧️',\n cloud_with_snow: '🌨️',\n snowflake: '❄️',\n snowman: '☃️',\n comet: '☄️',\n umbrella: '☂️',\n umbrella_with_rain_drops: '☔',\n rainbow: '🌈',\n sun_behind_cloud: '🌤️',\n sun_behind_rain_cloud: '🌦️',\n lightning: '⚡',\n fire: '🔥',\n droplet: '💧',\n ocean: '🌊',\n \n // Miscellaneous\n music: '🎵',\n notes: '🎶',\n microphone: '🎤',\n headphones: '🎧',\n musical_score: '🎼',\n musical_keyboard: '🎹',\n drum: '🥁',\n saxophone: '🎷',\n trumpet: '🎺',\n guitar: '🎸',\n violin: '🎻',\n game_die: '🎲',\n dart: '🎯',\n video_game: '🎮',\n joystick: '🕹️',\n slot_machine: '🎰',\n direct_hit: '🎯',\n trophy: '🏆',\n medal: '🏅',\n sports_medal: '🏅',\n first_place_medal: '🥇',\n second_place_medal: '🥈',\n third_place_medal: '🥉',\n reminder_ribbon: '🎗️',\n rosette: '🏵️',\n ticket: '🎫',\n tickets: '🎟️',\n circus_tent: '🎪',\n performing_arts: '🎭',\n art: '🎨',\n paintbrush: '🖌️',\n crayon: '🖍️',\n pencil: '✏️',\n pen: '🖊️',\n fountain_pen: '🖋️',\n brush: '🖌️',\n ruler: '📏',\n pencil2: '✏️',\n black_nib: '✒️',\n memo: '📝',\n briefcase: '💼',\n file_folder: '📁',\n open_file_folder: '📂',\n page_with_curl: '📃',\n page_facing_up: '📄',\n calendar: '📅',\n calendar2: '📆',\n card_index: '📇',\n chart_with_upwards_trend: '📈',\n chart_with_downwards_trend: '📉',\n bar_chart: '📊',\n clipboard: '📋',\n pushpin: '📌',\n round_pushpin: '📍',\n paperclip: '📎',\n linked_paperclips: '🖇️',\n straight_ruler: '📏',\n triangular_ruler: '📐',\n scissors: '✂️',\n card_file_box: '🗃️',\n file_cabinet: '🗄️',\n wastebasket: '🗑️',\n lock: '🔒',\n unlock: '🔓',\n lock_with_ink_pen: '🔏',\n closed_lock_with_key: '🔐',\n key: '🔑',\n old_key: '🗝️',\n hammer: '🔨',\n axe: '🪓',\n pick: '⛏️',\n hammer_and_pick: '⚒️',\n hammer_and_wrench: '🛠️',\n dagger: '🗡️',\n crossed_swords: '⚔️',\n gun: '🔫',\n bow_and_arrow: '🏹',\n shield: '🛡️',\n carpentry_saw: '🪚',\n wrench: '🔧',\n nut_and_bolt: '🔩',\n gear: '⚙️',\n clamp: '🗜️',\n balance_scale: '⚖️',\n probe: '🔍',\n mag: '🔍',\n mag_right: '🔎',\n flashlight: '🔦',\n candle: '🕯️',\n light_bulb: '💡',\n electric_light_bulb: '💡',\n electric_plug: '🔌',\n battery: '🔋',\n computer: '💻',\n desktop_computer: '🖥️',\n printer: '🖨️',\n keyboard: '⌨️',\n mouse_three_button: '🖱️',\n trackball: '🖲️',\n minidisc: '💽',\n floppy_disk: '💾',\n cd: '💿',\n dvd: '📀',\n abacus: '🧮',\n movie_camera: '🎥',\n film_frames: '🎞️',\n film_projector: '📽️',\n clapper: '🎬',\n tv: '📺',\n camera: '📷',\n camera_with_flash: '📸',\n video_camera: '📹',\n vhs: '📼',\n phone: '📞',\n telephone: '☎️',\n pager: '📟',\n fax: '📠',\n email: '📧',\n mailbox: '📫',\n mailbox_with_mail: '📬',\n mailbox_with_no_mail: '📭',\n package: '📦',\n inbox_tray: '📥',\n outbox_tray: '📤',\n envelope: '✉️',\n incoming_envelope: '📨',\n envelope_with_arrow: '📩',\n outbox_tray: '📤',\n inbox_tray: '📥',\n postbox: '📮',\n mailbox_closed: '📪',\n mailbox: '📫',\n \n // Travel & Places\n car: '🚗',\n taxi: '🚕',\n blue_car: '🚙',\n bus: '🚌',\n trolleybus: '🚎',\n racing_car: '🏎️',\n police_car: '🚓',\n ambulance: '🚑',\n fire_engine: '🚒',\n minibus: '🚐',\n truck: '🚚',\n articulated_lorry: '🚛',\n tractor: '🚜',\n racing_motorcycle: '🏍️',\n motorcycle: '🛵',\n motor_scooter: '🛵',\n kick_scooter: '🛴',\n bike: '🚲',\n motorway: '🛣️',\n railway_track: '🛤️',\n steam_locomotive: '🚂',\n railway_car: '🚃',\n high_speed_train: '🚄',\n bullet_train_side: '🚅',\n bullet_train_front: '🚅',\n train2: '🚆',\n metro: '🚇',\n light_rail: '🚈',\n station: '🚉',\n tram: '🚊',\n monorail: '🚝',\n mountain_railway: '🚞',\n train: '🚋',\n busstop: '🚏',\n motor_boat: '🛥️',\n ship: '🚢',\n rowboat: '🚣',\n speedboat: '🚤',\n ferry: '⛴️',\n sailboat: '⛵',\n boat: '🛥️',\n anchor: '⚓',\n rocket: '🚀',\n flying_saucer: '🛸',\n helicopter: '🚁',\n small_airplane: '🛩️',\n airplane: '✈️',\n airplane_departure: '🛫',\n airplane_arrival: '🛬',\n seat: '💺',\n satellite: '🛰️',\n bellhop_bell: '🛎️',\n luggage: '🧳',\n hourglass: '⏳',\n hourglass_flowing_sand: '⏳',\n watch: '⌚',\n alarm_clock: '⏰',\n stopwatch: '⏱️',\n timer_clock: '⏲️',\n mantelpiece_clock: '🕰️',\n clock12: '🕛',\n clock1: '🕐',\n clock2: '🕑',\n clock3: '🕒',\n clock4: '🕓',\n clock5: '🕔',\n clock6: '🕕',\n clock7: '🕖',\n clock8: '🕗',\n clock9: '🕘',\n clock10: '🕙',\n clock11: '🕚',\n clock1230: '🕧',\n clock130: '🕜',\n clock230: '🕝',\n clock330: '🕞',\n clock430: '🕟',\n clock530: '🕠',\n clock630: '🕡',\n clock730: '🕢',\n clock830: '🕣',\n clock930: '🕤',\n clock1030: '🕥',\n clock1130: '🕦',\n new_moon: '🌑',\n waxing_crescent_moon: '🌒',\n first_quarter_moon: '🌓',\n waxing_gibbous_moon: '🌔',\n full_moon: '🌕',\n waning_gibbous_moon: '🌖',\n last_quarter_moon: '🌗',\n waning_crescent_moon: '🌘',\n crescent_moon: '🌙',\n new_moon_with_face: '🌚',\n first_quarter_moon_with_face: '🌛',\n last_quarter_moon_with_face: '🌜',\n thermometer: '🌡️',\n sun: '☀️',\n full_moon_with_face: '🌝',\n sun_with_face: '🌞',\n ringed_planet: '🪐',\n star: '⭐',\n star2: '🌟',\n stars: '🌟',\n milky_way: '🌌',\n cloud: '☁️',\n cloud_with_lightning_and_rain: '⛈️',\n sun_behind_small_cloud: '🌤️',\n sun_behind_large_cloud: '🌥️',\n sun_behind_rain_cloud: '🌦️',\n cloud_with_rain: '🌧️',\n cloud_with_snow: '🌨️',\n cloud_with_lightning: '🌩️',\n tornado: '🌪️',\n fog: '🌫️',\n wind_face: '🌬️',\n cyclone: '🌀',\n rainbow: '🌈',\n closed_umbrella: '🌂',\n open_umbrella: '☂️',\n umbrella: '☔',\n parasol_on_ground: '⛱️',\n zap: '⚡',\n snowflake: '❄️',\n snowman_with_snow: '☃️',\n snowman: '☃️',\n comet: '☄️',\n fire: '🔥',\n droplet: '💧',\n sweat_drops: '💦',\n ocean: '🌊',\n \n // Flags\n flag_us: '🇺🇸',\n flag_gb: '🇬🇧',\n flag_uk: '🇬🇧',\n flag_mx: '🇲🇽',\n flag_ca: '🇨🇦',\n flag_es: '🇪🇸',\n flag_fr: '🇫🇷',\n flag_de: '🇩🇪',\n flag_it: '🇮🇹',\n flag_jp: '🇯🇵',\n flag_kr: '🇰🇷',\n flag_cn: '🇨🇳',\n flag_in: '🇮🇳',\n flag_br: '🇧🇷',\n flag_ar: '🇦🇷',\n flag_au: '🇦🇺',\n flag_za: '🇿🇦',\n flag_ru: '🇷🇺',\n flag_sa: '🇸🇦',\n flag_ae: '🇦🇪',\n flag_il: '🇮🇱',\n flag_tr: '🇹🇷',\n flag_eg: '🇪🇬',\n flag_ng: '🇳🇬',\n flag_ke: '🇰🇪',\n flag_id: '🇮🇩',\n flag_ph: '🇵🇭',\n flag_th: '🇹🇭',\n flag_vn: '🇻🇳',\n flag_my: '🇲🇾',\n flag_sg: '🇸🇬',\n};\n\n// Curated Spanish aliases: everyday words that should land on the \"obvious\" emoji first.\nconst SPANISH_ALIASES = {\n '❤️': ['corazon', 'amor', 'te quiero'],\n '😂': ['risa', 'jaja', 'jajaja', 'llorar de risa'],\n '🤣': ['carcajada', 'muerto de risa'],\n '😀': ['feliz', 'contento'],\n '😊': ['sonrisa', 'sonrojado'],\n '😍': ['enamorado', 'me encanta'],\n '😘': ['beso'],\n '😉': ['guino'],\n '😎': ['genial', 'lentes de sol'],\n '😢': ['triste'],\n '😭': ['llorar', 'llanto'],\n '😡': ['enojado', 'furioso'],\n '😱': ['susto', 'miedo'],\n '🤔': ['pensando', 'pensar', 'hmm'],\n '🙄': ['ojos en blanco'],\n '😴': ['dormir', 'sueno'],\n '🔥': ['fuego', 'candela'],\n '👍': ['pulgar', 'pulgar arriba', 'like', 'bien'],\n '👎': ['pulgar abajo', 'dislike', 'mal'],\n '👏': ['aplausos', 'aplaudir'],\n '🙏': ['gracias', 'por favor', 'rezar'],\n '👋': ['hola', 'adios', 'saludo'],\n '💪': ['fuerza', 'musculo'],\n '🤝': ['trato', 'acuerdo'],\n '👌': ['perfecto'],\n '🎉': ['fiesta', 'celebrar', 'felicidades'],\n '🎂': ['cumpleanos', 'pastel'],\n '🎁': ['regalo'],\n '💯': ['cien'],\n '✅': ['listo', 'hecho'],\n '❌': ['error', 'cancelar'],\n '⭐': ['estrella'],\n '✨': ['brillo', 'destellos'],\n '💩': ['caca'],\n '👀': ['mirar', 'ojos'],\n '🚀': ['cohete'],\n '💰': ['dinero', 'plata'],\n};\n\nexport const normalizeEmojiQuery = (value) => String(value ?? '').normalize('NFD')\n .replace(/\\p{M}/gu, '').toLowerCase().replace(/:/g, '').replace(/_/g, ' ')\n .replace(/\\s+/g, ' ').trim();\n\nconst TONE_RE = /[\\u{1F3FB}-\\u{1F3FF}]/gu;\nconst identity = (value) => String(value).replace(/️/g, '');\nconst baseIdentity = (value) => identity(value).replace(TONE_RE, '');\nconst asList = (value) => (Array.isArray(value) ? value : value ? [value] : []);\nconst capitalize = (value) => (value ? value.charAt(0).toUpperCase() + value.slice(1) : value);\nconst compact = (value) => value.replace(/ /g, '');\nconst COMPONENT_GROUP = 2;\n\nexport const SKIN_TONES = [\n { tone: 0, label: 'Predeterminado', swatch: '✋' },\n { tone: 1, label: 'Claro', swatch: '✋🏻' },\n { tone: 2, label: 'Medio claro', swatch: '✋🏼' },\n { tone: 3, label: 'Medio', swatch: '✋🏽' },\n { tone: 4, label: 'Medio oscuro', swatch: '✋🏾' },\n { tone: 5, label: 'Oscuro', swatch: '✋🏿' },\n];\n\nconst buildCategories = (messages) => [['all', 'Todos'], ...messages.groups\n .filter((group) => group.order !== COMPONENT_GROUP)\n .map((group) => [String(group.order), capitalize(group.message)])];\n\n// Live binding: only 'all' until emojibase-data loads (see loadEmojiData).\nexport let emojiCategories = [['all', 'Todos']];\nexport function getEmojiCategories() { return emojiCategories; }\n\nconst legacyByEmoji = new Map();\nfor (const [alias, emoji] of Object.entries(EMOJI_SHORTCUTS)) {\n const key = identity(emoji);\n if (!legacyByEmoji.has(key)) legacyByEmoji.set(key, []);\n legacyByEmoji.get(key).push(alias);\n}\nconst curatedByEmoji = new Map(Object.entries(SPANISH_ALIASES).map(([emoji, list]) => [identity(emoji), list]));\n\n// Only skins where every modifier is the same tone (1F3FB..1F3FF → 1..5).\nconst toneOfHex = (hexcode) => {\n const tones = hexcode.split('-').filter((part) => /^1F3F[B-F]$/.test(part));\n if (!tones.length || tones.some((tone) => tone !== tones[0])) return 0;\n return parseInt(tones[0].slice(-1), 16) - 10;\n};\nconst buildSkins = (skins) => {\n const byTone = new Map();\n for (const skin of skins || []) {\n const tone = toneOfHex(skin.hexcode);\n if (tone && !byTone.has(tone)) byTone.set(tone, { tone, emoji: skin.unicode });\n }\n return byTone.size ? [...byTone.values()].sort((a, b) => a.tone - b.tone) : undefined;\n};\n\n// Built once when emojibase-data loads. Index contains BASE emojis only; skins hang off each record.\nfunction buildUnicodeIndex({ english, spanish, githubShortcodes, emojibaseShortcodes, iamcalShortcodes }) {\n const spanishByHex = new Map(spanish.map((item) => [item.hexcode, item]));\n return english\n .filter((item) => item.group != null && item.group !== COMPONENT_GROUP)\n .map((item) => {\n const localized = spanishByHex.get(item.hexcode);\n const key = identity(item.unicode);\n const legacy = legacyByEmoji.get(key) || [];\n const primary = [...legacy, ...asList(githubShortcodes[item.hexcode])];\n const secondary = [...asList(emojibaseShortcodes[item.hexcode]), ...asList(iamcalShortcodes[item.hexcode])];\n const curated = curatedByEmoji.get(key) || [];\n const shortcodes = [...new Set([...primary, ...secondary, ...curated.map((alias) => alias.replace(/ /g, '_'))])];\n const shortcode = shortcodes[0] || item.label.replace(/[^a-z0-9]+/gi, '_').replace(/^_|_$/g, '').toLowerCase();\n if (!shortcodes.length) shortcodes.push(shortcode);\n const labelEs = localized?.label || item.label;\n const keywords = [...new Set([...(localized?.tags || []), ...(item.tags || [])].map(normalizeEmojiQuery).filter(Boolean))];\n return {\n emoji: item.unicode,\n hexcode: item.hexcode,\n shortcode,\n shortcodes,\n label: capitalize(labelEs),\n labelEn: item.label,\n source: 'unicode',\n category: String(item.group),\n keywords,\n skins: buildSkins(item.skins),\n order: item.order ?? 0,\n terms: [...new Set([...shortcodes, labelEs, item.label, ...keywords].map(normalizeEmojiQuery).filter(Boolean))],\n // Primary aliases win resolve conflicts over secondary emojibase/iamcal names.\n _primary: [...primary, ...curated],\n };\n })\n .sort((a, b) => a.order - b.order);\n}\n\nconst customIndex = customEmojis.map((item, position) => ({\n ...item,\n emoji: `:${item.shortcode}:`,\n shortcodes: [item.shortcode, ...(item.shortcodes || [])],\n label: capitalize(item.label || item.shortcode),\n labelEn: item.label || item.shortcode,\n source: 'custom',\n category: 'custom',\n keywords: (item.keywords || []).map(normalizeEmojiQuery).filter(Boolean),\n skins: undefined,\n order: 100000 + position,\n terms: [...new Set([item.shortcode, item.label, ...(item.keywords || [])].filter(Boolean).map(normalizeEmojiQuery))],\n}));\n\nconst words = (value) => value.split(' ').filter(Boolean);\nconst setOnce = (map, key, value) => { if (key && !map.has(key)) map.set(key, value); };\n\nfunction buildState(unicodeIndex) {\n // Strip internal helper fields from public records.\n const primaryAliases = new Map();\n for (const record of unicodeIndex) {\n primaryAliases.set(record, record._primary.map(normalizeEmojiQuery));\n delete record._primary;\n }\n\n const index = [...unicodeIndex, ...customIndex];\n\n // Precomputed normalized search data (parallel to `index`).\n const searchData = index.map((record) => {\n const aliases = [...new Set(record.shortcodes.map(normalizeEmojiQuery).filter(Boolean))];\n const labels = [...new Set([record.label, record.labelEn].filter(Boolean).map(normalizeEmojiQuery))];\n return {\n record,\n aliases,\n aliasCompact: aliases.map(compact),\n aliasWords: aliases.flatMap((alias) => words(alias).map((word) => [word, alias.length])),\n labels,\n labelWords: labels.flatMap((label) => words(label).map((word) => [word, label.length])),\n keywords: record.keywords,\n keywordWords: record.keywords.flatMap((keyword) => words(keyword).map((word) => [word, keyword.length])),\n terms: record.terms,\n };\n });\n\n // Lookup maps.\n const byEmoji = new Map();\n const aliasMap = new Map();\n const labelMap = new Map();\n const termMap = new Map();\n for (const record of unicodeIndex) {\n setOnce(byEmoji, identity(record.emoji), record);\n for (const skin of record.skins || []) setOnce(byEmoji, identity(skin.emoji), record);\n for (const alias of primaryAliases.get(record)) setOnce(aliasMap, alias, record);\n }\n for (const data of searchData) {\n if (data.record.source !== 'unicode') continue;\n for (const alias of data.aliases) { setOnce(aliasMap, alias, data.record); setOnce(aliasMap, compact(alias), data.record); }\n for (const label of data.labels) setOnce(labelMap, label, data.record);\n for (const term of data.terms) setOnce(termMap, term, data.record);\n }\n // Fallback lookup for toned sequences not listed explicitly (e.g. mixed tones).\n for (const record of unicodeIndex) setOnce(byEmoji, baseIdentity(record.emoji), record);\n return { index, searchData, byEmoji, aliasMap, labelMap, termMap };\n}\n\nconst customByCode = new Map(customIndex.map((record) => [normalizeEmojiQuery(record.shortcode), record]));\n\n// Lazy loading state. `state` starts with custom emojis only and is swapped atomically on load.\nlet state = buildState([]);\nlet loaded = false;\nlet loading = null;\nconst listeners = new Set();\n\nexport function isEmojiDataLoaded() { return loaded; }\n\nexport function subscribeEmojiData(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n}\n\n// Loads emojibase-data once (cached promise). Resolves true when ready, false if loading failed\n// (a later call retries).\nexport function loadEmojiData() {\n if (loaded) return Promise.resolve(true);\n if (!loading) {\n loading = loadSources().then(([english, spanish, githubShortcodes, emojibaseShortcodes, iamcalShortcodes, messages]) => {\n state = buildState(buildUnicodeIndex({ english, spanish, githubShortcodes, emojibaseShortcodes, iamcalShortcodes }));\n emojiCategories = buildCategories(messages);\n loaded = true;\n for (const listener of [...listeners]) {\n try { listener(); } catch (error) { console.error('[chat] emoji data listener failed', error); }\n }\n return true;\n }).catch((error) => {\n loading = null;\n console.warn('[chat] could not load emojibase-data', error);\n return false;\n });\n }\n return loading;\n}\n\nconst ensureEmojiData = () => { if (!loaded && !loading) loadEmojiData(); };\n\n// Tiers: 0 exact alias/label · 1 alias prefix · 2 label/word prefix · 3 keyword prefix · 4 substring.\n// Inside a tier the shortest matching term wins.\nconst TIER = 10000;\nconst NO_MATCH = Infinity;\nfunction scoreWord(data, q) {\n if (data.aliases.includes(q) || data.aliasCompact.includes(q) || data.labels.includes(q)) return q.length;\n let best = NO_MATCH;\n for (let i = 0; i < data.aliases.length; i += 1) {\n if (data.aliases[i].startsWith(q) || data.aliasCompact[i].startsWith(q)) best = Math.min(best, TIER + data.aliases[i].length);\n }\n if (best !== NO_MATCH) return best;\n for (const label of data.labels) if (label.startsWith(q)) best = Math.min(best, 2 * TIER + label.length);\n for (const [word, length] of data.labelWords) if (word.startsWith(q)) best = Math.min(best, 2 * TIER + length);\n for (const [word, length] of data.aliasWords) if (word.startsWith(q)) best = Math.min(best, 2 * TIER + length);\n if (best !== NO_MATCH) return best;\n for (const keyword of data.keywords) if (keyword.startsWith(q)) best = Math.min(best, 3 * TIER + keyword.length);\n for (const [word, length] of data.keywordWords) if (word.startsWith(q)) best = Math.min(best, 3 * TIER + length);\n if (best !== NO_MATCH) return best;\n for (const term of data.terms) if (term.includes(q)) best = Math.min(best, 4 * TIER + term.length);\n return best;\n}\nfunction scoreQuery(data, q, parts) {\n let score = scoreWord(data, q);\n if (parts.length > 1 && score >= TIER) {\n let worst = 0;\n for (const part of parts) {\n worst = Math.max(worst, scoreWord(data, part));\n if (worst === NO_MATCH) break;\n }\n score = Math.min(score, worst);\n }\n return score;\n}\n\nexport function getAllEmojiShortcodes() { ensureEmojiData(); return state.index; }\n\nexport function searchEmojiShortcodes(query, { limit = 10, source, category } = {}) {\n ensureEmojiData();\n const normalized = normalizeEmojiQuery(query);\n const raw = identity(String(query ?? '').trim());\n const parts = words(normalized);\n const results = [];\n for (const data of state.searchData) {\n const { record } = data;\n if (source && record.source !== source) continue;\n if (category && category !== 'all' && record.category !== category) continue;\n let score;\n if (!normalized) score = 0;\n else if (raw && (identity(record.emoji) === raw || record.skins?.some((skin) => identity(skin.emoji) === raw))) score = 0;\n else score = scoreQuery(data, normalized, parts);\n if (score !== NO_MATCH) results.push({ record, score });\n }\n results.sort((a, b) => a.score - b.score || a.record.order - b.record.order);\n return results.slice(0, limit).map(({ record }) => record);\n}\n\nexport function getEmojisByCategory(category) {\n ensureEmojiData();\n if (!category || category === 'all') return state.index;\n return state.index.filter((record) => record.category === category);\n}\n\nexport function getEmojiRecord(emoji) {\n if (emoji == null) return null;\n ensureEmojiData();\n const value = String(emoji).trim();\n if (/^:[^:\\s]+:$/.test(value)) {\n const code = normalizeEmojiQuery(value);\n return customByCode.get(code) || state.aliasMap.get(code) || null;\n }\n return state.byEmoji.get(identity(value)) || state.byEmoji.get(baseIdentity(value)) || null;\n}\n\nexport function applySkinTone(itemOrEmoji, tone) {\n const record = typeof itemOrEmoji === 'string'\n ? getEmojiRecord(itemOrEmoji)\n : (itemOrEmoji?.skins ? itemOrEmoji : getEmojiRecord(itemOrEmoji?.emoji));\n const fallback = typeof itemOrEmoji === 'string' ? itemOrEmoji : itemOrEmoji?.emoji ?? null;\n if (!record) return fallback;\n const level = Number(tone) || 0;\n if (!level || !record.skins) return record.emoji;\n return record.skins.find((skin) => skin.tone === level)?.emoji || record.emoji;\n}\n\n// Resolve only completed tokens. Partial words stay editable in autocomplete.\nexport function resolveEmojiShortcode(shortcode) {\n const alias = String(shortcode).toLowerCase();\n if (Object.prototype.hasOwnProperty.call(EMOJI_SHORTCUTS, alias)) return EMOJI_SHORTCUTS[alias];\n const query = normalizeEmojiQuery(shortcode);\n if (!query) return null;\n ensureEmojiData();\n const { aliasMap, labelMap, termMap } = state;\n return (aliasMap.get(query) || aliasMap.get(compact(query)) || labelMap.get(query) || termMap.get(query))?.emoji || null;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n// Local-only emoji preferences (no backend, no cross-device sync).\nexport const MAX_RECENT_EMOJIS = 32;\nexport const MAX_FAVORITE_EMOJIS = 60;\nconst STORAGE_KEY = 'lira-emoji-preferences:v1';\nconst LEGACY_RECENTS_KEY = 'lira-chat-recent-emojis';\nconst MAX_EMOJI_LENGTH = 64;\nconst hasWindow = typeof window !== 'undefined';\n\n// C0/C1 control characters (ZWJ / variation selectors are allowed).\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARS = /[\\u0000-\\u001F\\u007F-\\u009F]/;\n\n/** Unicode emoji (optionally skin-toned) or custom shortcode like ':party_parrot:'. */\nfunction sanitizeEmoji(value) {\n if (typeof value !== 'string') return null;\n if (!value || value.length > MAX_EMOJI_LENGTH || CONTROL_CHARS.test(value)) return null;\n return value;\n}\n\nfunction sanitizeSkinTone(value) {\n return Number.isInteger(value) && value >= 0 && value <= 5 ? value : 0;\n}\n\n// Sanitize + dedupe (first occurrence wins) + cap.\nfunction cleanList(list, max) {\n if (!Array.isArray(list)) return [];\n const seen = new Set();\n const out = [];\n for (const raw of list) {\n const emoji = sanitizeEmoji(raw);\n if (!emoji || seen.has(emoji)) continue;\n seen.add(emoji);\n out.push(emoji);\n if (out.length >= max) break;\n }\n return out;\n}\n\nconst EMPTY = { recents: [], favorites: [], skinTone: 0 };\n\nfunction parse(data) {\n return {\n recents: cleanList(data?.recents, MAX_RECENT_EMOJIS),\n favorites: cleanList(data?.favorites, MAX_FAVORITE_EMOJIS),\n skinTone: sanitizeSkinTone(data?.skinTone),\n };\n}\n\nfunction readStorage() {\n if (!hasWindow) return { ...EMPTY };\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return { ...EMPTY };\n return parse(JSON.parse(raw));\n } catch {\n return { ...EMPTY };\n }\n}\n\n// Private mode / quota errors are ignored: state stays in memory.\nfunction writeStorage({ recents, favorites, skinTone }) {\n if (!hasWindow) return;\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ recents, favorites, skinTone }));\n } catch {\n /* keep in memory */\n }\n}\n\n/**\n * One-time migration from the legacy recents key (array or { recents }).\n * Returns true when the current storage key was written.\n */\nfunction migrateLegacy() {\n if (!hasWindow) return false;\n let wrote = false;\n try {\n const legacy = window.localStorage.getItem(LEGACY_RECENTS_KEY);\n if (legacy == null) return false;\n if (!window.localStorage.getItem(STORAGE_KEY)) {\n let data = null;\n try {\n data = JSON.parse(legacy);\n } catch {\n data = null;\n }\n const recents = cleanList(Array.isArray(data) ? data : data?.recents, MAX_RECENT_EMOJIS);\n writeStorage({ ...EMPTY, recents });\n wrote = true;\n }\n window.localStorage.removeItem(LEGACY_RECENTS_KEY);\n } catch {\n /* ignore */\n }\n return wrote;\n}\n\nexport function createEmojiPreferencesStore() {\n const store = createStore((set, get) => {\n // Persist after every local mutation.\n const commit = (next) => {\n set(next);\n writeStorage(get());\n };\n\n return {\n ...readStorage(),\n\n isFavorite: (emoji) => {\n const key = sanitizeEmoji(emoji);\n return key ? get().favorites.includes(key) : false;\n },\n\n toggleFavorite: (raw) => {\n const emoji = sanitizeEmoji(raw);\n if (!emoji) return;\n const { favorites } = get();\n if (favorites.includes(emoji)) {\n commit({ favorites: favorites.filter((item) => item !== emoji) });\n return;\n }\n commit({ favorites: [emoji, ...favorites].slice(0, MAX_FAVORITE_EMOJIS) });\n },\n\n addRecent: (raw) => {\n const emoji = sanitizeEmoji(raw);\n if (!emoji) return;\n const rest = get().recents.filter((item) => item !== emoji);\n commit({ recents: [emoji, ...rest].slice(0, MAX_RECENT_EMOJIS) });\n },\n\n setSkinTone: (tone) => {\n if (!Number.isInteger(tone) || tone < 0 || tone > 5) return;\n if (get().skinTone === tone) return;\n commit({ skinTone: tone });\n },\n\n clearRecents: () => commit({ recents: [] }),\n };\n });\n\n // Cross-tab sync: another tab wrote (or storage was cleared) -> re-read.\n // Explicit opt-in (no import-time side effects). Ref-counted: the listener is\n // registered once and removed when every caller has called its stop().\n let syncRefs = 0;\n let migrated = false;\n const onStorage = (event) => {\n if (event.key === STORAGE_KEY || event.key === null) store.setState(readStorage());\n };\n store.startSync = () => {\n if (!hasWindow) return () => {};\n if (!migrated) {\n migrated = true;\n if (migrateLegacy()) store.setState(readStorage());\n }\n if (typeof window.addEventListener !== 'function') return () => {};\n if (syncRefs === 0) window.addEventListener('storage', onStorage);\n syncRefs += 1;\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n syncRefs -= 1;\n if (syncRefs === 0) window.removeEventListener('storage', onStorage);\n };\n };\n return store;\n}\n\nconst emojiPreferencesStore = createEmojiPreferencesStore();\n/** Backward-compatible singleton hook; called without selector it returns the full state. */\nexport const useEmojiPreferences = Object.assign((selector) => useStore(emojiPreferencesStore, selector), {\n getState: emojiPreferencesStore.getState,\n setState: emojiPreferencesStore.setState,\n subscribe: emojiPreferencesStore.subscribe,\n});\n\nexport function startEmojiPreferencesSync(store = emojiPreferencesStore) {\n return (store === useEmojiPreferences ? emojiPreferencesStore : store).startSync();\n}\n","import { useEffect, useSyncExternalStore } from 'react';\nimport { isEmojiDataLoaded, loadEmojiData, subscribeEmojiData } from './emojiShortcodes';\n\n// True once emojibase-data has loaded; mounting the hook starts the (cached) load. Components use the\n// value as a memo/effect dependency so they recompute when the full catalog arrives.\nexport function useEmojiDataReady() {\n const ready = useSyncExternalStore(subscribeEmojiData, isEmojiDataLoaded, isEmojiDataLoaded);\n useEffect(() => { if (!ready) loadEmojiData(); }, [ready]);\n return ready;\n}\n","/* eslint-disable react/prop-types */\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Car, Clock, Flag, Hand, Heart, Lightbulb, PawPrint, Puzzle, Smile, Sparkles, Star, Trophy, Utensils, X } from 'lucide-react';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nimport { searchCustomEmojis } from '../../media/emoji/customEmojiCatalog';\nimport {\n SKIN_TONES, applySkinTone, emojiCategories, getEmojiRecord, getEmojisByCategory, searchEmojiShortcodes,\n} from '../../media/emoji/emojiShortcodes';\nimport { useEmojiPreferences } from '../../media/emoji/emojiPreferences';\nimport { useEmojiDataReady } from '../../media/emoji/useEmojiData';\nimport MessageText from './MessageText';\nimport '../styles/EmojiPicker.css';\n\nconst categoryIcons = { recent: Clock, favorites: Star, 0: Smile, 1: Hand, 2: Puzzle, 3: PawPrint, 4: Utensils, 5: Car, 6: Trophy, 7: Lightbulb, 8: Heart, 9: Flag, custom: Sparkles };\nconst CELL_SIZE = 40;\nconst ESTIMATED_COLUMNS = 9;\nconst LONG_PRESS_MS = 500;\n\n// Resolve a stored string (recent/favorite) back to a record for labels and preview.\nfunction resolveRecord(value, customRecords) {\n const custom = customRecords.find((item) => item.emoji === value);\n if (custom) return custom;\n const record = getEmojiRecord(value);\n return record || { emoji: value, shortcode: '', label: value, source: 'unicode' };\n}\n\nconst EmojiCell = memo(function EmojiCell({ record, value, favorite, disabled, onPick, onToggleFavorite, onPreview }) {\n const timer = useRef(null);\n const longPressed = useRef(false);\n const clear = () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } };\n useEffect(() => clear, []);\n return <button type=\"button\" role=\"option\" aria-selected=\"false\"\n className={`chat-emoji-cell${favorite ? ' chat-emoji-cell--fav' : ''}`}\n data-value={value} title={record.label} aria-label={record.label} disabled={disabled}\n onMouseDown={(event) => event.preventDefault()}\n onMouseEnter={() => onPreview(record, value)} onFocus={() => onPreview(record, value)}\n onContextMenu={(event) => { event.preventDefault(); if (!disabled) onToggleFavorite(record); }}\n onTouchStart={() => {\n longPressed.current = false; clear();\n timer.current = setTimeout(() => { longPressed.current = true; timer.current = null; if (!disabled) onToggleFavorite(record); }, LONG_PRESS_MS);\n }}\n onTouchMove={clear} onTouchEnd={clear} onTouchCancel={clear}\n onClick={(event) => {\n if (longPressed.current) { event.preventDefault(); longPressed.current = false; return; }\n onPick(value);\n }}>\n <MessageText text={value} />\n </button>;\n});\n\nfunction EmojiSection({ id, title, items, lazy, rootRef, children, ...cellProps }) {\n const ref = useRef(null);\n const [visible, setVisible] = useState(!lazy);\n useEffect(() => {\n if (visible || !ref.current) return undefined;\n if (typeof IntersectionObserver === 'undefined') { setVisible(true); return undefined; }\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) { setVisible(true); observer.disconnect(); }\n }, { root: rootRef.current, rootMargin: '400px 0px' });\n observer.observe(ref.current);\n return () => observer.disconnect();\n }, [visible, rootRef]);\n const minHeight = visible ? undefined : Math.ceil(items.length / ESTIMATED_COLUMNS) * CELL_SIZE;\n return <section ref={ref} className=\"chat-emoji-section\" data-section={id} aria-labelledby={`chat-emoji-sec-${id}`}>\n <h3 id={`chat-emoji-sec-${id}`} className=\"chat-emoji-section-title\">{title}</h3>\n <div className=\"chat-emoji-grid chat-emoji-grid--modern\" role=\"listbox\" aria-label={title} style={minHeight ? { minHeight } : undefined}>\n {visible && items.map(({ record, value }) => <EmojiCell key={value} record={record} value={value}\n favorite={cellProps.favoriteSet.has(record.emoji)} disabled={cellProps.disabled}\n onPick={cellProps.onPick} onToggleFavorite={cellProps.onToggleFavorite} onPreview={cellProps.onPreview} />)}\n </div>\n {children}\n </section>;\n}\n\nexport default function EmojiPicker({ onSelect, isOpen, onClose, disabled }) {\n const customRecords = useCustomEmojis();\n const recents = useEmojiPreferences((state) => state.recents);\n const favorites = useEmojiPreferences((state) => state.favorites);\n const skinTone = useEmojiPreferences((state) => state.skinTone);\n const addRecent = useEmojiPreferences((state) => state.addRecent);\n const toggleFavorite = useEmojiPreferences((state) => state.toggleFavorite);\n const setSkinTone = useEmojiPreferences((state) => state.setSkinTone);\n const emojiReady = useEmojiDataReady(); // catalog loads lazily; recompute sections when it lands\n\n const [query, setQuery] = useState('');\n const [toneOpen, setToneOpen] = useState(false);\n const [activeSection, setActiveSection] = useState(null);\n const [preview, setPreview] = useState(null);\n const bodyRef = useRef(null);\n const searchRef = useRef(null);\n const scrollFrame = useRef(0);\n\n const favoriteSet = useMemo(() => new Set(favorites || []), [favorites]);\n const toValue = useCallback((record) => (record.source === 'custom' ? record.emoji : applySkinTone(record, skinTone)), [skinTone]);\n const trimmed = query.trim();\n\n const sections = useMemo(() => {\n const wrap = (records) => {\n const seen = new Set();\n return records.map((record) => ({ record, value: toValue(record) }))\n .filter(({ value }) => (seen.has(value) ? false : seen.add(value)));\n };\n if (trimmed) {\n return [{ id: 'results', title: 'Resultados', items: wrap([...searchCustomEmojis(customRecords, query), ...searchEmojiShortcodes(query, { limit: 120 })].slice(0, 120)), lazy: false }];\n }\n const list = [];\n if (recents?.length) {\n const seen = new Set();\n list.push({ id: 'recent', title: 'Recientes', lazy: false,\n items: recents.filter((value) => (seen.has(value) ? false : seen.add(value))).map((value) => ({ record: resolveRecord(value, customRecords), value })) });\n }\n if (favorites?.length) list.push({ id: 'favorites', title: 'Favoritos', lazy: false, items: wrap(favorites.map((value) => resolveRecord(value, customRecords))) });\n emojiCategories.filter(([id]) => id !== 'all').forEach(([id, label], index) => {\n const records = getEmojisByCategory(id) || [];\n if (records.length) list.push({ id, title: label, items: wrap(records), lazy: index > 0 });\n });\n if (customRecords.length) list.push({ id: 'custom', title: 'Personalizados', items: wrap(customRecords), lazy: true });\n return list;\n }, [trimmed, query, recents, favorites, toValue, emojiReady, customRecords]);\n\n const firstItem = sections.find((section) => section.items.length)?.items[0] || null;\n const shown = preview || (firstItem && { record: firstItem.record, value: firstItem.value });\n\n const onPick = useCallback((value) => { onSelect(value); addRecent(value); }, [onSelect, addRecent]);\n const onToggleFavorite = useCallback((record) => toggleFavorite(record.emoji), [toggleFavorite]);\n const onPreview = useCallback((record, value) => setPreview({ record, value }), []);\n\n // Active tab follows scroll position.\n const updateActive = useCallback(() => {\n const body = bodyRef.current;\n if (!body) return;\n const nodes = [...body.querySelectorAll('[data-section]')];\n const top = body.getBoundingClientRect().top;\n let current = nodes[0]?.dataset.section || null;\n for (const node of nodes) { if (node.getBoundingClientRect().top - top <= 8) current = node.dataset.section; else break; }\n setActiveSection(current);\n }, []);\n useEffect(() => {\n if (!isOpen) return undefined;\n updateActive();\n return () => cancelAnimationFrame(scrollFrame.current);\n }, [isOpen, sections, updateActive]);\n useEffect(() => { if (!isOpen) { setQuery(''); setToneOpen(false); setPreview(null); } }, [isOpen]);\n\n const scrollToSection = (id) => {\n const body = bodyRef.current;\n const node = body?.querySelector(`[data-section=\"${id}\"]`);\n if (!node) return;\n body.scrollTo({ top: node.offsetTop - body.firstElementChild.offsetTop, behavior: 'auto' });\n setActiveSection(id);\n };\n\n const focusCell = (cell) => { if (cell) { cell.focus(); cell.scrollIntoView({ block: 'nearest' }); } };\n const columnsOf = (grid) => {\n const cells = [...grid.querySelectorAll('.chat-emoji-cell')];\n if (!cells.length) return 1;\n const top = cells[0].offsetTop;\n return Math.max(1, cells.filter((cell) => cell.offsetTop === top).length);\n };\n\n const onBodyKeyDown = (event) => {\n const cell = event.target.closest?.('.chat-emoji-cell');\n if (!cell) return;\n const body = bodyRef.current;\n const grids = [...body.querySelectorAll('.chat-emoji-grid')].filter((grid) => grid.querySelector('.chat-emoji-cell'));\n const all = [...body.querySelectorAll('.chat-emoji-cell')];\n const grid = cell.closest('.chat-emoji-grid');\n const gridIndex = grids.indexOf(grid);\n const cells = [...grid.querySelectorAll('.chat-emoji-cell')];\n const index = cells.indexOf(cell);\n const cols = columnsOf(grid);\n let target = null;\n switch (event.key) {\n case 'ArrowRight': target = all[all.indexOf(cell) + 1]; break;\n case 'ArrowLeft': target = all[all.indexOf(cell) - 1]; break;\n case 'ArrowDown': {\n if (index + cols < cells.length) target = cells[index + cols];\n else if (Math.floor(index / cols) < Math.floor((cells.length - 1) / cols)) target = cells[cells.length - 1];\n else if (grids[gridIndex + 1]) {\n const next = [...grids[gridIndex + 1].querySelectorAll('.chat-emoji-cell')];\n target = next[Math.min(index % cols, next.length - 1)];\n }\n break;\n }\n case 'ArrowUp': {\n if (index - cols >= 0) target = cells[index - cols];\n else if (grids[gridIndex - 1]) {\n const prev = [...grids[gridIndex - 1].querySelectorAll('.chat-emoji-cell')];\n const prevCols = columnsOf(grids[gridIndex - 1]);\n const lastRowStart = Math.floor((prev.length - 1) / prevCols) * prevCols;\n target = prev[Math.min(lastRowStart + (index % cols), prev.length - 1)];\n } else { event.preventDefault(); searchRef.current?.focus(); return; }\n break;\n }\n case 'PageDown': target = grids[gridIndex + 1]?.querySelector('.chat-emoji-cell'); break;\n case 'PageUp': target = (index > 0 ? grid : grids[gridIndex - 1])?.querySelector('.chat-emoji-cell'); break;\n case 'Home': target = all[0]; break;\n case 'End': target = all[all.length - 1]; break;\n case 'Enter': case ' ': event.preventDefault(); if (!cell.disabled) cell.click(); return;\n default: return;\n }\n event.preventDefault();\n focusCell(target);\n };\n\n if (!isOpen) return null;\n const currentTone = SKIN_TONES.find((item) => item.tone === skinTone) || SKIN_TONES[0];\n const navTabs = [\n ...(recents?.length ? [['recent', 'Recientes']] : []),\n ...(favorites?.length ? [['favorites', 'Favoritos']] : []),\n ...emojiCategories.filter(([id]) => id !== 'all' && (getEmojisByCategory(id) || []).length),\n ...(customRecords.length ? [['custom', 'Personalizados']] : []),\n ];\n const previewFav = shown ? favoriteSet.has(shown.record.emoji) : false;\n const previewCode = shown?.record.shortcode ? `:${shown.record.shortcode}:` : '';\n\n return <div className=\"chat-emoji-picker chat-emoji-picker--modern\" role=\"dialog\" aria-label=\"Seleccionar emoji\" onKeyDown={(event) => {\n if (event.key !== 'Escape') return;\n event.preventDefault(); event.stopPropagation();\n if (toneOpen) setToneOpen(false); else onClose();\n }}>\n <div className=\"chat-emoji-top\">\n <input ref={searchRef} className=\"chat-emoji-search\" type=\"search\" autoFocus\n aria-label=\"Buscar emoji en español o inglés\" placeholder=\"Buscar emoji (español o inglés)…\"\n value={query} onChange={(event) => { setQuery(event.target.value); setPreview(null); bodyRef.current?.scrollTo({ top: 0 }); }}\n onKeyDown={(event) => {\n if (event.key !== 'ArrowDown') return;\n event.preventDefault();\n focusCell(bodyRef.current?.querySelector('.chat-emoji-cell'));\n }} />\n <div className=\"chat-emoji-tone\">\n <button type=\"button\" className=\"chat-emoji-tone-btn\" aria-haspopup=\"menu\" aria-expanded={toneOpen}\n aria-label={`Tono de piel: ${currentTone?.label || ''}`} title=\"Tono de piel\" onClick={() => setToneOpen((open) => !open)}>\n <span className=\"chat-emoji-tone-swatch\" style={{ background: currentTone?.swatch }} aria-hidden=\"true\" />\n </button>\n {toneOpen && <div className=\"chat-emoji-tone-menu\" role=\"menu\" aria-label=\"Tono de piel\">\n {SKIN_TONES.map((item) => <button key={String(item.tone)} type=\"button\" role=\"menuitemradio\"\n className=\"chat-emoji-tone-option\" aria-checked={item.tone === skinTone} aria-label={item.label} title={item.label}\n onClick={() => { setSkinTone(item.tone); setToneOpen(false); }}>\n <span className=\"chat-emoji-tone-swatch\" style={{ background: item.swatch }} aria-hidden=\"true\" />\n </button>)}\n </div>}\n </div>\n <button type=\"button\" className=\"chat-btn\" aria-label=\"Cerrar emojis\" onClick={onClose}><X size={16} /></button>\n </div>\n {!trimmed && <div className=\"chat-emoji-nav\" role=\"tablist\" aria-label=\"Categorías de emojis\">\n {navTabs.map(([id, label]) => { const Icon = categoryIcons[id] || Smile; return <button key={id} type=\"button\" role=\"tab\"\n className=\"chat-emoji-nav-btn\" title={label} aria-label={label} aria-selected={activeSection === id}\n onClick={() => scrollToSection(id)}><Icon size={16} aria-hidden=\"true\" /></button>; })}\n </div>}\n <div ref={bodyRef} className=\"chat-emoji-body\" onKeyDown={onBodyKeyDown} onScroll={() => {\n cancelAnimationFrame(scrollFrame.current);\n scrollFrame.current = requestAnimationFrame(updateActive);\n }}>\n {sections.map((section) => (section.id === 'results' && !section.items.length\n ? <p key=\"empty\" className=\"chat-emoji-empty\" role=\"status\">No se encontraron emojis</p>\n : <EmojiSection key={`${section.id}-${trimmed ? 'q' : 'b'}`} {...section} rootRef={bodyRef}\n favoriteSet={favoriteSet} disabled={disabled} onPick={onPick} onToggleFavorite={onToggleFavorite} onPreview={onPreview} />))}\n </div>\n <div className=\"chat-emoji-preview\" aria-live=\"polite\">\n {shown && <>\n <span className=\"chat-emoji-preview-emoji\" aria-hidden=\"true\"><MessageText text={shown.value} /></span>\n <span className=\"chat-emoji-preview-info\">\n <span className=\"chat-emoji-preview-name\">{shown.record.label}</span>\n {previewCode && <span className=\"chat-emoji-preview-code\">{previewCode}</span>}\n </span>\n <button type=\"button\" className=\"chat-emoji-fav-btn\" aria-pressed={previewFav}\n aria-label={previewFav ? 'Quitar de favoritos' : 'Agregar a favoritos'} title={previewFav ? 'Quitar de favoritos' : 'Agregar a favoritos'}\n onClick={() => toggleFavorite(shown.record.emoji)}>\n <Star size={16} aria-hidden=\"true\" fill={previewFav ? 'currentColor' : 'none'} />\n </button>\n </>}\n </div>\n </div>;\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport { Plus } from 'lucide-react';\nimport EmojiPicker from './EmojiPicker';\nimport MessageText from './MessageText';\n\nconst QUICK_REACTIONS = [\n ['👍', 'Me gusta'],\n ['❤️', 'Me encanta'],\n ['😂', 'Me divierte'],\n ['😮', 'Me asombra'],\n ['😢', 'Me entristece'],\n ['🙏', 'Gracias'],\n];\n\nexport default function ReactionPicker({ onSelect, onClose, align = 'start' }) {\n const [full, setFull] = useState(false);\n const rootRef = useRef(null);\n const quickRef = useRef(null);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n\n useEffect(() => {\n quickRef.current?.querySelector('.chat-reaction-picker__option')?.focus();\n }, []);\n\n useEffect(() => {\n const handlePointerDown = (event) => {\n if (rootRef.current && rootRef.current.contains(event.target)) return;\n onCloseRef.current?.();\n };\n document.addEventListener('pointerdown', handlePointerDown);\n return () => document.removeEventListener('pointerdown', handlePointerDown);\n }, []);\n\n const choose = (emoji) => { if (emoji) onSelect(emoji); };\n\n return <div ref={rootRef} className={`chat-reaction-picker chat-reaction-picker--${align}${full ? ' chat-reaction-picker--full' : ''}`} role=\"dialog\" aria-label=\"Reaccionar\" onKeyDown={(event) => {\n if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); onClose(); }\n }}>\n {full\n ? <EmojiPicker isOpen onSelect={choose} onClose={onClose} />\n : <div ref={quickRef} className=\"chat-reaction-picker__quick\" role=\"group\" aria-label=\"Reacciones rápidas\" onKeyDown={(event) => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return;\n const buttons = [...event.currentTarget.querySelectorAll('button')];\n const current = buttons.indexOf(document.activeElement);\n if (current < 0 || !buttons.length) return;\n event.preventDefault(); event.stopPropagation();\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? buttons.length - 1\n : (current + (event.key === 'ArrowRight' ? 1 : -1) + buttons.length) % buttons.length;\n buttons[next].focus();\n }}>\n {QUICK_REACTIONS.map(([emoji, label]) => <button key={emoji} type=\"button\" className=\"chat-reaction-picker__option\" title={label} aria-label={label}\n onMouseDown={(event) => event.preventDefault()} onClick={() => choose(emoji)}><MessageText text={emoji} /></button>)}\n <button type=\"button\" className=\"chat-reaction-picker__more\" title=\"Más emojis\" aria-label=\"Más emojis\" onClick={() => setFull(true)}><Plus size={16} aria-hidden=\"true\" /></button>\n </div>}\n </div>;\n}\n","import { createContext, useContext } from 'react';\n\n// ownIds: ids (string|number) that identify the current user.\n// resolveName(userId): display name for a user id, or null if unknown.\nexport const ChatPeopleContext = createContext({ ownIds: [], resolveName: () => null });\n\nexport const useChatPeople = () => useContext(ChatPeopleContext);\n","/* eslint-disable react/prop-types */\nimport { memo, useEffect, useRef, useState } from 'react';\nimport MessageText from './MessageText';\nimport { useChatPeople } from '../chatPeopleContext';\n\nconst MAX_NAMES = 10;\nconst BUMP_MS = 300;\n\nconst prefersReducedMotion = () => typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n\nfunction ReactionBar({ reactions = [], onToggle, disabled }) {\n const { ownIds: ownIdList, resolveName } = useChatPeople();\n const [bumped, setBumped] = useState(() => new Set());\n const prevCounts = useRef(null);\n const timers = useRef({});\n\n useEffect(() => {\n const next = {};\n const grown = [];\n for (const { emoji, count } of reactions) {\n next[emoji] = count;\n if (prevCounts.current && count > (prevCounts.current[emoji] ?? 0)) grown.push(emoji);\n }\n prevCounts.current = next;\n if (!grown.length || prefersReducedMotion()) return;\n setBumped((prev) => new Set([...prev, ...grown]));\n for (const emoji of grown) {\n clearTimeout(timers.current[emoji]);\n timers.current[emoji] = setTimeout(() => {\n delete timers.current[emoji];\n setBumped((prev) => {\n if (!prev.has(emoji)) return prev;\n const copy = new Set(prev);\n copy.delete(emoji);\n return copy;\n });\n }, BUMP_MS);\n }\n }, [reactions]);\n\n useEffect(() => () => Object.values(timers.current).forEach(clearTimeout), []);\n\n if (!reactions.length) return null;\n\n const ownIds = new Set((ownIdList || []).map(String));\n const nameOf = (id) => {\n const key = String(id);\n if (ownIds.has(key)) return 'Tú';\n return resolveName?.(key) || 'Usuario';\n };\n const titleFor = (userIds = []) => {\n const names = userIds.slice(0, MAX_NAMES).map(nameOf);\n const rest = userIds.length - names.length;\n return rest > 0 ? `${names.join(', ')} y ${rest} más` : names.join(', ');\n };\n\n return <div className=\"chat-reaction-bar\" role=\"group\" aria-label=\"Reacciones\">\n {reactions.map(({ emoji, count, mine, userIds }) => <button\n key={emoji}\n type=\"button\"\n className={`chat-reaction-chip${mine ? ' chat-reaction-chip--mine' : ''}${bumped.has(emoji) ? ' chat-reaction-chip--bump' : ''}`}\n aria-pressed={!!mine}\n aria-label={`${emoji} ${count} ${count === 1 ? 'reacción' : 'reacciones'}${mine ? ', incluida la tuya. Pulsa para quitarla' : '. Pulsa para reaccionar'}`}\n title={titleFor(userIds) || undefined}\n disabled={disabled}\n onClick={() => onToggle?.(emoji)}\n ><span className=\"chat-reaction-chip__emoji\"><MessageText text={emoji} /></span><span className=\"chat-reaction-chip__count\">{count}</span></button>)}\n </div>;\n}\n\nexport default memo(ReactionBar);\n","/* eslint-disable react/prop-types */\nimport { useRef, useState } from 'react';\nimport { Copy, Check, Reply, SmilePlus, Pencil } from 'lucide-react';\nimport { decodeEffect, effectMessageText } from '../../effects/protocol.js';\nimport { EffectCard } from '../../effects/ChatEffects.jsx';\nimport MessageText from './MessageText';\nimport MediaPreview from './MediaPreview';\nimport YouTubePreview from './YouTubePreview.jsx';\nimport ReactionPicker from './ReactionPicker';\nimport ReactionBar from './ReactionBar';\nimport { isStickerAttachment } from '../../core/extras/messageExtras';\nexport default function MessageBubble({ message, isMine, senderName, timestamp, onCopy, onReply, onJumpQuote, onReact, onEdit, isEditing }) {\n const [quoteUnavailable, setQuoteUnavailable] = useState(false);\n const [copyState, setCopyState] = useState('');\n const [pickerOpen, setPickerOpen] = useState(false);\n const reactBtnRef = useRef(null);\n const text = message.message ?? message.text ?? '';\n const quote = /^> ([^\\n]{1,240})\\n\\n/.exec(text);\n const body = quote ? text.slice(quote[0].length) : text;\n const effect = decodeEffect(body);\n const attachments = Array.isArray(message.attachments) ? message.attachments : message.attachment ? [message.attachment] : [];\n const date = timestamp == null ? null : new Date(timestamp);\n const validDate = date && Number.isFinite(date.getTime());\n const isSticker = !text.trim() && attachments.length > 0 && attachments.every(isStickerAttachment);\n const hasReactions = Boolean(message.reactionGroups?.length);\n const closePicker = () => { setPickerOpen(false); reactBtnRef.current?.focus(); };\n const bubbleClass = ['message-bubble', isMine ? 'message-bubble--mine' : 'message-bubble--other', attachments.length && 'message-bubble--media', !text && attachments.length && 'message-bubble--media-only', isEditing && 'message-bubble--editing', isSticker && 'message-bubble--sticker', hasReactions && 'message-bubble--has-reactions', pickerOpen && 'message-bubble--picker-open'].filter(Boolean).join(' ');\n return <div className={`message-row ${isMine ? 'message-row--mine' : ''}`}>\n {!isMine && senderName && <span className=\"message-avatar\" aria-hidden=\"true\">{senderName.charAt(0).toUpperCase()}</span>}\n <div className={bubbleClass}>\n {!isMine && senderName && <div className=\"message-sender\">{senderName}</div>}\n {quote && <blockquote className=\"chat-message-quote\" aria-label=\"Cita de texto\"><button type=\"button\" className=\"chat-quote-link\" title=\"Buscar cita de texto en los mensajes disponibles\" onClick={() => setQuoteUnavailable(!onJumpQuote?.(quote[1]))}><MessageText text={quote[1]} /></button>{quoteUnavailable && <small role=\"status\">Original no disponible o cita ambigua</small>}</blockquote>}\n {effect ? <EffectCard effect={effect} /> : body && <div className=\"message-content\"><MessageText text={body} /></div>}\n {!effect && <YouTubePreview text={body} />}\n <MediaPreview items={attachments} history />\n <ReactionBar reactions={message.reactionGroups} onToggle={(emoji) => onReact?.(message, emoji)} disabled={!onReact} />\n {message.localOnly && <small className=\"message-meta\">Solo en este dispositivo · pendiente de envío</small>}\n <div className=\"message-actions\">\n {onReact && <button ref={reactBtnRef} type=\"button\" className=\"message-action-btn\" aria-label=\"Reaccionar al mensaje\" title=\"Reaccionar\" aria-haspopup=\"dialog\" aria-expanded={pickerOpen} onClick={() => setPickerOpen((v) => !v)}><SmilePlus size={14} /></button>}\n {onEdit && !effect && <button type=\"button\" className=\"message-action-btn\" aria-label=\"Editar mensaje\" title=\"Editar (↑)\" onClick={() => onEdit()}><Pencil size={13} /></button>}\n {onReply && <button type=\"button\" className=\"message-action-btn\" aria-label=\"Responder al mensaje\" title=\"Responder\" onClick={() => onReply(message)}><Reply size={14} /></button>}\n {text && <button type=\"button\" className=\"message-action-btn\" aria-label={copyState === 'ok' ? 'Mensaje copiado' : 'Copiar mensaje'} title={copyState === 'ok' ? 'Copiado' : 'Copiar mensaje'} onClick={async () => {\n try {\n if (onCopy) await onCopy(effectMessageText(text));\n else await navigator.clipboard.writeText(effectMessageText(text));\n setCopyState('ok');\n } catch { setCopyState('error'); }\n }}>{copyState === 'ok' ? <Check size={13} /> : <Copy size={13} />}</button>}\n </div>\n {pickerOpen && onReact && <div className=\"message-reaction-popover\"><ReactionPicker align={isMine ? 'end' : 'start'} onClose={closePicker} onSelect={(emoji) => { onReact(message, emoji); closePicker(); }} /></div>}\n <div className=\"message-footer\">\n {validDate && <time className=\"message-meta\" dateTime={date.toISOString()} title={`${date.toLocaleString()}${isMine && !message.localOnly ? ' · Aceptado por el servidor' : ''}`}>{date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</time>}\n {message.edited && <span className=\"message-edited\" title={message.editedAt ? `Editado ${new Date(message.editedAt).toLocaleString()}` : 'Editado'}>editado</span>}\n {copyState && <span className=\"message-copy-status\" role=\"status\">{copyState === 'ok' ? 'Copiado' : 'No se pudo copiar'}</span>}\n </div>\n </div>\n </div>;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n// UI-only state of the persistent game panel, keyed by game key.\nexport function createGamePanelStore() {\n return createStore((set) => ({\n panels: {},\n setMinimized: (key, minimized) => set((state) => ({ panels: { ...state.panels, [key]: { ...state.panels[key], minimized: Boolean(minimized) } } })),\n dismiss: (key) => set((state) => ({ panels: { ...state.panels, [key]: { ...state.panels[key], minimized: false, dismissed: true } } })),\n reset: () => set({ panels: {} }),\n }));\n}\n\n// Backward-compatible singleton: hook plus getState/setState/subscribe.\nexport const gamePanelStore = createGamePanelStore();\nexport const useGamePanelStore = (selector) => useStore(gamePanelStore, selector);\nObject.assign(useGamePanelStore, {\n getState: gamePanelStore.getState,\n setState: gamePanelStore.setState,\n subscribe: gamePanelStore.subscribe,\n});\n\nexport default useGamePanelStore;\n","/* eslint-disable react/prop-types */\nimport { memo } from 'react';\nimport { ArrowDown, ChevronDown, X } from 'lucide-react';\nimport { getGameStatus, isTerminalGame, sameUser } from '../shared/gameStatus';\nimport './games.css';\n\nfunction SyncControls({ sync, connected, onResync, onAdoptOffer }) {\n if (sync?.status === 'requesting') return <div className=\"chat-game-sync\" role=\"status\">Sincronizando partida…</div>;\n return <div className=\"chat-game-sync\" role=\"alert\">\n {sync?.message && <span>{sync.message}</span>}\n {sync?.status === 'incompatible' && sync.offer && onAdoptOffer && <button type=\"button\" className=\"chat-game-action chat-game-action--primary\" disabled={!connected} onClick={onAdoptOffer}>Usar estado del anfitrión</button>}\n {onResync && <button type=\"button\" className=\"chat-game-action\" disabled={!connected} onClick={onResync}>Reintentar sincronización</button>}\n </div>;\n}\n\nfunction GameCard({ game, currentUserId, onAccept, onDecline, onMove, onClose, onRetry, onDropSettled, onMinimize, onDismiss, onResync, onAdoptOffer, soundControls, variant, connected = true }) {\n const isHost = sameUser(currentUserId, game.hostId);\n const isGuest = sameUser(currentUserId, game.guestId);\n const isParticipant = isHost || isGuest;\n const myTurn = game.status === 'active' && sameUser(currentUserId, game.turnId);\n const controlsDisabled = !connected || game.pending || Boolean(game.pendingEvent);\n const canMove = myTurn && !controlsDisabled && !game.error;\n const terminal = isTerminalGame(game);\n const board = game.board || Array.from({ length: 6 }, () => Array(7).fill(null));\n const status = getGameStatus(game, currentUserId);\n\n return (\n <section className={`chat-game-card${myTurn ? ' chat-game-card--my-turn' : ''}${variant ? ` chat-game-card--${variant}` : ''}`} aria-label=\"Partida de Conecta 4\">\n <header className=\"chat-game-header\">\n <div className=\"chat-game-heading\">\n <span className=\"chat-game-eyebrow\">MINIJUEGOS · 2 JUGADORES</span>\n <h3>Conecta 4 <span aria-hidden=\"true\">●●●●</span></h3>\n </div>\n {soundControls}\n {onMinimize && <button className=\"chat-game-close\" type=\"button\" aria-label=\"Minimizar tablero\" title=\"Minimizar tablero\" onClick={onMinimize}><ChevronDown size={16} aria-hidden=\"true\" /></button>}\n {isParticipant && !terminal && (\n <button className=\"chat-game-close\" type=\"button\" aria-label=\"Finalizar partida para ambos jugadores\" title=\"Finalizar partida para ambos\" onClick={onClose} disabled={!connected}><X size={16} aria-hidden=\"true\" /></button>\n )}\n {onDismiss && <button className=\"chat-game-close\" type=\"button\" aria-label=\"Cerrar tablero y volver al chat\" title=\"Cerrar tablero\" onClick={onDismiss}><X size={16} aria-hidden=\"true\" /></button>}\n </header>\n <p className=\"chat-game-status\" role=\"status\">{!connected && !terminal ? 'Sin conexión · esperando reconexión' : game.pending ? 'Sincronizando…' : status}</p>\n <div className=\"chat-game-players\" aria-label=\"Colores de los jugadores\">\n <span><i className=\"chat-game-dot chat-game-dot--host\" />{isHost ? 'Tú' : 'Rival'}<small>Azul</small></span>\n <span><i className=\"chat-game-dot chat-game-dot--guest\" />{isGuest ? 'Tú' : 'Rival'}<small>Violeta</small></span>\n </div>\n <div className=\"chat-game-board-wrap\">\n <div className=\"chat-game-columns\" aria-label=\"Selecciona una columna\">\n {Array.from({ length: 7 }, (_, column) => (\n <button type=\"button\" key={column} aria-label={`Lanzar ficha en columna ${column + 1}`} disabled={!canMove || board[0][column] != null} onClick={() => onMove?.(column)}><ArrowDown size={16} strokeWidth={2} aria-hidden=\"true\" /><span className=\"chat-game-column-number\">{column + 1}</span></button>\n ))}\n </div>\n <div className=\"chat-game-board\" role=\"img\" aria-label={`Tablero de Conecta 4, ${game.ply || 0} fichas colocadas. ${status}. ${board.map((row, index) => `Fila ${index + 1} de arriba abajo: ${row.map(cell => cell == null ? 'vacía' : sameUser(cell, game.hostId) ? 'azul' : 'violeta').join(', ')}`).join('. ')}`}>\n {board.flatMap((row, rowIndex) => row.map((cell, column) => {\n const occupied = cell != null;\n const owner = occupied ? (sameUser(cell, game.hostId) ? 'host' : 'guest') : '';\n const latest = game.lastMove?.row === rowIndex && game.lastMove?.column === column;\n const winning = game.winningCells?.some(([row, col]) => row === rowIndex && col === column);\n return <div className={`chat-game-cell${winning ? ' chat-game-cell--winning' : ''}`} key={`${rowIndex}-${column}`}>\n {occupied && <span key={latest ? game.lastMove.eventId : 'settled'} className={`chat-game-piece chat-game-piece--${owner}${latest ? ' chat-game-piece--new' : ''}`} style={latest ? { '--game-drop-distance': `${-(rowIndex + 1) * 105}%` } : undefined}\n onAnimationEnd={latest ? () => onDropSettled?.(game.lastMove.eventId) : undefined} />}\n </div>;\n }))}\n </div>\n </div>\n {game.status === 'invited' && isGuest && <div className=\"chat-game-actions\">\n <button type=\"button\" className=\"chat-game-action chat-game-action--primary\" disabled={controlsDisabled} onClick={onAccept}>Aceptar partida</button>\n <button type=\"button\" className=\"chat-game-action\" disabled={controlsDisabled} onClick={onDecline}>Rechazar</button>\n </div>}\n {game.status === 'conflict' && isParticipant && <SyncControls sync={game.sync} connected={connected} onResync={onResync} onAdoptOffer={onAdoptOffer} />}\n {game.error && <div className=\"chat-game-error\" role=\"alert\"><span>{game.error}</span>{onRetry && <button type=\"button\" className=\"chat-game-action\" disabled={!connected || game.pending} onClick={onRetry}>Reintentar</button>}</div>}\n <footer className=\"chat-game-footer\">{terminal ? 'Puedes seguir conversando o invitar a otra partida.' : 'Conecta cuatro fichas. El chat sigue disponible.'}</footer>\n </section>\n );\n}\n\nexport default memo(GameCard);\n","/* eslint-disable react/prop-types */\nimport { Component, lazy, memo, Suspense, useEffect } from 'react';\nimport { useChatConnectionStatus } from '../../core/connection/connectionStore';\nimport useChatGames from './useChatGames';\nimport GameCard from '../connect4/GameCard';\nimport GameSoundControls from './GameSoundControls';\nimport { connect4Sounds, settleConnect4Drop } from '../connect4/connect4Sounds';\nimport { isBattleshipGame, isTanksGame } from './gameStatus';\n\n// Lazy game cards (and three.js behind them) stay out of the main bundle.\n// React caches a rejected lazy(); a retry needs a fresh one to actually reload the chunk.\nconst LAZY_CARDS = {\n racing_live: { title: 'Carreras LIVE 🏎️', load: () => lazy(() => import('../racing-live/RacingLiveGameCard.jsx')) },\n battleship: { title: 'Batalla Naval', load: () => lazy(() => import('../battleship/BattleshipGameCard')) },\n tanks_live: { title: 'Tanques LIVE 3D', load: () => lazy(() => import('../tanks-live/TanksLiveGameCard.jsx')) },\n tanks: { title: 'Tanques de guerra', load: () => lazy(() => import('../tanks/TanksGameCard.jsx')) },\n};\nconst lazyCards = {};\nconst lazyCard = (type) => { lazyCards[type] ??= LAZY_CARDS[type].load(); return lazyCards[type]; };\n\nfunction LazyCardFallback({ title }) {\n return <section className=\"chat-game-card\" aria-busy=\"true\" aria-label={`Partida de ${title}`}>\n <p className=\"chat-game-status\" role=\"status\">Cargando {title}…</p>\n </section>;\n}\n\n// Keeps a failed game chunk load from reaching the global ErrorBoundary.\nclass LazyCardErrorBoundary extends Component {\n state = { failed: false };\n\n static getDerivedStateFromError() { return { failed: true }; }\n\n render() {\n if (!this.state.failed) return this.props.children;\n const { type } = this.props;\n return <section className=\"chat-game-card\" aria-label={`Partida de ${LAZY_CARDS[type].title}`}>\n <p className=\"chat-game-status\" role=\"alert\">No se pudo cargar {LAZY_CARDS[type].title}.</p>\n <button type=\"button\" className=\"chat-btn\" onClick={() => { lazyCards[type] = LAZY_CARDS[type].load(); this.setState({ failed: false }); }}>Reintentar</button>\n </section>;\n }\n}\n\nfunction ConnectedGameCard({ gameKey, currentUserId, variant = 'panel', onMinimize, onDismiss, suspended = false }) {\n const game = useChatGames((state) => state.games[gameKey]);\n const connected = useChatConnectionStatus() === 'connected';\n const type = game?.game === 'racing_live' ? 'racing_live' : game?.game === 'tanks_live' ? 'tanks_live' : isBattleshipGame(game) ? 'battleship' : isTanksGame(game) ? 'tanks' : game ? 'connect4' : null;\n useEffect(() => { if (type === 'connect4') connect4Sounds.preload(); }, [type]);\n if (!game) return null;\n if (type !== 'connect4') {\n const Card = lazyCard(type);\n return <LazyCardErrorBoundary key={type} type={type}>\n <Suspense fallback={<LazyCardFallback title={LAZY_CARDS[type].title} />}>\n <Card suspended={suspended} gameKey={gameKey} currentUserId={currentUserId} variant={variant} onMinimize={onMinimize} onDismiss={onDismiss} />\n </Suspense>\n </LazyCardErrorBoundary>;\n }\n // The store owns delivery errors; handlers must not leak rejected promises.\n const act = (type, data) => { void useChatGames.getState().act(gameKey, type, data).catch(() => {}); };\n const run = (name) => () => { void Promise.resolve(useChatGames.getState()[name]?.(gameKey)).catch(() => {}); };\n return <GameCard game={game} currentUserId={currentUserId} connected={connected}\n onAccept={() => act('game_accept')} onDecline={() => act('game_decline')}\n onMove={(column) => act('game_move', { column })} onClose={() => act('game_end')}\n onDropSettled={settleConnect4Drop} variant={variant} onMinimize={onMinimize} onDismiss={onDismiss}\n soundControls={variant === 'panel' ? <GameSoundControls manager={connect4Sounds} /> : undefined}\n onResync={run('requestResync')} onAdoptOffer={run('adoptResyncOffer')}\n onRetry={game.pendingEvent ? () => { void useChatGames.getState().retry(gameKey).catch(() => {}); } : undefined} />;\n}\n\nexport default memo(ConnectedGameCard);\n","/* eslint-disable react/prop-types */\nimport { Gamepad2 } from 'lucide-react';\nimport useChatGames from './useChatGames';\nimport useGamePanelStore from './useGamePanelStore';\nimport ConnectedGameCard from './ConnectedGameCard';\nimport { getGameTitle, getShortGameStatus } from './gameStatus';\n\n// The panel owns the interactive board; the timeline only links to it.\nexport default function GameTimelineEntry({ gameKey, currentUserId, inPanel }) {\n const game = useChatGames((state) => state.games[gameKey]);\n if (!game) return null;\n if (!inPanel) return <ConnectedGameCard gameKey={gameKey} currentUserId={currentUserId} variant=\"history\" />;\n return (\n <button type=\"button\" className=\"chat-game-placeholder\" onClick={() => useGamePanelStore.getState().setMinimized(gameKey, false)}>\n <Gamepad2 size={15} aria-hidden=\"true\" />\n <span>Partida de {getGameTitle(game)} · {getShortGameStatus(game, currentUserId)}</span>\n <strong>Ver tablero</strong>\n </button>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState } from 'react';\nimport dayjs from 'dayjs';\nimport { effectMessageText } from '../../effects/protocol.js';\nimport MessageBubble from './MessageBubble';\nimport GameTimelineEntry from '../../games/shared/GameTimelineEntry';\nimport { messageId } from '../../core/extras/messageExtras';\nimport { MessageCircle, Paperclip, Mic, Sparkles, ArrowDown } from 'lucide-react';\n\nconst validTime = (value) => value != null && value !== '' && dayjs(value).isValid();\nexport default function MessageList({ messages = [], currentUserId, onCopy, onReply, panelGameKey, onReact, onEditMessage, editingId }) {\n const scrollRef = useRef(null);\n const nearBottom = useRef(true);\n const [hasNew, setHasNew] = useState(false);\n const scrollToBottom = () => { const node = scrollRef.current; if (node) node.scrollTop = node.scrollHeight; nearBottom.current = true; setHasNew(false); };\n const prevLength = useRef(messages.length);\n useEffect(() => {\n const node = scrollRef.current;\n // Only growth counts as \"new\"; reactions/edits on old messages must not flag it.\n const grew = messages.length > prevLength.current; prevLength.current = messages.length;\n if (node && nearBottom.current) node.scrollTop = node.scrollHeight;\n else if (node && grew) setHasNew(true);\n }, [messages]);\n useEffect(() => {\n if (editingId == null) return;\n const id = String(editingId);\n const node = scrollRef.current?.querySelector(`[data-chat-message-id=\"${typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(id) : id.replace(/[\"\\\\]/g, '\\\\$&')}\"]`);\n node?.scrollIntoView({ block: 'nearest', behavior: 'auto' });\n }, [editingId]);\n // Keep the latest messages in view when the game panel opens or grows.\n useEffect(() => {\n const node = scrollRef.current;\n if (!node || typeof ResizeObserver === 'undefined') return undefined;\n const observer = new ResizeObserver(() => { if (nearBottom.current) node.scrollTop = node.scrollHeight; });\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n const keys = new Map();\n return <div className=\"chat-messages-area\">\n <div className=\"chat-messages\" ref={scrollRef} role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\" aria-label=\"Mensajes\" onLoadCapture={() => { const node = scrollRef.current; if (node && nearBottom.current) node.scrollTop = node.scrollHeight; }} onScroll={() => { const node = scrollRef.current; nearBottom.current = node.scrollHeight - node.scrollTop - node.clientHeight < 80; if (nearBottom.current) setHasNew(false); }}>\n {!messages.length && <div className=\"chat-conversation-welcome\"><div className=\"chat-welcome-icon\"><MessageCircle size={30} /></div><span className=\"chat-eyebrow\">ESTE ES TU ESPACIO</span><h3>Una buena conversación empieza aquí</h3><p>Comparte una idea, suelta un archivo o dale voz a tu mensaje.</p><div className=\"chat-welcome-features\"><span><Paperclip size={14} /> Archivos y media</span><span><Mic size={14} /> Notas de voz</span><span><Sparkles size={14} /> GIFs y emojis</span></div></div>}\n {messages.map((msg, index) => {\n const previous = messages[index - 1];\n const timed = validTime(msg.timestamp);\n const previousTimed = previous && validTime(previous.timestamp);\n const sameDay = timed && previousTimed && dayjs(msg.timestamp).isSame(dayjs(previous.timestamp), 'day');\n const gap = sameDay ? dayjs(msg.timestamp).diff(dayjs(previous.timestamp), 'minute', true) : Infinity;\n const grouped = previous && previous.user_id != null && msg.user_id != null && String(previous.user_id) === String(msg.user_id) && !previous.gameKey && !msg.gameKey && sameDay && gap >= 0 && gap <= 5;\n const base = String(msg.id ?? msg.message_id ?? `${msg.room_id}:${msg.user_id}:${msg.timestamp ?? ''}:${msg.message ?? ''}`);\n const occurrence = keys.get(base) || 0;\n keys.set(base, occurrence + 1);\n const id = messageId(msg);\n const isMine = Boolean(msg.localOnly) || (msg.user_id != null && currentUserId != null && String(msg.user_id) === String(currentUserId));\n const body = msg.message ?? msg.text;\n return <div key={`${base}:${occurrence}`} data-chat-message-index={index} data-chat-message-id={id ?? undefined} tabIndex={-1} className={`message-group ${grouped ? 'message-group--continued' : ''}`}>\n {timed && !sameDay && <div className=\"message-date-divider\"><span>{dayjs(msg.timestamp).format('DD MMM YYYY')}</span></div>}\n {msg.gameKey ? <GameTimelineEntry gameKey={msg.gameKey} currentUserId={currentUserId} inPanel={String(msg.gameKey) === String(panelGameKey)} /> : <MessageBubble message={msg} isMine={isMine} onReact={msg.localOnly || !id ? undefined : onReact} onEdit={isMine && !msg.localOnly && id && typeof body === 'string' && body.trim() && onEditMessage ? () => onEditMessage(msg) : undefined} isEditing={editingId != null && id === String(editingId)} senderName={!grouped ? msg.username : undefined} timestamp={timed ? msg.timestamp : undefined} onCopy={onCopy} onReply={onReply} onJumpQuote={(quote) => {\n const matches = messages.map((item, i) => ({ item, i })).filter(({ item }) => `${String(item.username || 'Usuario').replace(/[\\r\\n]/g, ' ').slice(0, 50)}: ${String(effectMessageText(item.message || item.text || '[Archivo adjunto]')).replace(/\\s+/g, ' ').slice(0, 180)}` === quote);\n if (matches.length !== 1) return false;\n const node = scrollRef.current?.querySelector(`[data-chat-message-index=\"${matches[0].i}\"]`);\n node?.scrollIntoView({ block: 'center', behavior: 'auto' }); node?.focus({ preventScroll: true });\n return Boolean(node);\n }} />}\n </div>;\n })}\n </div>\n {hasNew && <button type=\"button\" className=\"chat-new-messages\" onClick={scrollToBottom}>Ver mensajes nuevos <ArrowDown size={14} aria-hidden=\"true\" style={{ verticalAlign: 'middle' }} /></button>}\n </div>;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nconst LIMIT_SECONDS = 120;\n\nexport default function useVoiceRecorder(onRecorded) {\n const [status, setStatus] = useState('idle');\n const [seconds, setSeconds] = useState(0);\n const [error, setError] = useState('');\n const sessionRef = useRef(null);\n const mountedRef = useRef(true);\n const callbackRef = useRef(onRecorded);\n callbackRef.current = onRecorded;\n\n const release = useCallback((session) => {\n clearInterval(session?.timer);\n session?.stream?.getTracks().forEach((track) => track.stop());\n }, []);\n\n const finish = useCallback((cancelled = false) => {\n const session = sessionRef.current;\n if (!session) return;\n session.cancelled = cancelled;\n clearInterval(session.timer);\n if (session.recorder?.state === 'recording') {\n session.recorder.stop();\n release(session);\n } else {\n release(session);\n sessionRef.current = null;\n if (mountedRef.current) setStatus('idle');\n }\n }, [release]);\n\n const start = useCallback(async () => {\n if (sessionRef.current) return;\n setError('');\n if (!navigator.mediaDevices?.getUserMedia || typeof MediaRecorder === 'undefined') {\n setError('Este navegador no permite grabar audio. Puedes adjuntar un archivo de audio.');\n return;\n }\n const session = { cancelled: false, chunks: [], stream: null, recorder: null, timer: null };\n sessionRef.current = session;\n setStatus('requesting');\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n session.stream = stream;\n if (!mountedRef.current || session.cancelled || sessionRef.current !== session) {\n release(session);\n return;\n }\n const mimeType = ['audio/webm;codecs=opus', 'audio/ogg;codecs=opus', 'audio/mp4'].find((type) => MediaRecorder.isTypeSupported(type));\n const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);\n session.recorder = recorder;\n recorder.ondataavailable = (event) => { if (event.data.size) session.chunks.push(event.data); };\n recorder.onstop = () => {\n release(session);\n const isCurrent = sessionRef.current === session;\n if (isCurrent) sessionRef.current = null;\n if (!mountedRef.current || (!isCurrent && sessionRef.current)) return;\n setStatus('idle');\n if (session.cancelled) return;\n const type = recorder.mimeType || session.chunks[0]?.type || 'audio/webm';\n const blob = new Blob(session.chunks, { type });\n if (!blob.size) { setError('La grabación está vacía. Inténtalo de nuevo.'); return; }\n const extension = type.includes('mp4') ? 'm4a' : type.includes('ogg') ? 'ogg' : 'webm';\n callbackRef.current?.(new File([blob], `Nota de voz ${Date.now()}.${extension}`, { type }));\n };\n recorder.onerror = () => {\n session.cancelled = true;\n release(session);\n if (sessionRef.current === session) sessionRef.current = null;\n if (mountedRef.current) { setStatus('idle'); setError('No se pudo completar la grabación.'); }\n };\n recorder.start(250);\n session.startedAt = Date.now();\n setSeconds(0);\n setStatus('recording');\n session.timer = setInterval(() => {\n const elapsed = Math.floor((Date.now() - session.startedAt) / 1000);\n if (mountedRef.current) setSeconds(Math.min(elapsed, LIMIT_SECONDS));\n if (elapsed >= LIMIT_SECONDS) finish();\n }, 250);\n } catch (failure) {\n release(session);\n if (sessionRef.current === session) sessionRef.current = null;\n if (!mountedRef.current || session.cancelled) return;\n setStatus('idle');\n setError(failure.name === 'NotAllowedError' ? 'Permite el acceso al micrófono para grabar una nota de voz.' : 'No se pudo acceder al micrófono. Comprueba que esté disponible.');\n }\n }, [finish, release]);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n finish(true);\n };\n }, [finish]);\n\n return { status, seconds, error, start, stop: () => finish(), cancel: () => finish(true) };\n}\n","/**\n * GIF query expansion for Spanish / LatAm (Dominican) chat users.\n * Pure module: no React, no DOM, no network.\n *\n * expandGifQuery(\"cuánta bendición\") →\n * variants: original + alternative searches (es/en) to fan out against KLIPY,\n * intentTerms: words expected in good results' title/tags (re-ranking boost),\n * avoidTerms: generic noise (sports) to demote unless the query asks for it.\n */\n\nconst MAX_VARIANTS = 4;\n\nconst STOPWORDS = new Set([\n 'el', 'la', 'los', 'las', 'lo', 'un', 'una', 'unos', 'unas', 'de', 'del', 'al',\n 'y', 'e', 'o', 'u', 'a', 'en', 'con', 'por', 'para', 'mi', 'mis', 'su', 'sus',\n 'the', 'an', 'of', 'to', 'and', 'or', 'in', 'on', 'for', 'my', 'is',\n]);\n\nconst SPORTS_TERMS = new Set([\n 'futbol', 'soccer', 'football', 'gol', 'golazo', 'goal', 'messi', 'ronaldo', 'cr7',\n 'nba', 'nfl', 'mlb', 'fifa', 'mundial', 'beisbol', 'baseball', 'pelota', 'basket',\n 'baloncesto', 'basketball', 'lebron', 'deporte', 'deportes', 'sports', 'partido',\n 'jugador', 'player', 'licey', 'aguilas', 'escogido', 'champions', 'liga',\n]);\n\nconst AVOID_TERMS = [\n 'football', 'soccer', 'futbol', 'nba', 'nfl', 'mlb', 'goal', 'fifa', 'player',\n 'sports', 'basketball', 'match', 'team', 'jersey',\n];\n\n/**\n * Phrase / expression lexicon. `k` = trigger keys (normalized), `q` = alternative\n * queries in priority order (\"en:\" prefix → English), `i` = intent terms,\n * `re` = optional regex over the normalized text, `sports` = sports intent.\n */\nconst PHRASE_RULES = [\n { k: ['cuanta bendicion', 'cuanta bendicion meme'], q: ['cuanta bendicion meme', 'en:blessed meme', 'en:so blessed arms open'], i: ['cuanta bendicion', 'bendicion', 'blessed', 'bless', 'grateful', 'meme'] },\n { k: ['que bendicion', 'bendicion', 'bendiciones', 'bendecido', 'bendecida', 'blessed'], q: ['que bendicion', 'en:blessed happy', 'en:thank god happy'], i: ['bendicion', 'blessed', 'grateful', 'thank god', 'happy'] },\n { k: ['vida', 'asi es la vida', 'la vida'], q: ['vida meme', 'en:life meme', 'asi es la vida'], i: ['vida', 'life', 'asi es la vida', 'meme'] },\n { k: ['excelente', 'excellent'], q: ['en:excellent mr burns', 'en:mr burns excellent', 'excelente'], i: ['excellent', 'excelente', 'burns', 'mr burns', 'simpsons'] },\n { k: ['senor burns', 'sr burns', 'mr burns', 'montgomery', 'montgomery burns'], q: ['en:mr burns', 'en:montgomery burns', 'en:simpsons burns'], i: ['burns', 'mr burns', 'montgomery', 'simpsons'] },\n { k: ['no puede ser', 'no lo puedo creer', 'no me digas'], q: ['no puede ser', 'en:shocked reaction', 'en:surprised omg'], i: ['shocked', 'surprised', 'omg', 'no puede ser', 'wow'] },\n { k: ['diablo', 'diablo loco', 'diache', 'diantre'], q: ['diablo meme dominicano', 'en:dominican meme', 'diablo meme'], i: ['diablo', 'dominicano', 'dominican', 'meme', 'republica dominicana'] },\n { k: ['ya tu sabes', 'ya tu sabe', 'ya tu sabe lo que hay', 'pa que tu lo sepa'], q: ['ya tu sabes', 'en:you know meme', 'en:latino meme'], i: ['ya tu sabes', 'you know', 'wink', 'latino', 'meme'] },\n { k: ['jaja', 'jeje', 'jiji', 'jsjs', 'lol', 'lmao', 'xd'], re: /^(?:[jh][aeiou]){2,}[jh]?$|^(?:js)+j?$/, q: ['jajaja', 'en:laughing', 'en:lol funny'], i: ['laugh', 'laughing', 'lol', 'funny', 'jaja', 'risa'] },\n { k: ['que risa', 'me muero de risa', 'muerto de risa', 'me parto', 'risa'], q: ['que risa', 'en:laughing hard', 'en:dying laughing'], i: ['laugh', 'laughing', 'funny', 'risa', 'lol'] },\n { k: ['ay no', 'ay dios', 'ay dios mio', 'dios mio', 'oh no'], q: ['ay no', 'en:oh no', 'en:oh my god'], i: ['oh no', 'omg', 'ay no', 'dios mio', 'worried'] },\n { k: ['que pena', 'que verguenza', 'verguenza', 'cringe'], q: ['que pena', 'en:embarrassed', 'en:awkward cringe'], i: ['embarrassed', 'awkward', 'cringe', 'pena', 'verguenza'] },\n { k: ['tranquilo', 'tranquila', 'tranqui', 'calma', 'relax', 'calmate'], q: ['tranquilo', 'en:calm down', 'en:relax chill'], i: ['calm', 'relax', 'chill', 'tranquilo'] },\n { k: ['dale', 'dale pues', 'dale ahi'], q: ['dale', 'en:lets go', 'en:ok deal'], i: ['dale', 'lets go', 'ok', 'deal'] },\n { k: ['klk', 'que lo que', 'q lo q', 'que lo ke', 'klk mi loco', 'que hay'], q: ['klk', 'que lo que dominicano', 'en:whats up'], i: ['klk', 'que lo que', 'whats up', 'sup', 'hey', 'dominicano'] },\n { k: ['vamo arriba', 'vamos arriba', 'pa arriba', 'vamos', 'vamo', 'lets go'], q: ['vamo arriba', 'en:lets go hype', 'en:lets go'], i: ['lets go', 'hype', 'vamos', 'arriba', 'motivation'] },\n { k: ['wepa', 'epa', 'yupi', 'yay', 'eso'], q: ['wepa', 'en:yay celebration', 'en:excited happy dance'], i: ['wepa', 'yay', 'celebrate', 'excited', 'happy'] },\n { k: ['uff', 'ouf', 'uy', 'fiu'], q: ['uff', 'en:phew relief', 'en:exhausted sigh'], i: ['phew', 'sigh', 'relief', 'uff'] },\n { k: ['mano', 'manito', 'pana', 'mi pana', 'hermano', 'bro', 'compai', 'socio'], q: ['pana meme', 'en:bro hug', 'en:best friends'], i: ['bro', 'friend', 'friends', 'pana', 'hermano', 'brother'] },\n { k: ['tigre', 'tiguere', 'tiguerazo', 'tiguerito'], q: ['tiguere dominicano', 'en:cool guy swag', 'en:smooth'], i: ['tiguere', 'tigre', 'swag', 'cool', 'smooth'] },\n { k: ['que chulo', 'chulo', 'chula', 'que lindo', 'que linda', 'lindo', 'linda', 'que bello', 'cute'], q: ['que lindo', 'en:cute', 'en:aww adorable'], i: ['cute', 'aww', 'adorable', 'lindo', 'chulo'] },\n { k: ['que vaina', 'vaina', 'que es la vaina', 'que cosa', 'que es eso'], q: ['que vaina', 'en:confused what', 'en:what reaction'], i: ['confused', 'what', 'que vaina', 'huh'] },\n { k: ['que loco', 'loco', 'loca', 'locura', 'crazy'], q: ['que loco', 'en:crazy', 'en:crazy reaction'], i: ['crazy', 'loco', 'insane'] },\n { k: ['aplausos', 'aplauso', 'bravo', 'clap'], q: ['aplausos', 'en:applause', 'en:clapping bravo'], i: ['applause', 'clapping', 'clap', 'bravo', 'aplausos'] },\n { k: ['felicidades', 'felicitaciones', 'enhorabuena', 'congrats'], q: ['felicidades', 'en:congratulations', 'en:congrats celebration'], i: ['congratulations', 'congrats', 'felicidades', 'celebrate'] },\n { k: ['gracias', 'muchas gracias', 'mil gracias', 'grax', 'thanks'], q: ['gracias', 'en:thank you', 'en:thanks grateful'], i: ['thank you', 'thanks', 'gracias', 'grateful'] },\n { k: ['buenos dias', 'buen dia', 'good morning'], q: ['buenos dias', 'en:good morning', 'en:good morning coffee'], i: ['good morning', 'buenos dias', 'morning'] },\n { k: ['buenas tardes'], q: ['buenas tardes', 'en:good afternoon'], i: ['good afternoon', 'buenas tardes'] },\n { k: ['buenas noches', 'dulces suenos', 'good night'], q: ['buenas noches', 'en:good night', 'en:sleepy good night'], i: ['good night', 'buenas noches', 'night', 'sleep'] },\n { k: ['feliz cumpleanos', 'feliz cumple', 'cumpleanos', 'cumple', 'happy birthday'], q: ['feliz cumpleanos', 'en:happy birthday', 'en:birthday cake party'], i: ['birthday', 'happy birthday', 'cumpleanos', 'cake', 'party'] },\n { k: ['te amo', 'te quiero', 'te adoro', 'amor', 'mi amor', 'i love you'], q: ['te amo', 'en:i love you', 'en:love hearts'], i: ['love', 'i love you', 'te amo', 'hearts', 'heart'] },\n { k: ['triste', 'tristeza', 'que triste', 'depre', 'sad'], q: ['triste', 'en:sad', 'en:sad crying'], i: ['sad', 'triste', 'crying', 'depressed'] },\n { k: ['llorando', 'llorar', 'lloro', 'a llorar'], q: ['llorando', 'en:crying', 'en:crying sobbing'], i: ['crying', 'cry', 'sobbing', 'tears', 'llorando'] },\n { k: ['enojado', 'enojada', 'molesto', 'molesta', 'enfadado', 'enfadada', 'furioso', 'furiosa', 'rabia', 'angry'], q: ['enojado', 'en:angry', 'en:mad furious'], i: ['angry', 'mad', 'furious', 'rage', 'enojado'] },\n { k: ['sorprendido', 'sorprendida', 'sorpresa', 'wow', 'guau', 'omg'], q: ['sorprendido', 'en:surprised', 'en:wow shocked'], i: ['surprised', 'wow', 'shocked', 'omg', 'sorpresa'] },\n { k: ['facepalm', 'que bruto', 'que bruta', 'que tonto', 'en serio', 'smh'], q: ['en:facepalm', 'en:smh', 'que bruto'], i: ['facepalm', 'smh', 'disappointed', 'really'] },\n { k: ['ok', 'okey', 'okay', 'vale', 'esta bien', 'de acuerdo', 'perfecto'], q: ['ok', 'en:okay thumbs up', 'en:ok approved'], i: ['ok', 'okay', 'thumbs up', 'approved', 'perfect'] },\n { k: ['si', 'claro', 'claro que si', 'obvio', 'por supuesto', 'yes'], q: ['si', 'en:yes', 'en:yes nodding'], i: ['yes', 'si', 'nodding', 'of course'] },\n { k: ['no', 'nop', 'nope', 'para nada', 'jamas', 'nunca'], q: ['no', 'en:no nope', 'en:no way'], i: ['no', 'nope', 'no way', 'never'] },\n { k: ['no se', 'ni idea', 'quien sabe'], q: ['no se', 'en:i dont know shrug', 'en:shrug'], i: ['shrug', 'i dont know', 'no se', 'idk'] },\n { k: ['adios', 'chao', 'chau', 'bye', 'nos vemos', 'hasta luego'], q: ['adios', 'en:bye bye', 'en:goodbye wave'], i: ['bye', 'goodbye', 'adios', 'wave'] },\n { k: ['hola', 'holi', 'saludos', 'hey', 'hello', 'hi'], q: ['hola', 'en:hello', 'en:hi wave'], i: ['hello', 'hi', 'hola', 'wave', 'hey'] },\n { k: ['fiesta', 'party', 'parranda', 'rumba', 'juidero', 'janguear'], q: ['fiesta', 'en:party', 'en:party celebration'], i: ['party', 'fiesta', 'celebration', 'celebrate'] },\n { k: ['bailar', 'baile', 'bailando', 'a bailar', 'dance'], q: ['bailando', 'en:dancing', 'en:dance party'], i: ['dance', 'dancing', 'baile', 'bailando'] },\n { k: ['bachata', 'merengue', 'dembow', 'salsa'], q: ['bachata merengue', 'en:dominican dance', 'en:latin dance'], i: ['bachata', 'merengue', 'dembow', 'latin', 'dance', 'dominican'] },\n { k: ['cansado', 'cansada', 'agotado', 'agotada', 'no puedo mas', 'tired'], q: ['cansado', 'en:tired', 'en:exhausted'], i: ['tired', 'exhausted', 'cansado', 'sleepy'] },\n { k: ['tengo sueno', 'sueno', 'dormir', 'a dormir', 'zzz', 'sleepy'], q: ['tengo sueno', 'en:sleepy', 'en:sleeping'], i: ['sleepy', 'sleep', 'sleeping', 'sueno', 'tired'] },\n { k: ['hambre', 'tengo hambre', 'a comer', 'comida', 'hungry'], q: ['tengo hambre', 'en:hungry', 'en:food eating'], i: ['hungry', 'food', 'eating', 'hambre', 'comida'] },\n { k: ['dinero', 'cuarto', 'cuartos', 'chavos', 'plata', 'pesos', 'quincena', 'pago', 'money'], q: ['dinero', 'en:money', 'en:money rain rich'], i: ['money', 'cash', 'rich', 'dinero', 'payday'] },\n { k: ['trabajo', 'trabajando', 'a trabajar', 'chamba', 'oficina', 'work'], q: ['trabajo', 'en:working', 'en:office work'], i: ['work', 'working', 'office', 'trabajo', 'job'] },\n { k: ['lunes', 'monday'], q: ['lunes', 'en:monday', 'en:monday mood'], i: ['monday', 'lunes', 'mood'] },\n { k: ['viernes', 'por fin viernes', 'al fin viernes', 'friday'], q: ['viernes', 'en:friday', 'en:its friday'], i: ['friday', 'viernes', 'weekend', 'tgif'] },\n { k: ['fin de semana', 'finde', 'weekend'], q: ['fin de semana', 'en:weekend', 'en:weekend vibes'], i: ['weekend', 'fin de semana', 'relax'] },\n { k: ['cafe', 'cafecito', 'un cafe', 'coffee'], q: ['cafe', 'en:coffee', 'en:coffee morning'], i: ['coffee', 'cafe', 'morning'] },\n { k: ['calor', 'que calor', 'hot'], q: ['que calor', 'en:hot sweating', 'en:so hot'], i: ['hot', 'heat', 'sweating', 'calor'] },\n { k: ['frio', 'que frio', 'cold'], q: ['que frio', 'en:cold freezing', 'en:so cold'], i: ['cold', 'freezing', 'frio'] },\n { k: ['pensando', 'hmm', 'mmm', 'dejame pensar', 'thinking'], q: ['pensando', 'en:thinking', 'en:hmm thinking'], i: ['thinking', 'hmm', 'think', 'pensando'] },\n { k: ['miedo', 'que miedo', 'susto', 'asustado', 'asustada', 'scared'], q: ['que miedo', 'en:scared', 'en:scared terrified'], i: ['scared', 'fear', 'terrified', 'miedo'] },\n { k: ['nervioso', 'nerviosa', 'nervios', 'nervous'], q: ['nervioso', 'en:nervous', 'en:nervous sweating'], i: ['nervous', 'anxious', 'nervioso'] },\n { k: ['aburrido', 'aburrida', 'que aburrido', 'bored'], q: ['aburrido', 'en:bored', 'en:so bored'], i: ['bored', 'boring', 'aburrido'] },\n { k: ['feliz', 'contento', 'contenta', 'alegre', 'happy'], q: ['feliz', 'en:happy', 'en:happy dance'], i: ['happy', 'joy', 'feliz', 'smile'] },\n { k: ['emocionado', 'emocionada', 'que emocion', 'excited'], q: ['emocionado', 'en:excited', 'en:so excited'], i: ['excited', 'hype', 'emocionado'] },\n { k: ['que bueno', 'buenisimo', 'genial', 'chevere', 'nitido', 'brutal', 'tremendo'], q: ['que bueno', 'en:great awesome', 'en:awesome thumbs up'], i: ['great', 'awesome', 'cool', 'genial', 'nice'] },\n { k: ['esperando', 'apurate', 'te espero', 'waiting'], q: ['esperando', 'en:waiting', 'en:hurry up waiting'], i: ['waiting', 'wait', 'hurry', 'esperando'] },\n { k: ['chisme', 'bochinche', 'cuentame', 'el chisme', 'tea'], q: ['chisme', 'en:gossip', 'en:sipping tea'], i: ['gossip', 'tea', 'chisme', 'bochinche', 'drama'] },\n { k: ['mentira', 'mentiroso', 'mentirosa', 'eso es mentira', 'liar'], q: ['mentira', 'en:liar', 'en:lie lying'], i: ['liar', 'lie', 'lying', 'mentira'] },\n { k: ['suerte', 'buena suerte', 'exito', 'exitos', 'good luck'], q: ['buena suerte', 'en:good luck', 'en:fingers crossed'], i: ['good luck', 'luck', 'suerte', 'fingers crossed'] },\n { k: ['lo siento', 'perdon', 'perdoname', 'disculpa', 'disculpame', 'sorry'], q: ['lo siento', 'en:sorry', 'en:sorry apology'], i: ['sorry', 'apology', 'perdon', 'lo siento'] },\n { k: ['besos', 'beso', 'muack', 'mua', 'kiss'], q: ['besos', 'en:kiss', 'en:kisses love'], i: ['kiss', 'kisses', 'beso', 'love'] },\n { k: ['abrazo', 'abrazos', 'hug'], q: ['abrazo', 'en:hug', 'en:big hug'], i: ['hug', 'hugs', 'abrazo'] },\n { k: ['callate', 'silencio', 'shh'], q: ['callate', 'en:shh quiet', 'en:shut up'], i: ['shh', 'quiet', 'silence', 'callate'] },\n { k: ['dominicano', 'dominicana', 'rd', 'republica dominicana', 'quisqueya', 'dominican'], q: ['dominicano meme', 'en:dominican republic', 'en:dominican flag'], i: ['dominicano', 'dominican', 'republica dominicana', 'rd', 'quisqueya'] },\n { k: ['gol', 'golazo', 'goal'], q: ['golazo', 'en:goal celebration', 'en:soccer goal'], i: ['goal', 'gol', 'golazo', 'soccer', 'futbol'], sports: true },\n];\n\n/** Word lexicon es→en used to build an English variant when no phrase rule matches. */\nconst WORDS = {\n triste: 'sad', feliz: 'happy', contento: 'happy', alegre: 'happy', enojado: 'angry', molesto: 'annoyed',\n furioso: 'furious', cansado: 'tired', aburrido: 'bored', asustado: 'scared', miedo: 'scared',\n sorprendido: 'surprised', confundido: 'confused', nervioso: 'nervous', celoso: 'jealous',\n orgulloso: 'proud', emocionado: 'excited', enamorado: 'in love', avergonzado: 'embarrassed',\n loco: 'crazy', gracioso: 'funny', chistoso: 'funny', lindo: 'cute', bonito: 'pretty', feo: 'ugly',\n bueno: 'good', malo: 'bad', mejor: 'best', peor: 'worst', rapido: 'fast', lento: 'slow',\n flojo: 'lazy', vago: 'lazy', rico: 'rich', pobre: 'broke', borracho: 'drunk', enfermo: 'sick',\n hambre: 'hungry', sueno: 'sleepy', calor: 'hot', frio: 'cold', amor: 'love', corazon: 'heart',\n beso: 'kiss', abrazo: 'hug', risa: 'laugh', llorar: 'cry', reir: 'laugh', gritar: 'scream',\n bailar: 'dance', baile: 'dance', cantar: 'sing', comer: 'eat', beber: 'drink', dormir: 'sleep',\n correr: 'run', esperar: 'wait', pensar: 'think', ganar: 'win', perder: 'lose', saludo: 'hello',\n perro: 'dog', gato: 'cat', pollo: 'chicken', mono: 'monkey', pajaro: 'bird', bebe: 'baby',\n nino: 'kid', mama: 'mom', papa: 'dad', abuela: 'grandma', amigo: 'friend', novio: 'boyfriend',\n novia: 'girlfriend', jefe: 'boss', escuela: 'school', examen: 'exam', tarea: 'homework',\n comida: 'food', cerveza: 'beer', vino: 'wine', agua: 'water', pizza: 'pizza', playa: 'beach',\n lluvia: 'rain', sol: 'sun', casa: 'home', carro: 'car', dinero: 'money', trabajo: 'work',\n fiesta: 'party', musica: 'music', navidad: 'christmas', verano: 'summer', invierno: 'winter',\n lunes: 'monday', viernes: 'friday', domingo: 'sunday', cafe: 'coffee', vida: 'life',\n bendicion: 'blessed', exito: 'success', sorpresa: 'surprise', regalo: 'gift', pastel: 'cake',\n bizcocho: 'cake', telefono: 'phone', mensaje: 'message', gracias: 'thank you', hola: 'hello',\n adios: 'bye', si: 'yes', no: 'no', fuego: 'fire', diablo: 'devil', angel: 'angel',\n};\n\nconst EN_WORDS = new Set(Object.values(WORDS).flatMap((v) => v.split(' ')).concat(\n ['meme', 'reaction', 'funny', 'lol', 'omg', 'wow', 'yes', 'ok', 'okay', 'what', 'why', 'love', 'you', 'i', 'me'],\n));\n\n/**\n * Lowercase, trim, strip accents/diacritics, emoji and punctuation, collapse spaces.\n * @param {string} text\n * @returns {string} e.g. \"¡Cuánta Bendición!\" → \"cuanta bendicion\"\n */\nexport function normalizeQuery(text) {\n return String(text ?? '')\n .toLowerCase()\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .replace(/[\\p{Extended_Pictographic}\\u{1F1E6}-\\u{1F1FF}\\u{1F3FB}-\\u{1F3FF}‍️⃣]/gu, ' ')\n .replace(/[^\\p{L}\\p{N}\\s]/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/**\n * Normalized tokens without (a small set of) stopwords. Falls back to all tokens\n * if everything was a stopword.\n * @param {string} text\n * @returns {string[]}\n */\nexport function tokenize(text) {\n const all = normalizeQuery(text).split(' ').filter(Boolean);\n const kept = all.filter((t) => !STOPWORDS.has(t));\n return kept.length ? kept : all;\n}\n\n/** Collapse repeated letters (\"ufff\" → \"uf\", \"siii\" → \"si\") for fuzzy matching. */\nconst squash = (s) => s.replace(/(.)\\1+/g, '$1');\n\n/** Levenshtein distance with early exit when it exceeds `max`. */\nfunction lev(a, b, max = 1) {\n if (Math.abs(a.length - b.length) > max) return max + 1;\n let prev = Array.from({ length: b.length + 1 }, (_, j) => j);\n for (let i = 1; i <= a.length; i++) {\n const cur = [i];\n let rowMin = i;\n for (let j = 1; j <= b.length; j++) {\n cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));\n rowMin = Math.min(rowMin, cur[j]);\n }\n if (rowMin > max) return max + 1;\n prev = cur;\n }\n return prev[b.length];\n}\n\nconst COMPILED_RULES = PHRASE_RULES.map((r) => ({ ...r, sk: r.k.map((k) => squash(normalizeQuery(k))) }));\n\n/**\n * Best phrase rule for a normalized query: exact > whole-word contains > typing prefix > 1-typo.\n * @returns {{ rule: object, exact: boolean } | null}\n */\nfunction findRule(normalized) {\n const s = squash(normalized);\n const padded = ` ${s} `;\n let best = null;\n let bestScore = 0;\n for (const rule of COMPILED_RULES) {\n if (rule.re?.test(normalized)) {\n if (1000 > bestScore) { best = rule; bestScore = 1000; }\n continue;\n }\n for (const k of rule.sk) {\n let score = 0;\n if (s === k) score = 1000 + k.length;\n else if ((k.length > 3 || k.includes(' ')) && padded.includes(` ${k} `)) score = 500 + k.length;\n else if (s.length >= 4 && k.startsWith(s)) score = 300 + s.length;\n else if (s.length >= 5 && k.length >= 5 && lev(s, k) <= 1) score = 200 + k.length;\n if (score > bestScore) { best = rule; bestScore = score; }\n }\n }\n return best ? { rule: best, exact: bestScore >= 1000 } : null;\n}\n\n/** Translate one token via WORDS, tolerating plural / feminine forms. */\nfunction translateWord(t) {\n if (WORDS[t]) return WORDS[t];\n const base = t.endsWith('es') ? t.slice(0, -2) : t.endsWith('s') ? t.slice(0, -1) : t;\n if (WORDS[base]) return WORDS[base];\n if (base.endsWith('a') && WORDS[`${base.slice(0, -1)}o`]) return WORDS[`${base.slice(0, -1)}o`];\n return null;\n}\n\nconst uniq = (arr) => [...new Set(arr.filter(Boolean))];\n\n/**\n * Expand a chat GIF query into weighted search variants + re-ranking hints.\n * @param {string} query\n * @returns {{\n * original: string, normalized: string,\n * variants: Array<{ q: string, weight: number, lang: 'es'|'en', reason: string }>,\n * intentTerms: string[], avoidTerms: string[], isPhrase: boolean\n * }}\n */\nexport function expandGifQuery(query) {\n const original = String(query ?? '').trim();\n const normalized = normalizeQuery(original);\n const tokens = tokenize(original);\n const empty = { original, normalized, variants: [], intentTerms: [], avoidTerms: [], isPhrase: false };\n if (!normalized) return empty;\n\n const isEnglish = tokens.every((t) => EN_WORDS.has(t));\n const translated = tokens.map(translateWord);\n const known = translated.filter(Boolean).length;\n const enPhrase = !isEnglish && known && known * 2 >= tokens.length\n ? tokens.map((t, idx) => translated[idx] || t).join(' ')\n : null;\n\n const variants = [];\n const seen = new Set();\n const push = (q, weight, lang, reason) => {\n const key = normalizeQuery(q);\n if (!key || seen.has(key) || variants.length >= MAX_VARIANTS) return;\n seen.add(key);\n variants.push({ q, weight, lang, reason });\n };\n\n push(original, 1, isEnglish ? 'en' : 'es', 'original');\n\n const match = findRule(normalized);\n let intent = [];\n let sports = tokens.some((t) => SPORTS_TERMS.has(t));\n\n if (match) {\n const { rule, exact } = match;\n const factor = exact ? 1 : 0.9;\n rule.q.forEach((entry, idx) => {\n const en = entry.startsWith('en:');\n push(en ? entry.slice(3) : entry, +((0.9 - idx * 0.1) * factor).toFixed(2), en ? 'en' : 'es', exact ? 'phrase-rule' : 'phrase-rule-partial');\n });\n intent = rule.i.map(normalizeQuery);\n sports = sports || !!rule.sports;\n } else {\n const hasMeme = tokens.includes('meme');\n if (!hasMeme) push(`${normalized} meme`, 0.8, isEnglish ? 'en' : 'es', tokens.length > 1 ? 'phrase-meme' : 'word-meme');\n if (enPhrase) push(enPhrase, 0.6, 'en', 'translation');\n if (enPhrase && !hasMeme) push(`${enPhrase} reaction`, 0.5, 'en', 'translation-reaction');\n }\n\n const intentTerms = uniq([...intent, ...tokens, ...translated, ...(enPhrase ? [enPhrase] : [])])\n .filter((t) => t !== 'meme' || intent.includes('meme'))\n .slice(0, 24);\n\n return {\n original,\n normalized,\n variants,\n intentTerms,\n avoidTerms: sports ? [] : AVOID_TERMS.slice(),\n isPhrase: tokens.length > 1 || !!match,\n };\n}\n\nexport default expandGifQuery;\n","/**\n * Ranking de relevancia para resultados de GIF de KLIPY.\n * Módulo puro: sin React, DOM ni red.\n */\nimport { normalizeQuery, tokenize } from './gifQueryExpansion.js';\n\nconst RANK_DECAY = 0.08;\nconst TITLE_PHRASE = 1.2;\nconst TAG_PHRASE = 0.9;\nconst TITLE_TOKEN = 0.6;\nconst TAG_TOKEN = 0.4;\nconst PARTIAL_PHRASE = 0.25;\nconst AVOID_PENALTY = 0.8;\nconst EMPTY_PENALTY = 0.15;\nconst PROTECT_TOP = 4; // top-N del query original que no se deben enterrar\nconst PROTECT_SLACK = 2; // posiciones que pueden bajar como máximo\n\n/** Normaliza texto libre (incluye separadores tipo slug). */\nconst norm = (s) => normalizeQuery(String(s || '').replace(/[-_]+/g, ' ')) || '';\n\n/** Clave de deduplicación. */\nconst keyOf = (item) => item?.id ?? item?.url ?? item?.slug;\n\n/**\n * Precalcula términos normalizados (una vez por llamada).\n * @param {string[]} intentTerms\n * @param {string[]} avoidTerms\n */\nfunction prepareTerms(intentTerms = [], avoidTerms = []) {\n const prep = (list) => {\n const seen = new Set();\n const out = [];\n for (const t of list || []) {\n const n = norm(t);\n if (!n || seen.has(n)) continue;\n seen.add(n);\n const tokens = tokenize(n);\n out.push({ text: n, padded: ` ${n} `, tokens, phrase: tokens.length > 1 });\n }\n return out;\n };\n return { intent: prep(intentTerms), avoid: prep(avoidTerms) };\n}\n\n/** Prepara el texto indexable del item. */\nfunction prepareItem(item) {\n const title = norm(item?.title);\n const tags = Array.isArray(item?.tags) ? item.tags.map(norm).filter(Boolean) : [];\n const tagText = tags.join(' ');\n return {\n title,\n titlePadded: ` ${title} `,\n tagsPadded: tags.map((t) => ` ${t} `),\n titleTokens: new Set(tokenize(title)),\n tagTokens: new Set(tokenize(tagText)),\n all: ` ${title} ${tagText} `,\n empty: !title && !tags.length,\n };\n}\n\n/** Bonus de intención + flag de coincidencia. */\nfunction intentMatch(doc, intent) {\n let bonus = 0;\n let matched = false;\n for (const term of intent) {\n if (term.phrase) {\n if (doc.titlePadded.includes(term.padded)) {\n bonus += TITLE_PHRASE;\n matched = true;\n } else if (doc.tagsPadded.some((t) => t.includes(term.padded))) {\n bonus += TAG_PHRASE;\n matched = true;\n } else {\n let hits = 0;\n for (const tk of term.tokens) if (doc.titleTokens.has(tk) || doc.tagTokens.has(tk)) hits++;\n if (hits) bonus += PARTIAL_PHRASE * (hits / term.tokens.length);\n if (hits === term.tokens.length) matched = true;\n }\n } else if (doc.titleTokens.has(term.text)) {\n bonus += TITLE_TOKEN;\n matched = true;\n } else if (doc.tagTokens.has(term.text)) {\n bonus += TAG_TOKEN;\n matched = true;\n }\n }\n return { bonus, matched };\n}\n\n/** Score interno con términos ya preparados. */\nfunction scoreWith(item, terms, variantWeight = 1, rank = 0) {\n const doc = prepareItem(item);\n const prior = (1 / (1 + Math.max(0, rank) * RANK_DECAY)) * variantWeight;\n if (doc.empty) return { score: prior - EMPTY_PENALTY, matched: false };\n const { bonus, matched } = intentMatch(doc, terms.intent);\n let score = prior + bonus;\n if (!matched && terms.avoid.some((a) => doc.all.includes(a.padded))) score -= AVOID_PENALTY;\n return { score, matched };\n}\n\n/**\n * Puntúa un GIF según orden de KLIPY, peso de variante e intención.\n * @param {object} item GIF `{ id, title, tags, ... }`\n * @param {{ intentTerms?: string[], avoidTerms?: string[], variantWeight?: number, rank?: number }} opts\n * @returns {number}\n */\nexport function scoreGif(item, { intentTerms = [], avoidTerms = [], variantWeight = 1, rank = 0 } = {}) {\n return scoreWith(item, prepareTerms(intentTerms, avoidTerms), variantWeight, rank).score;\n}\n\n/**\n * Fusiona resultados de varias variantes, deduplica por id y ordena por score.\n * Los primeros resultados del query original (índice 0) que coinciden con la\n * intención no bajan más de PROTECT_SLACK posiciones respecto a su rank original.\n * @param {{ variant?: { weight?: number }, items: object[] }[]} groups\n * @param {{ intentTerms?: string[], avoidTerms?: string[] }} expansion\n * @returns {object[]}\n */\nexport function rankGifs(groups, expansion = {}) {\n const terms = prepareTerms(expansion?.intentTerms, expansion?.avoidTerms);\n const noIntent = terms.intent.length === 0;\n const best = new Map();\n let seq = 0;\n\n (groups || []).forEach((group, gi) => {\n const weight = group?.variant?.weight ?? 1;\n (group?.items || []).forEach((item, rank) => {\n const key = keyOf(item);\n if (key == null) return;\n const { score, matched } = scoreWith(item, terms, weight, rank);\n const prev = best.get(key);\n const protectedRank = gi === 0 && rank < PROTECT_TOP && (matched || noIntent) ? rank : -1;\n if (!prev) {\n best.set(key, { item, score, order: seq++, protectedRank });\n } else {\n if (score > prev.score) {\n prev.score = score;\n prev.item = item;\n }\n if (protectedRank >= 0 && prev.protectedRank < 0) prev.protectedRank = protectedRank;\n }\n });\n });\n\n const sorted = [...best.values()].sort((a, b) => b.score - a.score || a.order - b.order);\n\n const pinned = sorted.filter((e) => e.protectedRank >= 0).sort((a, b) => a.protectedRank - b.protectedRank);\n for (const entry of pinned) {\n const idx = sorted.indexOf(entry);\n const maxIdx = entry.protectedRank + PROTECT_SLACK;\n if (idx > maxIdx) {\n sorted.splice(idx, 1);\n sorted.splice(maxIdx, 0, entry);\n }\n }\n\n return sorted.map((e) => e.item);\n}\n\n/**\n * ¿Hay al menos `min` resultados que coinciden con la intención?\n * @param {object[]} items\n * @param {{ intentTerms?: string[] }} expansion\n * @param {{ min?: number }} [opts]\n * @returns {boolean}\n */\nexport function hasGoodResults(items, expansion, { min = 6 } = {}) {\n const list = items || [];\n const terms = prepareTerms(expansion?.intentTerms, []);\n if (!terms.intent.length) return list.length >= min;\n let count = 0;\n for (const item of list) {\n if (intentMatch(prepareItem(item), terms.intent).matched && ++count >= min) return true;\n }\n return false;\n}\n\n/**\n * Añade a `previous` los items de `next` cuyo id aún no está (scroll infinito).\n * @param {object[]} previous\n * @param {object[]} next\n * @returns {object[]}\n */\nexport function interleaveFresh(previous = [], next = []) {\n const seen = new Set((previous || []).map(keyOf));\n const out = [...(previous || [])];\n for (const item of next || []) {\n const key = keyOf(item);\n if (key == null || seen.has(key)) continue;\n seen.add(key);\n out.push(item);\n }\n return out;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\nimport { isTrustedKlipyUrl } from '../klipy/klipy.js';\n\n// Local-only GIF favorites/recents (no backend, no cross-device sync).\nexport const MAX_RECENTS = 40;\nexport const MAX_FAVORITES = 200;\nconst STORAGE_KEY = 'lira-gif-library:v1';\nconst hasWindow = typeof window !== 'undefined';\n\n/** Only credential-free https URLs on KLIPY media hosts are accepted. */\nfunction safeUrl(value) {\n if (typeof value !== 'string' || value.length > 2048) return null;\n if (!isTrustedKlipyUrl(value)) return null;\n try {\n const url = new URL(value);\n return url.port ? null : url.href;\n } catch {\n return null;\n }\n}\n\nconst text = (value, max = 256) => (typeof value === 'string' ? value.slice(0, max) : '');\nconst dimension = (value) => (Number.isFinite(value) && value > 0 ? Math.round(value) : 0);\n\n/** Strip to the stored shape; returns null for invalid items. */\nexport function sanitizeItem(item, savedAt) {\n if (!item || typeof item !== 'object') return null;\n const { id } = item;\n if (!((typeof id === 'string' && id) || (typeof id === 'number' && Number.isFinite(id)))) return null;\n const url = safeUrl(item.url);\n const preview = safeUrl(item.preview);\n if (!url || !preview) return null;\n const time = savedAt ?? item.savedAt;\n return {\n id: String(id).slice(0, 128),\n slug: text(item.slug),\n title: text(item.title),\n preview,\n url,\n width: dimension(item.width),\n height: dimension(item.height),\n savedAt: Number.isFinite(time) && time >= 0 ? time : 0,\n };\n}\n\n// Sanitize + dedupe by id (first occurrence wins) + cap.\nfunction cleanList(list, max) {\n if (!Array.isArray(list)) return [];\n const seen = new Set();\n const out = [];\n for (const raw of list) {\n const item = sanitizeItem(raw);\n if (!item || seen.has(item.id)) continue;\n seen.add(item.id);\n out.push(item);\n if (out.length >= max) break;\n }\n return out;\n}\n\nfunction readStorage() {\n const empty = { favorites: [], recents: [] };\n if (!hasWindow) return empty;\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return empty;\n const data = JSON.parse(raw);\n return {\n favorites: cleanList(data?.favorites, MAX_FAVORITES),\n recents: cleanList(data?.recents, MAX_RECENTS),\n };\n } catch {\n return empty;\n }\n}\n\n// Private mode / quota errors are ignored: state stays in memory.\nfunction writeStorage({ favorites, recents }) {\n if (!hasWindow) return;\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ favorites, recents }));\n } catch {\n /* keep in memory */\n }\n}\n\nconst idOf = (value) => (value == null ? '' : String(value));\n\nexport function createGifLibraryStore() {\n const store = createStore((set, get) => {\n // Persist after every local mutation.\n const commit = (next) => {\n set(next);\n const { favorites, recents } = get();\n writeStorage({ favorites, recents });\n };\n\n return {\n ...readStorage(),\n\n isFavorite: (id) => {\n const key = idOf(id);\n return get().favorites.some((item) => item.id === key);\n },\n\n toggleFavorite: (raw) => {\n const key = idOf(raw?.id);\n const { favorites } = get();\n if (favorites.some((item) => item.id === key)) {\n commit({ favorites: favorites.filter((item) => item.id !== key) });\n return;\n }\n const item = sanitizeItem(raw, Date.now());\n if (!item) return;\n commit({ favorites: [item, ...favorites].slice(0, MAX_FAVORITES) });\n },\n\n addRecent: (raw) => {\n const item = sanitizeItem(raw, Date.now());\n if (!item) return;\n const rest = get().recents.filter((entry) => entry.id !== item.id);\n commit({ recents: [item, ...rest].slice(0, MAX_RECENTS) });\n },\n\n removeRecent: (id) => {\n const key = idOf(id);\n commit({ recents: get().recents.filter((item) => item.id !== key) });\n },\n\n clearRecents: () => commit({ recents: [] }),\n };\n });\n\n // Cross-tab sync: another tab wrote (or storage was cleared) → re-read.\n // Explicit opt-in (no import-time side effects). Ref-counted: the listener is\n // registered once and removed when every caller has called its stop().\n let syncRefs = 0;\n const onStorage = (event) => {\n if (event.key === STORAGE_KEY || event.key === null) store.setState(readStorage());\n };\n store.startSync = () => {\n if (!hasWindow || typeof window.addEventListener !== 'function') return () => {};\n if (syncRefs === 0) {\n window.addEventListener('storage', onStorage);\n store.setState(readStorage());\n }\n syncRefs += 1;\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n syncRefs -= 1;\n if (syncRefs === 0) window.removeEventListener('storage', onStorage);\n };\n };\n return store;\n}\n\nconst gifLibraryStore = createGifLibraryStore();\n/** Backward-compatible singleton hook (with vanilla store API attached). */\nexport const useGifLibrary = Object.assign((selector) => useStore(gifLibraryStore, selector), {\n getState: gifLibraryStore.getState, setState: gifLibraryStore.setState, subscribe: gifLibraryStore.subscribe,\n});\n\nexport function startGifLibrarySync(store = gifLibraryStore) {\n return (store === useGifLibrary ? gifLibraryStore : store).startSync();\n}\n","/**\n * Motor de búsqueda de GIFs (sin React): feeds trending/search/recent/favorites,\n * búsqueda inteligente multi-variante, caché LRU con TTL y dedupe de requests en vuelo.\n */\nimport { fetchTrendingGifs, searchGifsPage, fetchRecentGifs, getKlipyLocale } from '../klipy/klipy.js';\nimport { expandGifQuery, normalizeQuery } from './gifQueryExpansion.js';\nimport { rankGifs, hasGoodResults } from './gifRelevance.js';\nimport { useGifLibrary } from './gifLibrary.js';\n\nconst CACHE_TTL_MS = 5 * 60 * 1000;\nconst CACHE_MAX = 150;\nconst MAX_VARIANTS_PAGE1 = 3;\nconst MAX_VARIANTS_NEXT = 2;\nconst APPROX_NOTICE = 'Mostrando resultados aproximados';\n\n/** @type {Map<string, { value: any, expires: number }>} */\nconst cache = new Map();\n/** @type {Map<string, { promise: Promise<any>, controller: AbortController, refs: number }>} */\nconst inflight = new Map();\n\n/** Vacía la caché en memoria (las requests en vuelo siguen su curso). */\nexport function clearGifCache() {\n cache.clear();\n}\n\nfunction makeAbortError() {\n try {\n return new DOMException('Aborted', 'AbortError');\n } catch {\n const err = new Error('Aborted');\n err.name = 'AbortError';\n return err;\n }\n}\n\nconst isAbortError = (err) => err?.name === 'AbortError';\n\nfunction cacheGet(key) {\n const entry = cache.get(key);\n if (!entry) return undefined;\n if (entry.expires <= Date.now()) {\n cache.delete(key);\n return undefined;\n }\n // LRU: mover al final.\n cache.delete(key);\n cache.set(key, entry);\n return entry.value;\n}\n\nfunction cacheSet(key, value) {\n cache.delete(key);\n cache.set(key, { value, expires: Date.now() + CACHE_TTL_MS });\n while (cache.size > CACHE_MAX) {\n cache.delete(cache.keys().next().value);\n }\n}\n\n/**\n * Ejecuta `fetcher(signal)` con caché + dedupe. La request compartida solo se aborta\n * cuando TODOS los callers abortaron; cada caller abortado recibe AbortError de inmediato.\n * @param {string} key\n * @param {(signal: AbortSignal) => Promise<any>} fetcher\n * @param {AbortSignal} [signal]\n */\nfunction cachedRequest(key, fetcher, signal) {\n if (signal?.aborted) return Promise.reject(makeAbortError());\n\n const hit = cacheGet(key);\n if (hit !== undefined) return Promise.resolve(hit);\n\n let entry = inflight.get(key);\n if (!entry) {\n const controller = new AbortController();\n const promise = Promise.resolve()\n .then(() => fetcher(controller.signal))\n .then((value) => {\n cacheSet(key, value); // nunca se cachean fallos\n return value;\n })\n .finally(() => {\n if (inflight.get(key) === entry) inflight.delete(key);\n });\n entry = { promise, controller, refs: 0 };\n inflight.set(key, entry);\n }\n const shared = entry;\n shared.refs += 1;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const release = () => {\n shared.refs -= 1;\n if (shared.refs <= 0) {\n if (inflight.get(key) === shared) inflight.delete(key);\n shared.controller.abort();\n }\n };\n const onAbort = () => {\n if (settled) return;\n settled = true;\n release();\n reject(makeAbortError());\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n\n shared.promise.then(\n (value) => {\n if (settled) return;\n settled = true;\n shared.refs -= 1;\n signal?.removeEventListener('abort', onAbort);\n resolve(value);\n },\n (err) => {\n if (settled) return;\n settled = true;\n shared.refs -= 1;\n signal?.removeEventListener('abort', onAbort);\n reject(err);\n },\n );\n });\n}\n\nconst keyOf = (kind, query, locale, page, perPage) =>\n `${kind}|${query}|${locale}|${page}|${perPage}`;\n\nconst normalizeResult = (res) => ({\n items: Array.isArray(res?.items) ? res.items : [],\n hasMore: Boolean(res?.hasMore),\n});\n\nfunction loadTrending({ page, perPage, signal }) {\n const key = keyOf('trending', '', getKlipyLocale(), page, perPage);\n return cachedRequest(\n key,\n (s) => fetchTrendingGifs({ page, perPage, locale: getKlipyLocale(), signal: s }).then(normalizeResult),\n signal,\n ).then((res) => ({ ...res, notice: null }));\n}\n\nfunction loadVariant(variant, page, perPage, signal) {\n const key = keyOf('search', normalizeQuery(variant.q), getKlipyLocale(), page, perPage);\n return cachedRequest(\n key,\n (s) =>\n searchGifsPage({ query: variant.q, page, perPage, locale: getKlipyLocale(), signal: s }).then(\n normalizeResult,\n ),\n signal,\n );\n}\n\n/** Elige variantes por peso, garantizando que la query original quede incluida. */\nfunction pickVariants(expansion, limit) {\n const all = Array.isArray(expansion?.variants) ? [...expansion.variants] : [];\n if (!all.length) {\n all.push({ q: expansion?.original || expansion?.normalized || '', weight: 1, lang: null, reason: 'original' });\n }\n const sorted = all\n .map((v, i) => ({ v, i }))\n .sort((a, b) => (b.v.weight ?? 0) - (a.v.weight ?? 0) || a.i - b.i)\n .map(({ v }) => v);\n const picked = sorted.slice(0, limit);\n const originalNorm = normalizeQuery(expansion?.original || '');\n if (originalNorm && !picked.some((v) => normalizeQuery(v.q) === originalNorm)) {\n const orig = sorted.find((v) => normalizeQuery(v.q) === originalNorm) || {\n q: expansion.original,\n weight: 1,\n lang: null,\n reason: 'original',\n };\n if (picked.length < limit) picked.push(orig);\n else picked[limit - 1] = orig;\n }\n return picked;\n}\n\nasync function loadSearch({ query, page, perPage, signal }) {\n const expansion = expandGifQuery(query);\n const variants = pickVariants(expansion, page > 1 ? MAX_VARIANTS_NEXT : MAX_VARIANTS_PAGE1);\n\n const settled = await Promise.allSettled(\n variants.map((v) => loadVariant(v, page, perPage, signal)),\n );\n if (signal?.aborted) throw makeAbortError();\n\n const groups = [];\n let firstError = null;\n settled.forEach((r, i) => {\n if (r.status === 'fulfilled') {\n groups.push({ ...variants[i], variant: variants[i], items: r.value.items, hasMore: r.value.hasMore });\n } else if (!firstError || isAbortError(firstError)) {\n firstError = r.reason;\n }\n });\n if (!groups.length) throw firstError || new Error('GIF search failed');\n\n const items = rankGifs(groups, expansion) || [];\n const hasMore = groups.some((g) => g.hasMore);\n let notice = null;\n if (page === 1 && items.length && !hasGoodResults(items, expansion)) notice = APPROX_NOTICE;\n\n return { items, hasMore, notice };\n}\n\nasync function loadRecent({ page, perPage, signal }) {\n const local = useGifLibrary.getState().recents || [];\n if (local.length) {\n return page === 1\n ? { items: local.slice(), hasMore: false, notice: null }\n : { items: [], hasMore: false, notice: null };\n }\n const key = keyOf('recent', '', '', page, perPage);\n const res = await cachedRequest(\n key,\n (s) => fetchRecentGifs({ page, perPage, signal: s }).then(normalizeResult),\n signal,\n );\n return { ...res, notice: null };\n}\n\nfunction loadFavorites({ page }) {\n const favs = useGifLibrary.getState().favorites || [];\n return Promise.resolve({\n items: page === 1 ? favs.slice() : [],\n hasMore: false,\n notice: null,\n });\n}\n\n/**\n * Carga una página del feed de GIFs.\n * @param {{ source: 'trending'|'search'|'recent'|'favorites', query?: string, page?: number, perPage?: number, signal?: AbortSignal }} opts\n * @returns {Promise<{ items: any[], hasMore: boolean, notice: string|null }>}\n */\nexport async function loadGifFeed({ source, query, page = 1, perPage = 24, signal } = {}) {\n if (signal?.aborted) throw makeAbortError();\n switch (source) {\n case 'search':\n if (!String(query ?? '').trim()) return loadTrending({ page, perPage, signal });\n return loadSearch({ query, page, perPage, signal });\n case 'recent':\n return loadRecent({ page, perPage, signal });\n case 'favorites':\n return loadFavorites({ page });\n case 'trending':\n default:\n return loadTrending({ page, perPage, signal });\n }\n}\n","/**\n * Categorías del selector de GIFs (orientadas a español/LatAm).\n * Módulo puro: sin efectos secundarios. Íconos de lucide-react.\n */\nimport {\n Angry, Clock, Eye, Flame, Frown, Hand, HandHeart, Heart, Laugh, Music, PartyPopper, Smile, Sparkles, Star,\n} from 'lucide-react';\nimport { normalizeQuery } from './gifQueryExpansion.js';\n\nexport const DEFAULT_CATEGORY_ID = 'trending';\n\nexport const GIF_CATEGORIES = Object.freeze([\n { id: 'trending', label: 'Tendencias', icon: Flame, source: 'trending', query: '' },\n { id: 'memes', label: 'Memes', icon: Laugh, source: 'search', query: 'memes en español' },\n { id: 'recent', label: 'Recientes', icon: Clock, source: 'recent', query: '' },\n { id: 'favorites', label: 'Favoritos', icon: Star, source: 'favorites', query: '' },\n { id: 'love', label: 'Amor', icon: Heart, source: 'search', query: 'amor' },\n { id: 'laugh', label: 'Risas', icon: Smile, source: 'search', query: 'jajaja' },\n { id: 'sad', label: 'Tristeza', icon: Frown, source: 'search', query: 'triste' },\n { id: 'angry', label: 'Enojo', icon: Angry, source: 'search', query: 'enojado' },\n { id: 'surprise', label: 'Sorpresa', icon: Sparkles, source: 'search', query: 'sorprendido' },\n { id: 'party', label: 'Celebración', icon: PartyPopper, source: 'search', query: 'celebracion' },\n { id: 'reactions', label: 'Reacciones', icon: Eye, source: 'search', query: 'reaccion' },\n { id: 'thanks', label: 'Gracias', icon: HandHeart, source: 'search', query: 'gracias' },\n { id: 'greet', label: 'Saludos', icon: Hand, source: 'search', query: 'hola' },\n { id: 'dance', label: 'Bailar', icon: Music, source: 'search', query: 'bailar' },\n].map((c) => Object.freeze(c)));\n\n/** Sinónimos (normalizados) por id de categoría, para emparejar con KLIPY. */\nconst CATEGORY_SYNONYMS = {\n memes: ['memes', 'meme', 'memes en espanol'],\n love: ['amor', 'love', 'enamorado', 'corazon'],\n laugh: ['risa', 'risas', 'jajaja', 'laugh', 'laughing', 'funny', 'lol'],\n sad: ['triste', 'tristeza', 'sad', 'crying', 'cry', 'llorar'],\n angry: ['enojo', 'enojado', 'angry', 'mad'],\n surprise: ['sorpresa', 'sorprendido', 'surprised', 'surprise', 'wow', 'omg'],\n party: ['celebracion', 'fiesta', 'party', 'celebrate', 'celebration'],\n reactions: ['reaccion', 'reacciones', 'reaction', 'reactions'],\n thanks: ['gracias', 'thank you', 'thanks', 'thankyou'],\n greet: ['hola', 'saludos', 'hello', 'hi', 'hey'],\n dance: ['bailar', 'baile', 'dance', 'dancing'],\n};\n\nconst safeNormalize = (value) => (typeof value === 'string' ? normalizeQuery(value) : '');\n\nfunction matchKeys(category) {\n const keys = new Set([safeNormalize(category.label), safeNormalize(category.query)]);\n for (const s of CATEGORY_SYNONYMS[category.id] || []) keys.add(safeNormalize(s));\n keys.delete('');\n return keys;\n}\n\nfunction findKlipyMatch(category, klipyCategories) {\n const keys = matchKeys(category);\n return klipyCategories.find((k) => {\n if (!k || typeof k !== 'object') return false;\n return keys.has(safeNormalize(k.category)) || keys.has(safeNormalize(k.query));\n });\n}\n\n/**\n * Enriquece nuestras categorías de búsqueda con preview/klipyQuery de KLIPY.\n * No agrega categorías de KLIPY sin coincidencia. No muta las entradas.\n */\nexport function mergeKlipyCategories(categories, klipyCategories) {\n const base = Array.isArray(categories) ? categories : GIF_CATEGORIES;\n const klipy = Array.isArray(klipyCategories) ? klipyCategories : [];\n return base.map((cat) => {\n const copy = { ...cat };\n if (cat.source !== 'search' || klipy.length === 0) return copy;\n const match = findKlipyMatch(cat, klipy);\n if (!match) return copy;\n if (match.preview) copy.preview = match.preview;\n const kq = match.query || match.category;\n if (kq) copy.klipyQuery = kq;\n return copy;\n });\n}\n\nexport function findCategory(id) {\n return GIF_CATEGORIES.find((c) => c.id === id) || null;\n}\n","/* eslint-disable react/prop-types */\nimport { memo, useCallback, useEffect, useRef, useState } from 'react';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\n\nconst prefersReducedMotion = () =>\n typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nfunction GifCategoryBar({ categories = [], activeId, onSelect, disabled }) {\n const scrollerRef = useRef(null);\n const chipRefs = useRef(new Map());\n const [canPrev, setCanPrev] = useState(false);\n const [canNext, setCanNext] = useState(false);\n\n const updateOverflow = useCallback(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const max = el.scrollWidth - el.clientWidth;\n setCanPrev(el.scrollLeft > 1);\n setCanNext(max > 1 && el.scrollLeft < max - 1);\n }, []);\n\n // Track scroll position and size changes to toggle nav buttons.\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return undefined;\n updateOverflow();\n el.addEventListener('scroll', updateOverflow, { passive: true });\n let ro;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(updateOverflow);\n ro.observe(el);\n } else {\n window.addEventListener('resize', updateOverflow);\n }\n return () => {\n el.removeEventListener('scroll', updateOverflow);\n if (ro) ro.disconnect();\n else window.removeEventListener('resize', updateOverflow);\n };\n }, [updateOverflow]);\n\n useEffect(() => { updateOverflow(); }, [categories, updateOverflow]);\n\n // Vertical wheel -> horizontal scroll when content overflows.\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return undefined;\n const onWheel = (event) => {\n if (event.ctrlKey) return;\n if (el.scrollWidth <= el.clientWidth) return;\n if (Math.abs(event.deltaY) <= Math.abs(event.deltaX)) return;\n const factor = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? el.clientWidth : 1;\n const before = el.scrollLeft;\n el.scrollLeft = before + event.deltaY * factor;\n if (el.scrollLeft !== before) event.preventDefault();\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, []);\n\n // Keep active chip visible.\n useEffect(() => {\n const chip = chipRefs.current.get(activeId);\n if (chip && typeof chip.scrollIntoView === 'function') {\n chip.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: prefersReducedMotion() ? 'auto' : 'smooth' });\n }\n }, [activeId]);\n\n const scrollByPage = (dir) => {\n const el = scrollerRef.current;\n if (!el) return;\n el.scrollBy({ left: dir * el.clientWidth * 0.7, behavior: prefersReducedMotion() ? 'auto' : 'smooth' });\n };\n\n const handleKeyDown = (event) => {\n if (disabled || !categories.length) return;\n const current = categories.findIndex((c) => c.id === activeId);\n const last = categories.length - 1;\n let next;\n switch (event.key) {\n case 'ArrowRight': next = current < 0 ? 0 : (current + 1) % categories.length; break;\n case 'ArrowLeft': next = current <= 0 ? last : current - 1; break;\n case 'Home': next = 0; break;\n case 'End': next = last; break;\n default: return;\n }\n event.preventDefault();\n const target = categories[next];\n chipRefs.current.get(target.id)?.focus();\n if (target.id !== activeId) onSelect?.(target.id);\n };\n\n const hasActive = categories.some((c) => c.id === activeId);\n\n return (\n <div className=\"chat-gif-cats\">\n <button\n type=\"button\"\n className=\"chat-gif-cats__nav chat-gif-cats__nav--prev\"\n aria-label=\"Categorías anteriores\"\n onClick={() => scrollByPage(-1)}\n hidden={!canPrev}\n tabIndex={-1}\n >\n <ChevronLeft size={16} aria-hidden=\"true\" />\n </button>\n <div\n ref={scrollerRef}\n className=\"chat-gif-cats__scroller\"\n role=\"tablist\"\n aria-label=\"Categorías de GIFs\"\n onKeyDown={handleKeyDown}\n >\n {categories.map((cat, index) => {\n const active = cat.id === activeId;\n const focusable = active || (!hasActive && index === 0);\n const Icon = cat.icon;\n return (\n <button\n key={cat.id}\n ref={(node) => {\n if (node) chipRefs.current.set(cat.id, node);\n else chipRefs.current.delete(cat.id);\n }}\n type=\"button\"\n role=\"tab\"\n className={`chat-gif-cats__chip${active ? ' chat-gif-cats__chip--active' : ''}`}\n aria-selected={active}\n tabIndex={focusable ? 0 : -1}\n disabled={disabled}\n title={cat.label}\n onClick={() => { if (!active) onSelect?.(cat.id); }}\n >\n {Icon && <Icon size={15} strokeWidth={1.75} aria-hidden=\"true\" className=\"chat-gif-cats__icon\" />}\n <span className=\"chat-gif-cats__label\">{cat.label}</span>\n </button>\n );\n })}\n </div>\n <button\n type=\"button\"\n className=\"chat-gif-cats__nav chat-gif-cats__nav--next\"\n aria-label=\"Más categorías\"\n onClick={() => scrollByPage(1)}\n hidden={!canNext}\n tabIndex={-1}\n >\n <ChevronRight size={16} aria-hidden=\"true\" />\n </button>\n </div>\n );\n}\n\nexport default memo(GifCategoryBar);\n","/* eslint-disable react/prop-types */\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Loader2, Star } from 'lucide-react';\n\nconst WIDE_BREAKPOINT = 420;\nconst PREVIEW_DELAY = 350;\nconst SKELETON_RATIOS = [1.3, 0.75, 1, 1.5, 0.8, 1.1, 0.9, 1.4, 0.7, 1.2, 1, 0.85];\n\nfunction ratioOf(item) {\n const w = Number(item?.width);\n const h = Number(item?.height);\n return w > 0 && h > 0 ? h / w : 1;\n}\n\n// Greedy masonry: each entry goes to the currently shortest column (stable for appends).\nfunction distribute(list, cols, getRatio) {\n const columns = Array.from({ length: cols }, () => []);\n const heights = new Array(cols).fill(0);\n list.forEach((entry, index) => {\n let target = 0;\n for (let c = 1; c < cols; c += 1) {\n if (heights[c] < heights[target] - 0.001) target = c;\n }\n columns[target].push({ entry, index });\n heights[target] += getRatio(entry);\n });\n return columns;\n}\n\nfunction prefersReducedMotion() {\n try {\n return window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n } catch {\n return false;\n }\n}\n\nfunction isFocusVisible(el) {\n try {\n return el.matches(':focus-visible');\n } catch {\n return true;\n }\n}\n\nconst GifTile = memo(function GifTile({ item, fav, disabled, onSelect, onToggleFavorite }) {\n const [loaded, setLoaded] = useState(false);\n const [broken, setBroken] = useState(false);\n const [preview, setPreview] = useState(false);\n const [previewFailed, setPreviewFailed] = useState(false);\n const timerRef = useRef(null);\n\n const w = Number(item.width);\n const h = Number(item.height);\n const aspectRatio = w > 0 && h > 0 ? `${w} / ${h}` : '1 / 1';\n const label = item.title || 'GIF';\n const canPreview = Boolean(item.url) && item.url !== item.preview && !previewFailed;\n const showPreview = preview && canPreview && !broken;\n\n const clearTimer = () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n useEffect(() => clearTimer, []);\n\n const startPreview = (immediate) => {\n if (!canPreview || prefersReducedMotion()) return;\n clearTimer();\n if (immediate) setPreview(true);\n else timerRef.current = setTimeout(() => setPreview(true), PREVIEW_DELAY);\n };\n\n const stopPreview = () => {\n clearTimer();\n setPreview(false);\n };\n\n const handleError = () => {\n if (showPreview) {\n setPreviewFailed(true);\n setPreview(false);\n return;\n }\n setBroken(true);\n };\n\n return (\n <div\n role=\"listitem\"\n className={`chat-gif-tile${showPreview ? ' chat-gif-tile--preview' : ''}`}\n onPointerEnter={(e) => {\n if (e.pointerType === 'touch') return;\n startPreview(false);\n }}\n onPointerLeave={stopPreview}\n >\n <button\n type=\"button\"\n className=\"chat-gif-tile__pick\"\n aria-label={label}\n disabled={disabled}\n onClick={() => onSelect(item)}\n onFocus={(e) => {\n if (isFocusVisible(e.currentTarget)) startPreview(true);\n }}\n onBlur={stopPreview}\n >\n <span className=\"chat-gif-tile__media\" style={{ aspectRatio }}>\n {broken ? (\n <span className=\"chat-gif-tile__broken\" aria-hidden=\"true\">GIF</span>\n ) : (\n <img\n className={`chat-gif-tile__img${loaded ? ' chat-gif-tile__img--loaded' : ''}`}\n src={showPreview ? item.url : item.preview}\n alt={label}\n loading=\"lazy\"\n decoding=\"async\"\n onLoad={() => setLoaded(true)}\n onError={handleError}\n />\n )}\n </span>\n </button>\n {onToggleFavorite && (\n <button\n type=\"button\"\n className={`chat-gif-tile__fav${fav ? ' chat-gif-tile__fav--on' : ''}`}\n aria-pressed={fav}\n aria-label={fav ? 'Quitar de favoritos' : 'Agregar a favoritos'}\n onClick={(e) => {\n e.stopPropagation();\n onToggleFavorite(item);\n }}\n >\n <Star size={14} fill={fav ? 'currentColor' : 'none'} />\n </button>\n )}\n </div>\n );\n});\n\nfunction findNeighbor(container, current, key) {\n const buttons = Array.from(container.querySelectorAll('.chat-gif-tile__pick:not(:disabled)'));\n const from = current.getBoundingClientRect();\n const fx = from.left + from.width / 2;\n const fy = from.top + from.height / 2;\n let best = null;\n let bestScore = Infinity;\n buttons.forEach((btn) => {\n if (btn === current) return;\n const r = btn.getBoundingClientRect();\n const cx = r.left + r.width / 2;\n const cy = r.top + r.height / 2;\n const dx = cx - fx;\n const dy = cy - fy;\n let primary;\n let secondary;\n if (key === 'ArrowDown') { primary = dy; secondary = Math.abs(dx); }\n else if (key === 'ArrowUp') { primary = -dy; secondary = Math.abs(dx); }\n else if (key === 'ArrowRight') { primary = dx; secondary = Math.abs(dy); }\n else { primary = -dx; secondary = Math.abs(dy); }\n if (primary <= 1) return;\n const score = primary + secondary * 2;\n if (score < bestScore) {\n bestScore = score;\n best = btn;\n }\n });\n return best;\n}\n\nexport default function GifGrid({\n items,\n loading,\n hasMore,\n error,\n onLoadMore,\n onRetry,\n onSelect,\n onToggleFavorite,\n isFavorite,\n empty,\n disabled,\n scrollKey,\n}) {\n const list = items || [];\n const containerRef = useRef(null);\n const sentinelRef = useRef(null);\n const [cols, setCols] = useState(2);\n\n // Stable callbacks so memoized tiles don't re-render when parent handlers change identity.\n const handlersRef = useRef({ onSelect, onToggleFavorite, onLoadMore });\n handlersRef.current = { onSelect, onToggleFavorite, onLoadMore };\n const stableSelect = useCallback((item) => handlersRef.current.onSelect?.(item), []);\n const stableToggle = useCallback((item) => handlersRef.current.onToggleFavorite?.(item), []);\n\n const stateRef = useRef({ loading, error, hasMore });\n stateRef.current = { loading, error, hasMore };\n const intersectingRef = useRef(false);\n const lastFiredCountRef = useRef(-1);\n\n const requestMore = useCallback(() => {\n const s = stateRef.current;\n if (!s.hasMore || s.loading || s.error) return;\n handlersRef.current.onLoadMore?.();\n }, []);\n\n // Responsive column count.\n useEffect(() => {\n const el = containerRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return undefined;\n const ro = new ResizeObserver((entries) => {\n const width = entries[0]?.contentRect?.width ?? el.clientWidth;\n setCols(width >= WIDE_BREAKPOINT ? 3 : 2);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // Reset scroll when the query/tab changes.\n useEffect(() => {\n if (containerRef.current) containerRef.current.scrollTop = 0;\n lastFiredCountRef.current = -1;\n }, [scrollKey]);\n\n // Infinite scroll.\n useEffect(() => {\n const root = containerRef.current;\n const sentinel = sentinelRef.current;\n if (!hasMore || !root || !sentinel) return undefined;\n const observer = new IntersectionObserver(\n (entries) => {\n const visible = entries.some((e) => e.isIntersecting);\n intersectingRef.current = visible;\n if (visible) requestMore();\n },\n { root, rootMargin: '200px' },\n );\n observer.observe(sentinel);\n return () => {\n observer.disconnect();\n intersectingRef.current = false;\n };\n }, [hasMore, requestMore]);\n\n // If the sentinel is still visible after a page loads, keep filling (once per new item count).\n useEffect(() => {\n if (loading || error || !hasMore || !intersectingRef.current) return;\n if (lastFiredCountRef.current === list.length) return;\n lastFiredCountRef.current = list.length;\n requestMore();\n }, [loading, error, hasMore, list.length, requestMore]);\n\n const columns = useMemo(() => distribute(list, cols, ratioOf), [list, cols]);\n const skeletonColumns = useMemo(\n () => distribute(SKELETON_RATIOS, cols, (r) => r),\n [cols],\n );\n\n const handleKeyDown = (e) => {\n if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) return;\n const target = e.target;\n if (!(target instanceof Element) || !target.classList.contains('chat-gif-tile__pick')) return;\n const next = findNeighbor(containerRef.current, target, e.key);\n e.preventDefault();\n if (next) {\n next.focus();\n next.scrollIntoView?.({ block: 'nearest' });\n }\n };\n\n const showSkeletons = loading && list.length === 0;\n const showEmpty = !loading && !error && list.length === 0;\n const EmptyIcon = empty?.icon;\n\n return (\n <>\n {error && (\n <div className=\"chat-attachment-notice chat-gif-error\" role=\"alert\">\n {error}{' '}\n <button type=\"button\" onClick={onRetry}>Reintentar</button>\n </div>\n )}\n <div\n ref={containerRef}\n className=\"chat-gif-grid\"\n role=\"list\"\n aria-label=\"Resultados de GIFs\"\n aria-busy={loading}\n onKeyDown={handleKeyDown}\n >\n {showSkeletons &&\n skeletonColumns.map((col, c) => (\n <div className=\"chat-gif-col\" key={`sk-${c}`}>\n {col.map(({ entry, index }) => (\n <div\n key={index}\n className=\"chat-gif-skeleton\"\n style={{ aspectRatio: `1 / ${entry}` }}\n aria-hidden=\"true\"\n />\n ))}\n </div>\n ))}\n\n {!showSkeletons &&\n list.length > 0 &&\n columns.map((col, c) => (\n <div className=\"chat-gif-col\" key={c}>\n {col.map(({ entry }) => (\n <GifTile\n key={entry.id ?? entry.slug}\n item={entry}\n fav={Boolean(isFavorite?.(entry))}\n disabled={disabled}\n onSelect={stableSelect}\n onToggleFavorite={onToggleFavorite ? stableToggle : undefined}\n />\n ))}\n </div>\n ))}\n\n {showEmpty && empty && (\n <div className=\"chat-gif-empty\" role=\"status\">\n {EmptyIcon && <EmptyIcon size={24} strokeWidth={1.5} aria-hidden=\"true\" className=\"chat-gif-empty__icon\" />}\n <strong className=\"chat-gif-empty__title\">{empty.title}</strong>\n {empty.hint && <small className=\"chat-gif-empty__hint\">{empty.hint}</small>}\n </div>\n )}\n\n {hasMore && (\n <div ref={sentinelRef} className=\"chat-gif-load-more\">\n {loading && list.length > 0 && <Loader2 size={20} className=\"spin\" />}\n </div>\n )}\n </div>\n </>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useCallback, useRef, useMemo } from 'react';\nimport { X, Search, SearchX, Star, Clock, ImageOff } from 'lucide-react';\nimport { fetchGifCategories, isTrustedKlipyUrl } from '../../media/klipy/klipy';\nimport { loadGifFeed } from '../../media/gif-search/gifSearchEngine';\nimport { GIF_CATEGORIES, DEFAULT_CATEGORY_ID, mergeKlipyCategories } from '../../media/gif-search/gifCategories';\nimport { useGifLibrary } from '../../media/gif-search/gifLibrary';\nimport GifCategoryBar from './GifCategoryBar';\nimport GifGrid from './GifGrid';\nimport '../styles/GifPicker.css';\n\nconst PER_PAGE = 24;\nconst SEARCH_DEBOUNCE_MS = 300;\n\nconst isSafeGif = (gif) => Boolean(gif?.id) && isTrustedKlipyUrl(gif.url) && isTrustedKlipyUrl(gif.preview);\n\nconst getEmptyState = (source, query) => {\n if (source === 'search') {\n return { icon: SearchX, title: `Sin resultados para “${query}”`, hint: 'Prueba con otra palabra o una expresión (ej. “no puede ser”)' };\n }\n if (source === 'favorites') {\n return { icon: Star, title: 'Aún no tienes favoritos', hint: 'Toca la estrella de un GIF para guardarlo aquí' };\n }\n if (source === 'recent') {\n return { icon: Clock, title: 'Sin GIFs recientes', hint: 'Los GIFs que envíes aparecerán aquí' };\n }\n return { icon: ImageOff, title: 'No se encontraron GIFs' };\n};\n\nexport default function GifPicker({ onSelect, onClose, disabled }) {\n const [query, setQuery] = useState('');\n const [categoryId, setCategoryId] = useState(DEFAULT_CATEGORY_ID);\n const [klipyCats, setKlipyCats] = useState([]);\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(false);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState('');\n const [notice, setNotice] = useState('');\n const requestRef = useRef(null);\n const versionRef = useRef(0);\n\n const favorites = useGifLibrary((s) => s.favorites);\n const recents = useGifLibrary((s) => s.recents);\n const toggleFavorite = useGifLibrary((s) => s.toggleFavorite);\n\n const favoriteIds = useMemo(() => new Set((favorites || []).map((g) => g?.id)), [favorites]);\n const isFavorite = useCallback((item) => favoriteIds.has(typeof item === 'object' ? item?.id : item), [favoriteIds]);\n\n // Load KLIPY categories once (errors ignored)\n useEffect(() => {\n const controller = new AbortController();\n fetchGifCategories({ signal: controller.signal })\n .then((cats) => { if (!controller.signal.aborted && Array.isArray(cats)) setKlipyCats(cats); })\n .catch(() => {});\n return () => controller.abort();\n }, []);\n\n const categories = useMemo(() => mergeKlipyCategories(GIF_CATEGORIES, klipyCats), [klipyCats]);\n const activeCategory = useMemo(\n () => categories.find((c) => c.id === categoryId) ?? categories[0],\n [categories, categoryId],\n );\n\n const trimmedQuery = query.trim();\n const source = trimmedQuery ? 'search' : (activeCategory?.source ?? 'trending');\n const feedQuery = trimmedQuery || activeCategory?.query || '';\n const libraryKey = source === 'favorites' ? (favorites?.length ?? 0) : source === 'recent' ? (recents?.length ?? 0) : 0;\n\n const feedRef = useRef({ source, query: feedQuery });\n feedRef.current = { source, query: feedQuery };\n\n const loadPage = useCallback(async (pageNum, append) => {\n requestRef.current?.abort();\n const controller = new AbortController();\n requestRef.current = controller;\n const version = ++versionRef.current;\n const { source: src, query: q } = feedRef.current;\n setLoading(true);\n setError('');\n try {\n const result = await loadGifFeed({ source: src, query: q, page: pageNum, perPage: PER_PAGE, signal: controller.signal });\n if (version !== versionRef.current) return;\n const safe = (result?.items || []).filter(isSafeGif);\n setItems((prev) => [...new Map([...(append ? prev : []), ...safe].map((g) => [g.id, g])).values()]);\n setHasMore(Boolean(result?.hasMore));\n setNotice(result?.notice || '');\n setPage(pageNum);\n } catch (err) {\n if (err?.name !== 'AbortError' && version === versionRef.current) setError('Error cargando GIFs. Intenta de nuevo.');\n } finally {\n if (version === versionRef.current) setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n requestRef.current?.abort();\n versionRef.current++;\n setItems([]);\n setHasMore(false);\n setError('');\n setNotice('');\n setLoading(true);\n const delay = source === 'search' ? SEARCH_DEBOUNCE_MS : 0;\n const timer = setTimeout(() => loadPage(1, false), delay);\n return () => { clearTimeout(timer); requestRef.current?.abort(); };\n }, [source, feedQuery, libraryKey, loadPage]);\n\n const handleLoadMore = useCallback(() => {\n if (loading || !hasMore || error) return;\n loadPage(page + 1, true);\n }, [loading, hasMore, error, page, loadPage]);\n\n const handleRetry = useCallback(() => {\n if (items.length) loadPage(page + 1, true);\n else loadPage(1, false);\n }, [items.length, page, loadPage]);\n\n const handleCategorySelect = useCallback((id) => {\n setQuery('');\n setCategoryId(id);\n }, []);\n\n const handleKeyDown = (e) => {\n if (e.key === 'Escape' && query) {\n e.preventDefault();\n e.stopPropagation();\n setQuery('');\n }\n };\n\n const handleSelect = (gif) => {\n if (disabled || !gif || !isTrustedKlipyUrl(gif.url)) return;\n onSelect?.({\n kind: 'gif',\n id: gif.id,\n slug: gif.slug,\n title: gif.title,\n preview: gif.preview,\n url: gif.url,\n name: gif.title || 'GIF',\n type: 'image/gif',\n size: 0,\n // KLIPY share is registered by the chat only after the message is sent.\n shareQuery: source === 'search' ? trimmedQuery : (source === 'trending' ? '' : feedQuery),\n });\n useGifLibrary.getState().addRecent(gif);\n onClose?.();\n };\n\n const handleToggleFavorite = useCallback((item) => {\n if (disabled || !item) return;\n toggleFavorite(item);\n }, [disabled, toggleFavorite]);\n\n const empty = getEmptyState(source, trimmedQuery);\n\n return (\n <div className=\"chat-gif-picker chat-gif-picker--smart\" role=\"dialog\" aria-label=\"Buscar GIFs\">\n <div className=\"chat-gif-picker-header\">\n <strong>Buscar GIFs</strong>\n <button type=\"button\" className=\"chat-btn\" aria-label=\"Cerrar selector GIF\" onClick={onClose}><X size={16} /></button>\n </div>\n <div className=\"chat-gif-search\">\n <Search size={18} aria-hidden=\"true\" />\n <input\n type=\"search\"\n autoFocus\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Busca memes, reacciones… (ej. cuánta bendición)\"\n disabled={disabled}\n aria-label=\"Buscar GIFs\"\n autoComplete=\"off\"\n enterKeyHint=\"search\"\n />\n {query && (\n <button\n type=\"button\"\n className=\"chat-gif-search__clear\"\n aria-label=\"Borrar búsqueda\"\n onClick={() => setQuery('')}\n disabled={disabled}\n >\n <X size={14} aria-hidden=\"true\" />\n </button>\n )}\n </div>\n <GifCategoryBar\n categories={categories}\n activeId={trimmedQuery ? null : activeCategory?.id ?? null}\n onSelect={handleCategorySelect}\n disabled={disabled}\n />\n {notice && <p className=\"chat-gif-notice\" role=\"status\">{notice}</p>}\n <GifGrid\n items={items}\n loading={loading}\n hasMore={hasMore}\n error={error}\n onLoadMore={handleLoadMore}\n onRetry={handleRetry}\n onSelect={handleSelect}\n onToggleFavorite={handleToggleFavorite}\n isFavorite={isFavorite}\n empty={empty}\n disabled={disabled}\n scrollKey={`${source}:${feedQuery}`}\n />\n <p className=\"chat-gif-attribution\">\n Powered by <a href=\"https://klipy.com\" target=\"_blank\" rel=\"noopener noreferrer\">KLIPY</a>\n </p>\n </div>\n );\n}\n","import { getKlipyApiRoot, isTrustedKlipyUrl } from './klipy.js';\nimport { getKlipyCustomerId } from './klipyCustomer.js';\nimport { STICKER_NAME_PREFIX } from '../../core/extras/messageExtras.js';\n\nconst getStickersUrl = () => `${getKlipyApiRoot()}/stickers`;\nconst PREVIEW_SIZES = ['sm', 'xs', 'md', 'hd'];\nconst FULL_SIZES = ['md', 'hd', 'sm'];\nconst FORMATS = ['gif', 'webp'];\nconst ERROR_MESSAGE = 'Error consultando KLIPY';\n\nlet categoriesCache = null;\n\nexport function getStickerCustomerId() {\n return getKlipyCustomerId();\n}\n\nconst pickMedia = (file, sizes) => {\n for (const size of sizes) {\n for (const format of FORMATS) {\n const media = file?.[size]?.[format];\n if (isTrustedKlipyUrl(media?.url)) return media;\n }\n }\n return null;\n};\n\nconst normalizeItem = (item) => {\n if (!item || item.type === 'ad') return null;\n const full = pickMedia(item.file, FULL_SIZES);\n const preview = pickMedia(item.file, PREVIEW_SIZES) || full;\n if (!full || !preview) return null;\n return {\n id: item.id,\n slug: item.slug,\n title: item.title || '',\n preview: preview.url,\n url: full.url,\n width: Number(full.width) || null,\n height: Number(full.height) || null,\n };\n};\n\nconst request = async (path, params, signal) => {\n const query = params ? `?${new URLSearchParams(params)}` : '';\n const response = await fetch(`${getStickersUrl()}${path}${query}`, { signal });\n if (!response.ok) throw new Error(ERROR_MESSAGE);\n return response.json();\n};\n\nconst toPage = (json, perPage) => {\n const raw = Array.isArray(json?.data?.data) ? json.data.data : [];\n const items = raw.map(normalizeItem).filter(Boolean);\n const hasNext = json?.data?.has_next;\n return {\n items,\n hasMore: typeof hasNext === 'boolean' ? hasNext : raw.length >= perPage,\n };\n};\n\nconst pageParams = (page, perPage) => ({\n page: String(page),\n per_page: String(perPage),\n});\n\nexport async function fetchTrendingStickers({ page = 1, perPage = 24, signal } = {}) {\n const json = await request('/trending', {\n ...pageParams(page, perPage),\n customer_id: getStickerCustomerId(),\n }, signal);\n return toPage(json, perPage);\n}\n\nexport async function searchStickers({ query, page = 1, perPage = 24, signal } = {}) {\n const q = String(query ?? '').trim();\n if (!q) return fetchTrendingStickers({ page, perPage, signal });\n const json = await request('/search', {\n ...pageParams(page, perPage),\n q,\n customer_id: getStickerCustomerId(),\n }, signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchRecentStickers({ page = 1, perPage = 24, signal } = {}) {\n const customerId = encodeURIComponent(getStickerCustomerId());\n const json = await request(`/recent/${customerId}`, pageParams(page, perPage), signal);\n return toPage(json, perPage);\n}\n\nexport async function fetchStickerCategories({ signal } = {}) {\n if (categoriesCache) return categoriesCache;\n const json = await request('/categories', null, signal);\n const raw = json?.data?.categories ?? json?.data?.data ?? json?.data ?? [];\n const list = Array.isArray(raw) ? raw : [];\n const categories = list\n .map((entry) => {\n if (typeof entry === 'string') {\n const name = entry.trim();\n return name ? { category: name, query: name, preview: null } : null;\n }\n const category = String(entry?.category ?? entry?.name ?? entry?.title ?? '').trim();\n const query = String(entry?.query ?? entry?.q ?? category).trim();\n if (!category || !query) return null;\n const previewUrl = entry?.preview_url ?? entry?.preview ?? entry?.image;\n return { category, query, preview: isTrustedKlipyUrl(previewUrl) ? previewUrl : null };\n })\n .filter(Boolean);\n categoriesCache = categories;\n return categories;\n}\n\nexport async function shareSticker(slug, { query } = {}) {\n if (!slug) return false;\n try {\n const body = { customer_id: getStickerCustomerId() };\n const q = String(query ?? '').trim();\n if (q) body.q = q;\n const response = await fetch(`${getStickersUrl()}/share/${encodeURIComponent(slug)}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport function toStickerAttachment(item) {\n return {\n kind: 'gif',\n id: item.id,\n slug: item.slug,\n title: item.title,\n preview: item.preview,\n url: item.url,\n name: STICKER_NAME_PREFIX + (item.title || 'Sticker').slice(0, 140),\n type: 'image/gif',\n size: 0,\n sticker: true,\n };\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { X, Loader2, Search } from 'lucide-react';\nimport {\n fetchTrendingStickers,\n searchStickers,\n fetchStickerCategories,\n fetchRecentStickers,\n toStickerAttachment,\n} from '../../media/klipy/klipyStickers';\nimport '../styles/StickerPicker.css';\n\nconst PER_PAGE = 24;\nconst SEARCH_DEBOUNCE_MS = 300;\n\nconst EMPTY_TEXT = {\n trending: 'No hay stickers en tendencia',\n recent: 'No hay stickers recientes todavía',\n category: 'No se encontraron stickers',\n search: 'No se encontraron stickers',\n};\n\nconst requestFor = (mode, term, page, signal) => {\n if (mode === 'recent') return fetchRecentStickers({ page, perPage: PER_PAGE, signal });\n if (mode === 'trending') return fetchTrendingStickers({ page, perPage: PER_PAGE, signal });\n return searchStickers({ query: term, page, perPage: PER_PAGE, signal });\n};\n\nexport default function StickerPicker({ onSelect, onClose, disabled }) {\n const [query, setQuery] = useState('');\n const [mode, setMode] = useState('trending');\n const [activeCategory, setActiveCategory] = useState(null);\n const [categories, setCategories] = useState([]);\n const [stickers, setStickers] = useState([]);\n const [loading, setLoading] = useState(false);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState('');\n const [previewItem, setPreviewItem] = useState(null);\n const gridRef = useRef(null);\n const requestRef = useRef(null);\n const versionRef = useRef(0);\n const loadMoreRef = useRef(null);\n const prevTabRef = useRef({ mode: 'trending', category: null });\n\n const term = mode === 'search'\n ? query.trim()\n : mode === 'category' ? (activeCategory?.query || '') : '';\n\n const loadStickers = useCallback(async (loadMode, loadTerm, pageNum = 1, append = false) => {\n requestRef.current?.abort();\n const controller = new AbortController();\n requestRef.current = controller;\n const version = ++versionRef.current;\n setLoading(true);\n setError('');\n try {\n const { items = [], hasMore: more = false } = await requestFor(loadMode, loadTerm, pageNum, controller.signal) || {};\n if (version !== versionRef.current) return;\n setStickers(prev => [...new Map([...(append ? prev : []), ...items].map(item => [item.id, item])).values()]);\n setHasMore(Boolean(more) && items.length > 0);\n setPage(pageNum);\n } catch (err) {\n if (err?.name !== 'AbortError' && version === versionRef.current) {\n setError(loadMode === 'recent' ? 'Recientes no disponible.' : 'Error cargando stickers. Intenta de nuevo.');\n setHasMore(false);\n }\n } finally {\n if (version === versionRef.current) setLoading(false);\n }\n }, []);\n\n // Categories load once.\n useEffect(() => {\n const controller = new AbortController();\n fetchStickerCategories({ signal: controller.signal })\n .then(list => { if (Array.isArray(list)) setCategories(list.filter(c => c?.query)); })\n .catch(() => {});\n return () => controller.abort();\n }, []);\n\n // Reload whenever mode/term changes; only searches are debounced.\n useEffect(() => {\n requestRef.current?.abort();\n versionRef.current++;\n setStickers([]);\n setHasMore(false);\n setPreviewItem(null);\n setError('');\n setLoading(true);\n const timer = setTimeout(() => {\n gridRef.current?.scrollTo({ top: 0 });\n loadStickers(mode, term, 1, false);\n }, mode === 'search' ? SEARCH_DEBOUNCE_MS : 0);\n return () => { clearTimeout(timer); requestRef.current?.abort(); };\n }, [mode, term, loadStickers]);\n\n // Infinite scroll.\n useEffect(() => {\n if (!hasMore || loading || error) return undefined;\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadStickers(mode, term, page + 1, true);\n }, { root: gridRef.current, rootMargin: '80px' });\n if (loadMoreRef.current) observer.observe(loadMoreRef.current);\n return () => observer.disconnect();\n }, [hasMore, loading, error, page, mode, term, loadStickers]);\n\n const handleQueryChange = (value) => {\n setQuery(value);\n if (value.trim()) {\n if (mode !== 'search') {\n prevTabRef.current = { mode, category: activeCategory };\n setMode('search');\n }\n } else if (mode === 'search') {\n setActiveCategory(prevTabRef.current.category);\n setMode(prevTabRef.current.mode || 'trending');\n }\n };\n\n const selectTab = (nextMode, category = null) => {\n setQuery('');\n setActiveCategory(category);\n setMode(nextMode);\n };\n\n const handleSelect = (item) => {\n if (disabled || !item) return;\n // KLIPY share is registered by the chat only after the message is sent.\n onSelect?.({ ...toStickerAttachment(item), shareQuery: term || '' });\n onClose?.();\n };\n\n const handleGridKeyDown = (e) => {\n const keys = ['ArrowRight', 'ArrowLeft', 'ArrowDown', 'ArrowUp', 'Home', 'End'];\n if (!keys.includes(e.key)) return;\n const items = Array.from(gridRef.current?.querySelectorAll('.chat-sticker-item') || []);\n const index = items.indexOf(document.activeElement);\n if (index === -1 || !items.length) return;\n const firstTop = items[0].offsetTop;\n const columns = Math.max(1, items.findIndex(el => el.offsetTop !== firstTop) === -1\n ? items.length\n : items.findIndex(el => el.offsetTop !== firstTop));\n let next = index;\n if (e.key === 'ArrowRight') next = index + 1;\n else if (e.key === 'ArrowLeft') next = index - 1;\n else if (e.key === 'ArrowDown') next = index + columns;\n else if (e.key === 'ArrowUp') next = index - columns;\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = items.length - 1;\n e.preventDefault();\n next = Math.min(items.length - 1, Math.max(0, next));\n items[next]?.focus();\n };\n\n const isTabSelected = (tabMode, category = null) => (\n mode === tabMode && (tabMode !== 'category' || activeCategory?.query === category?.query)\n );\n\n return (\n <div className=\"chat-gif-picker chat-sticker-picker\" role=\"dialog\" aria-label=\"Buscar stickers\">\n <div className=\"chat-gif-picker-header\">\n <strong>Stickers</strong>\n <button type=\"button\" className=\"chat-btn\" aria-label=\"Cerrar selector de stickers\" onClick={onClose}><X size={16} /></button>\n </div>\n <div className=\"chat-gif-search\">\n <Search size={18} aria-hidden=\"true\" />\n <input\n type=\"search\"\n autoFocus\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder=\"Buscar stickers (ej. hola, gato, gracias)...\"\n disabled={disabled}\n aria-label=\"Buscar stickers\"\n />\n </div>\n <div className=\"chat-sticker-tabs\" role=\"tablist\" aria-label=\"Categorías de stickers\">\n <button\n type=\"button\"\n role=\"tab\"\n className=\"chat-sticker-tab\"\n aria-selected={isTabSelected('trending')}\n onClick={() => selectTab('trending')}\n disabled={disabled}\n >\n Tendencias\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n className=\"chat-sticker-tab\"\n aria-selected={isTabSelected('recent')}\n onClick={() => selectTab('recent')}\n disabled={disabled}\n >\n Recientes\n </button>\n {categories.map((cat) => (\n <button\n key={cat.query}\n type=\"button\"\n role=\"tab\"\n className=\"chat-sticker-tab chat-sticker-chip\"\n aria-selected={isTabSelected('category', cat)}\n onClick={() => selectTab('category', cat)}\n disabled={disabled}\n title={cat.category}\n >\n {cat.preview && <img src={cat.preview} alt=\"\" aria-hidden=\"true\" loading=\"lazy\" />}\n <span>{cat.category}</span>\n </button>\n ))}\n </div>\n {error && (\n <div className=\"chat-attachment-notice\" role=\"alert\">\n {error}{' '}\n <button type=\"button\" onClick={() => loadStickers(mode, term, stickers.length ? page + 1 : 1, stickers.length > 0)}>Reintentar</button>\n </div>\n )}\n <div\n ref={gridRef}\n className=\"chat-gif-grid chat-sticker-grid\"\n role=\"list\"\n aria-label=\"Resultados de stickers\"\n onKeyDown={handleGridKeyDown}\n >\n {stickers.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n className=\"chat-sticker-item\"\n role=\"listitem\"\n onClick={() => handleSelect(item)}\n onMouseEnter={() => setPreviewItem(item)}\n onFocus={() => setPreviewItem(item)}\n disabled={disabled}\n aria-label={item.title || 'Sticker'}\n >\n <img src={item.preview} alt={item.title || 'Sticker'} loading=\"lazy\" />\n </button>\n ))}\n {(hasMore || loading) && (\n <div ref={loadMoreRef} className=\"chat-gif-load-more\" aria-hidden=\"true\">\n {loading && <Loader2 size={24} className=\"spin\" />}\n </div>\n )}\n {!stickers.length && !loading && !error && (\n <p className=\"chat-gif-empty\">{EMPTY_TEXT[mode]}</p>\n )}\n </div>\n <div className=\"chat-sticker-preview\" aria-live=\"polite\">\n {previewItem ? (\n <>\n <img src={previewItem.url || previewItem.preview} alt={previewItem.title || 'Sticker'} />\n <span>{previewItem.title || 'Sticker'}</span>\n </>\n ) : (\n <span className=\"chat-sticker-preview-hint\">Pasa el cursor sobre un sticker para verlo</span>\n )}\n </div>\n <p className=\"chat-gif-attribution\">\n Powered by <a href=\"https://klipy.com\" target=\"_blank\" rel=\"noopener noreferrer\">KLIPY</a>\n </p>\n </div>\n );\n}\n","// Exact, familiar emoticons take priority over name searches, without a catalog load.\nconst faces = [\n [[':)', ':-)'], '🙂', 'slightly_smiling_face', 'Cara sonriente'],\n [[':D', ':-D'], '😄', 'smile', 'Sonrisa grande'],\n [[':O', ':-O'], '😮', 'open_mouth', 'Cara de asombro'],\n [[':/', ':-/', ':\\\\', ':-\\\\'], '😕', 'confused', 'Cara confundida'],\n [[':(', ':-('], '🙁', 'slightly_frowning_face', 'Cara triste'],\n [[';)', ';-)'], '😉', 'wink', 'Guiño'],\n [[':P', ':-P'], '😛', 'stuck_out_tongue', 'Sacando la lengua'],\n [[':*', ':-*'], '😘', 'kissing_heart', 'Beso'],\n [[':|', ':-|'], '😐', 'neutral_face', 'Cara neutral'],\n [[\":'(\"], '😢', 'cry', 'Cara llorando'],\n [['<3'], '❤️', 'heart', 'Corazón'],\n];\nconst shortcuts = new Map(faces.flatMap(([aliases, emoji, shortcode, label]) => aliases.map(alias => [alias.toLowerCase(), { emoji, shortcode, label, source: 'unicode' }])));\n\nexport function findEmojiToken(text, cursor = text.length) {\n const prefix = text.slice(0, cursor);\n const match = /(^|[^\\p{L}\\p{N}_/:\\\\])([:;<][^\\s]{1,32})$/u.exec(prefix);\n if (!match) return null;\n const token = match[2];\n const start = match.index + match[1].length;\n const face = shortcuts.get(token.toLowerCase());\n if (face) return { start, shortcode: token.slice(1), emoticon: { ...face, emoticon: token } };\n if (/^:[\\p{L}\\p{N}_+\\p{M}-]{1,32}$/u.test(token)) return { start, shortcode: token.slice(1) };\n return null;\n}\n","/* eslint-disable react/prop-types */\nimport { useEffect, useRef, useState, useCallback, useId, useMemo } from 'react';\nimport MessageText from './MessageText';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nimport { searchCustomEmojis } from '../../media/emoji/customEmojiCatalog';\nimport { searchEmojiShortcodes, applySkinTone } from '../../media/emoji/emojiShortcodes';\nimport { useEmojiPreferences } from '../../media/emoji/emojiPreferences';\nimport { useEmojiDataReady } from '../../media/emoji/useEmojiData';\nimport { findEmojiToken } from '../../media/emoji/emojiAutocompleteToken.js';\nimport '../styles/EmojiPicker.css';\n\nconst RESULT_LIMIT = 8;\nconst RECENT_POOL_LIMIT = 48;\n\nconst recentValue = (recent) => (typeof recent === 'string' ? recent : recent?.emoji || '');\nconst stripVariation = (text) => String(text || '').replace(/️/g, '');\n\nconst foldText = (text) => String(text).normalize('NFD').replace(/\\p{M}/gu, '').toLowerCase();\n\n// Wrap the matched prefix of the shortcode in <mark>.\nfunction HighlightedShortcode({ shortcode, query }) {\n const folded = foldText(shortcode);\n const q = foldText(query);\n if (q && folded.startsWith(q)) {\n return <>:<mark className=\"chat-emoji-autocomplete-match\">{shortcode.slice(0, q.length)}</mark>{shortcode.slice(q.length)}:</>;\n }\n const at = q ? folded.indexOf(q) : -1;\n if (at > 0 && /[_+-]/.test(folded[at - 1])) {\n return <>:{shortcode.slice(0, at)}<mark className=\"chat-emoji-autocomplete-match\">{shortcode.slice(at, at + q.length)}</mark>{shortcode.slice(at + q.length)}:</>;\n }\n return <>:{shortcode}:</>;\n}\n\nexport default function EmojiAutocomplete({\n textareaRef,\n value,\n onInsert,\n onClose,\n isOpen\n}) {\n const customRecords = useCustomEmojis();\n const [suggestions, setSuggestions] = useState([]);\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [query, setQuery] = useState('');\n const dropdownRef = useRef(null);\n const shortcodeStartRef = useRef(-1);\n const prefs = useEmojiPreferences() || {};\n const { skinTone, recents, addRecent } = prefs;\n // Mounted with the composer: starts the lazy emoji catalog load early (also used by resolveEmojiShortcode).\n const emojiReady = useEmojiDataReady();\n const baseId = useId().replace(/:/g, '');\n const listId = `chat-emoji-ac-${baseId}`;\n const optionId = (index) => `${listId}-opt-${index}`;\n\n const valueFor = useCallback((record) => (\n record.source === 'custom' ? record.emoji : (applySkinTone(record, skinTone) || record.emoji)\n ), [skinTone]);\n\n const recentList = useMemo(\n () => (Array.isArray(recents) ? recents.map(recentValue).filter(Boolean) : []),\n [recents]\n );\n\n // Update suggestions based on current textarea state\n useEffect(() => {\n if (!isOpen || !textareaRef.current) {\n setSuggestions([]);\n return;\n }\n\n const textarea = textareaRef.current;\n const cursorPos = textarea.selectionStart;\n const found = findEmojiToken(value, cursorPos);\n\n if (!found || found.shortcode.length === 0) {\n setSuggestions([]);\n onClose();\n return;\n }\n\n const search = (query, limit) => [...searchCustomEmojis(customRecords, query), ...searchEmojiShortcodes(query, { limit })].slice(0, limit);\n let results;\n if (found.emoticon) {\n results = [found.emoticon];\n } else if (found.shortcode.length === 1 && recentList.length) {\n // Boost matching recents (most recent first) for very short queries.\n const pool = search(found.shortcode, RECENT_POOL_LIMIT);\n const rank = (record) => {\n const candidates = [stripVariation(record.emoji), stripVariation(valueFor(record))];\n const idx = recentList.findIndex((recent) => candidates.includes(stripVariation(recent)));\n return idx === -1 ? Infinity : idx;\n };\n const ranked = pool.map((record, order) => ({ record, order, recent: rank(record) }));\n ranked.sort((a, b) => (a.recent === b.recent ? a.order - b.order : a.recent - b.recent));\n results = ranked.slice(0, RESULT_LIMIT).map(({ record }) => record);\n } else {\n results = search(found.shortcode, RESULT_LIMIT);\n }\n\n if (!results.length) {\n setSuggestions([]);\n onClose();\n return;\n }\n\n shortcodeStartRef.current = found.start;\n setQuery(found.shortcode);\n setSuggestions(results);\n setSelectedIndex(0);\n }, [value, isOpen, textareaRef, onClose, recentList, valueFor, emojiReady, customRecords]);\n\n const insertEmoji = useCallback((record) => {\n const textarea = textareaRef.current;\n if (!textarea || !record) return;\n const start = shortcodeStartRef.current;\n if (start < 0) return;\n const end = textarea.selectionStart;\n const emoji = valueFor(record);\n\n onInsert(value.substring(0, start) + emoji + value.substring(end));\n addRecent?.(emoji);\n\n setTimeout(() => {\n textarea.focus();\n const newPos = start + emoji.length;\n textarea.setSelectionRange(newPos, newPos);\n }, 0);\n\n onClose();\n }, [textareaRef, value, onInsert, onClose, addRecent, valueFor]);\n\n const active = isOpen && suggestions.length > 0;\n\n // Keyboard navigation in capture phase so it beats the composer's Enter-to-send.\n useEffect(() => {\n const node = textareaRef.current;\n if (!node || !active) return undefined;\n const count = suggestions.length;\n const stop = (event) => { event.preventDefault(); event.stopPropagation(); };\n const handleKeyDown = (event) => {\n if (event.isComposing || event.keyCode === 229) return;\n switch (event.key) {\n case 'ArrowDown':\n stop(event);\n setSelectedIndex((prev) => (prev + 1) % count);\n break;\n case 'ArrowUp':\n stop(event);\n setSelectedIndex((prev) => (prev - 1 + count) % count);\n break;\n case 'Home':\n stop(event);\n setSelectedIndex(0);\n break;\n case 'End':\n stop(event);\n setSelectedIndex(count - 1);\n break;\n case 'Enter':\n case 'Tab':\n if (event.shiftKey && event.key === 'Enter') return;\n stop(event);\n insertEmoji(suggestions[selectedIndex] || suggestions[0]);\n break;\n case 'Escape':\n stop(event);\n onClose();\n break;\n case 'ArrowLeft':\n case 'ArrowRight':\n onClose();\n break;\n default:\n break;\n }\n };\n const dismiss = () => onClose();\n node.addEventListener('keydown', handleKeyDown, true);\n node.addEventListener('click', dismiss);\n return () => {\n node.removeEventListener('keydown', handleKeyDown, true);\n node.removeEventListener('click', dismiss);\n };\n }, [textareaRef, active, suggestions, selectedIndex, insertEmoji, onClose]);\n\n // ARIA combobox wiring on the textarea while open.\n useEffect(() => {\n const node = textareaRef.current;\n if (!node) return undefined;\n if (active) {\n node.setAttribute('aria-expanded', 'true');\n node.setAttribute('aria-controls', listId);\n node.setAttribute('aria-autocomplete', 'list');\n node.setAttribute('aria-activedescendant', `${listId}-opt-${selectedIndex}`);\n } else {\n node.setAttribute('aria-expanded', 'false');\n node.removeAttribute('aria-controls');\n node.removeAttribute('aria-activedescendant');\n node.removeAttribute('aria-autocomplete');\n }\n return undefined;\n }, [textareaRef, active, listId, selectedIndex]);\n\n useEffect(() => () => {\n const node = textareaRef.current;\n if (!node) return;\n node.removeAttribute('aria-expanded');\n node.removeAttribute('aria-controls');\n node.removeAttribute('aria-activedescendant');\n node.removeAttribute('aria-autocomplete');\n }, [textareaRef]);\n\n useEffect(() => {\n if (!active) return;\n dropdownRef.current?.querySelector('[aria-selected=\"true\"]')?.scrollIntoView({ block: 'nearest', behavior: 'auto' });\n }, [selectedIndex, active, suggestions]);\n\n if (!active) return null;\n\n return (\n <div ref={dropdownRef} className=\"chat-emoji-autocomplete chat-emoji-autocomplete--modern\">\n <div className=\"chat-emoji-autocomplete-hint\">\n <span>Emojis que coinciden con <strong>:{query}</strong></span>\n <span aria-hidden=\"true\"><kbd>↑</kbd><kbd>↓</kbd> navegar · <kbd>Enter</kbd>/<kbd>Tab</kbd> elegir · <kbd>Esc</kbd> cerrar</span>\n </div>\n <div className=\"chat-emoji-autocomplete-list\" id={listId} role=\"listbox\" aria-label=\"Sugerencias de emoji\">\n {suggestions.map((suggestion, index) => {\n const selected = index === selectedIndex;\n const display = valueFor(suggestion);\n return (\n <div\n key={`${suggestion.source}-${suggestion.shortcode}-${index}`}\n id={optionId(index)}\n className={`chat-emoji-autocomplete-item${selected ? ' selected' : ''}`}\n role=\"option\"\n aria-selected={selected}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => insertEmoji(suggestion)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n <span className=\"chat-emoji-autocomplete-emoji\" aria-hidden=\"true\"><MessageText text={display} /></span>\n <span className=\"chat-emoji-autocomplete-text\">\n <span className=\"chat-emoji-autocomplete-shortcode\">{suggestion.emoticon || <HighlightedShortcode shortcode={suggestion.shortcode} query={query} />}</span>\n {suggestion.label && <span className=\"chat-emoji-autocomplete-label\">{suggestion.label}</span>}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { Paperclip, Smile, Clapperboard, Send, X, Mic, Square, GripHorizontal, Loader2, Gamepad2, Anchor, CircleDot, Box, Check, Sticker, Crosshair, Flag } from 'lucide-react';\nimport { EffectPicker } from '../../effects/ChatEffects.jsx';\nimport EmojiPicker from './EmojiPicker';\nimport MediaPreview from './MediaPreview';\nimport useVoiceRecorder from '../hooks/useVoiceRecorder';\nimport GifPicker from './GifPicker';\nimport StickerPicker from './StickerPicker';\nimport EmojiAutocomplete from './EmojiAutocomplete';\nimport { resolveEmojiShortcode } from '../../media/emoji/emojiShortcodes';\nimport { findEmojiToken } from '../../media/emoji/emojiAutocompleteToken.js';\nimport { useCustomEmojis } from '../../media/emoji/useCustomEmojis';\nimport { isStickerAttachment } from '../../core/extras/messageExtras';\nimport '../styles/gameMenu.css';\nimport { RACING_TRACKS } from '../../games/racing-live/logic/tracks/index.js';\n// Loaded eagerly as on master: the Battleship preview overlay renders in the shell before its lazy chunk.\nimport '../../games/battleship/battleship.css';\n\nconst DEFAULT_GAME_TYPES = ['connect4', 'battleship'];\nconst GAME_MENU = [\n { type: 'connect4', label: 'Conecta 4', Icon: CircleDot },\n { type: 'battleship', label: 'Batalla Naval', Icon: Anchor },\n { type: 'tanks', label: 'Tanques de guerra', Icon: Crosshair },\n { type: 'tanks_live', label: 'Tanques LIVE 3D', Icon: Crosshair },\n { type: 'racing_live', label: 'Carreras LIVE 🏎️', Icon: Flag },\n];\n// Carreras LIVE opens a class submenu; ids must match src/games/racing-live/logic/classes.js.\nconst RACE_CLASS_MENU = [\n { id: '50cc', hint: '~80 km/h' }, { id: '100cc', hint: '~130 km/h' }, { id: '200cc', hint: '~200 km/h · recomendada' },\n { id: '400cc', hint: '~300 km/h' }, { id: '500cc', hint: '~380 km/h' },\n];\n// Tanques LIVE opens map → lives submenus; ids must match src/games/tanks-live/logic/maps.js.\nconst TANK_MAP_MENU = [\n { id: 'random', label: 'Aleatorio 🎲', hint: 'recomendado' }, { id: 'meadow', label: 'Pradera 🌿', hint: 'clásico' },\n { id: 'forest', label: 'Bosque 🌲', hint: 'combate cercano' }, { id: 'desert', label: 'Desierto 🏜️', hint: 'abierto' },\n { id: 'ruins', label: 'Ciudad en ruinas 🏚️', hint: 'pasillos' }, { id: 'arctic', label: 'Ártico ❄️', hint: 'bloques de hielo' },\n];\nconst TANK_LIVES_MENU = [{ lives: 1, hint: 'muerte súbita' }, { lives: 3, hint: 'recomendado' }, { lives: 5, hint: 'partida larga' }];\n\nexport default function MessageComposer({ onSendEffect, value, onChange, onSend, disabled, attachments = [], attachmentError, sending = false, onAddAttachment, onRemoveAttachment, reply, onCancelReply, onInviteGame, gameInviteDisabled, gameTypes = DEFAULT_GAME_TYPES, onOpenBattleshipPreview, editing = null, onStartEditLast, onCancelEdit }) {\n const customEmojis = useCustomEmojis();\n const textareaRef = useRef(null);\n const composerRef = useRef(null);\n const [pickerHeight, setPickerHeight] = useState(520);\n const [pickerAvailableHeight, setPickerAvailableHeight] = useState(520);\n const pickerResizeRef = useRef(null);\n const fileInputRef = useRef(null);\n const gameMenuRef = useRef(null);\n const gameButtonRef = useRef(null);\n const [popover, setPopover] = useState(null);\n const [raceMenu, setRaceMenu] = useState(null); // null | 'track' | 'class'\n const [raceTrack, setRaceTrack] = useState('random');\n const [tankMenu, setTankMenu] = useState(null); // null | 'map' | 'lives'\n const [tankMap, setTankMap] = useState('random');\n const [autocompleteOpen, setAutocompleteOpen] = useState(false);\n const handleAutocompleteClose = useCallback(() => setAutocompleteOpen(false), []);\n const handleAutocompleteInsert = useCallback((next) => onChange(next), [onChange]);\n const voice = useVoiceRecorder(onAddAttachment);\n const recording = voice.status !== 'idle';\n const sendingMedia = attachments[0];\n const sendingTitle = isStickerAttachment(sendingMedia) ? 'Enviando sticker…'\n : sendingMedia?.kind === 'gif' ? 'Enviando GIF…'\n : sendingMedia?.type?.startsWith('audio/') ? 'Enviando audio…'\n : sendingMedia ? 'Enviando archivo…' : 'Enviando mensaje…';\n useEffect(() => { if (sending) { setPopover(null); setAutocompleteOpen(false); } }, [sending]);\n const canSend = editing ? !disabled && Boolean(value.trim()) : !disabled && (attachments.length > 0 || Boolean(value.trim()));\n const editingId = editing?.messageId;\n const pickerKind = popover === 'gif' || popover === 'sticker' ? popover : null;\n\n useEffect(() => { if (reply) { setPopover(null); setAutocompleteOpen(false); textareaRef.current?.focus(); } }, [reply]);\n\n // Entering edit mode: the parent fills `value`; focus and place the caret at the end.\n useEffect(() => {\n if (editingId == null) return undefined;\n setPopover(null); setAutocompleteOpen(false);\n const frame = requestAnimationFrame(() => { const node = textareaRef.current; if (!node) return; node.focus(); const end = node.value.length; node.setSelectionRange(end, end); });\n return () => cancelAnimationFrame(frame);\n }, [editingId]);\n\n useEffect(() => {\n const node = textareaRef.current;\n if (node) { node.style.height = 'auto'; node.style.height = `${Math.min(node.scrollHeight, 144)}px`; }\n }, [value]);\n\n useEffect(() => {\n const composer = composerRef.current;\n const parent = composer?.parentElement;\n if (!composer || !parent || (!popover && !autocompleteOpen)) return undefined;\n const resize = () => setPickerAvailableHeight(Math.max(60,\n composer.getBoundingClientRect().top - parent.getBoundingClientRect().top - 8));\n const observer = new ResizeObserver(resize);\n observer.observe(parent);\n observer.observe(composer);\n resize();\n return () => observer.disconnect();\n }, [popover, autocompleteOpen]);\n\n // Games menu: focus the first entry on open, close on outside pointer.\n useEffect(() => {\n if (popover !== 'games') { setRaceMenu(null); setTankMenu(null); return undefined; }\n gameMenuRef.current?.querySelector('[role=\"menuitem\"]:not(:disabled)')?.focus();\n const close = (event) => {\n if (gameMenuRef.current?.contains(event.target) || gameButtonRef.current?.contains(event.target)) return;\n setPopover(null);\n };\n document.addEventListener('pointerdown', close);\n return () => document.removeEventListener('pointerdown', close);\n }, [popover]);\n useEffect(() => {\n if (popover === 'games') gameMenuRef.current?.querySelector('[role=\"menuitem\"]:not(:disabled)')?.focus();\n }, [raceMenu, tankMenu]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const chooseGame = (action) => { setPopover(null); textareaRef.current?.focus(); action?.(); };\n const handleGameMenuKeyDown = (event) => {\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) return;\n event.preventDefault();\n const items = [...(gameMenuRef.current?.querySelectorAll('[role=\"menuitem\"]:not(:disabled)') || [])];\n const index = items.indexOf(document.activeElement);\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? items.length - 1\n : (index + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length;\n items[next]?.focus();\n };\n\n const handleKeyDown = useCallback((event) => {\n if (event.key === 'Escape' && popover) {\n event.preventDefault(); event.stopPropagation();\n const fromGames = popover === 'games';\n setPopover(null);\n (fromGames ? gameButtonRef.current : textareaRef.current)?.focus(); return;\n }\n if (event.key === 'Escape' && editing && !event.defaultPrevented && !autocompleteOpen) {\n event.preventDefault(); onCancelEdit?.(); return;\n }\n if (event.defaultPrevented || event.target !== textareaRef.current) return;\n if (event.key === 'ArrowUp' && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey\n && value === '' && !attachments.length && !event.nativeEvent.isComposing && event.keyCode !== 229\n && !popover && !autocompleteOpen && !recording && !sending && !editing) {\n event.preventDefault();\n if (onStartEditLast?.()) requestAnimationFrame(() => { const node = textareaRef.current; if (!node) return; node.focus(); const end = node.value.length; node.setSelectionRange(end, end); });\n return;\n }\n if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing && event.keyCode !== 229) {\n event.preventDefault();\n if (canSend && !recording) onSend();\n }\n }, [popover, canSend, recording, onSend, editing, onCancelEdit, onStartEditLast, autocompleteOpen, value, attachments.length, sending]);\n\n const handlePaste = useCallback((event) => {\n const files = Array.from(event.clipboardData?.files || []);\n if (!files.length) {\n for (const item of Array.from(event.clipboardData?.items || [])) {\n if (item.kind === 'file') { const file = item.getAsFile(); if (file) files.push(file); }\n }\n }\n if (files.length) { event.preventDefault(); files.forEach((file) => onAddAttachment?.(file)); }\n }, [onAddAttachment]);\n\n const handleInputChange = useCallback((event) => {\n const newValue = event.target.value;\n const caret = event.target.selectionStart;\n // Commit an exact shortcode on space or closing colon, without sending.\n // Keep partial tokens editable, including longer aliases such as :detective_woman.\n const completed = /(^|[^\\p{L}\\p{N}_]):([\\p{L}\\p{N}\\p{M}_+-]{1,64})(:| )$/u.exec(newValue.slice(0, caret));\n if (!event.nativeEvent.isComposing && completed && event.nativeEvent.inputType !== 'insertFromPaste') {\n const emoji = customEmojis.find((item) => item.shortcode === completed[2].toLowerCase())?.emoji || resolveEmojiShortcode(completed[2]);\n if (emoji) {\n const start = completed.index + completed[1].length;\n const suffix = completed[3] === ' ' ? ' ' : '';\n onChange(newValue.slice(0, start) + emoji + suffix + newValue.slice(caret));\n setAutocompleteOpen(false);\n setPopover(null);\n requestAnimationFrame(() => textareaRef.current?.setSelectionRange(start + emoji.length + suffix.length, start + emoji.length + suffix.length));\n return;\n }\n }\n onChange(newValue);\n if (popover) setPopover(null);\n \n setAutocompleteOpen(Boolean(findEmojiToken(newValue, caret)));\n }, [onChange, popover, customEmojis]);\n\n return (\n <div ref={composerRef} className={`chat-composer${editing ? ' chat-composer--editing' : ''}`} style={{ '--chat-picker-available-height': `${pickerAvailableHeight}px` }} onKeyDown={handleKeyDown}\n onPaste={handlePaste} onDragOver={(event) => event.preventDefault()}\n onDrop={(event) => { event.preventDefault(); Array.from(event.dataTransfer.files).forEach((file) => onAddAttachment?.(file)); }}>\n <input ref={fileInputRef} type=\"file\" multiple hidden onChange={(event) => { Array.from(event.target.files || []).forEach((file) => onAddAttachment?.(file)); event.target.value = ''; }} />\n {sending && <div className=\"chat-send-status\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n <div className=\"chat-send-status-body\">\n <span className=\"chat-send-status-icon\"><Loader2 size={23} className=\"chat-send-spinner\" aria-hidden=\"true\" /></span>\n <div className=\"chat-send-status-copy\"><strong>{sendingTitle}</strong>\n {sendingMedia?.name && <span className=\"chat-send-status-file\" title={sendingMedia.name}>{sendingMedia.name}</span>}\n <small>Mantén esta conversación abierta hasta que termine.</small>\n </div>\n </div>\n <div className=\"chat-send-status-track\" aria-hidden=\"true\"><span /></div>\n </div>}\n {attachmentError && <div className=\"chat-attachment-notice\" role=\"alert\">{attachmentError}</div>}\n {voice.error && <div className=\"chat-attachment-notice\" role=\"alert\">{voice.error}</div>}\n {editing && <div className=\"chat-reply-preview chat-edit-preview\"><div><strong>Editando mensaje</strong><span>{String(editing.original?.message || editing.original?.text || '').slice(0, 180)}</span><small>Enter para guardar · Esc para cancelar</small></div><button type=\"button\" className=\"chat-btn\" onClick={onCancelEdit} aria-label=\"Cancelar edición\"><X size={16} /></button></div>}\n {reply && !editing && <div className=\"chat-reply-preview\"><div><strong>Respuesta a {reply.username || 'Usuario'}</strong><span>{String(reply.message || reply.text || '[Archivo adjunto]').slice(0, 180)}</span><small>Se enviará como cita de texto</small></div><button type=\"button\" className=\"chat-btn\" onClick={onCancelReply} aria-label=\"Cancelar respuesta\"><X size={16} /></button></div>}\n <MediaPreview items={attachments} onRemove={sending ? undefined : onRemoveAttachment} />\n <div className=\"chat-composer-top\">\n <textarea ref={textareaRef} className=\"chat-composer-textarea\" value={value} onChange={handleInputChange}\n readOnly={disabled} aria-label=\"Mensaje\" placeholder=\"Escribe un mensaje…\" rows={1} spellCheck />\n </div>\n {recording && <div className=\"chat-voice-recording\" role=\"status\">\n <span className=\"chat-recording-indicator\" />\n <span>{voice.status === 'requesting' ? 'Esperando permiso del micrófono…' : `Grabando ${Math.floor(voice.seconds / 60)}:${String(voice.seconds % 60).padStart(2, '0')} / 2:00`}</span>\n {voice.status === 'recording' && <button type=\"button\" className=\"chat-composer-btn\" onClick={voice.stop} aria-label=\"Terminar grabación y previsualizar\" title=\"Terminar y previsualizar\"><Square size={16} /></button>}\n <button type=\"button\" className=\"chat-composer-btn\" onClick={voice.cancel} aria-label=\"Cancelar grabación\" title=\"Cancelar grabación\"><X size={16} /></button>\n </div>}\n <div className=\"chat-composer-bottom\">\n <div className=\"chat-composer-actions\">\n {(onInviteGame || onOpenBattleshipPreview) && <button ref={gameButtonRef} type=\"button\" className=\"chat-composer-btn\"\n disabled={sending || Boolean(editing) || (gameInviteDisabled && !onOpenBattleshipPreview)}\n onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'games' ? null : 'games'); }}\n aria-label=\"Juegos\" aria-haspopup=\"menu\" aria-expanded={popover === 'games'} title=\"Invitar a jugar\"><Gamepad2 size={18} /></button>}\n {onSendEffect && <button type=\"button\" className=\"chat-composer-btn\" disabled={disabled || Boolean(editing)} onClick={() => setPopover(popover === 'effects' ? null : 'effects')} aria-label=\"Efectos y zumbidos\" aria-expanded={popover === 'effects'} title=\"Efectos y zumbidos\">✨</button>}\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending || Boolean(editing)} onClick={() => fileInputRef.current?.click()} aria-label=\"Adjuntar archivos\" title=\"Adjuntar archivos\"><Paperclip size={18} /></button>\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending} onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'emoji' ? null : 'emoji'); }} aria-label=\"Emojis\" aria-expanded={popover === 'emoji'} title=\"Emojis\"><Smile size={18} /></button>\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending || Boolean(editing)} onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'gif' ? null : 'gif'); }} aria-label=\"Buscar GIFs\" aria-expanded={popover === 'gif'} title=\"Buscar GIFs\"><Clapperboard size={18} /></button>\n <button type=\"button\" className=\"chat-composer-btn\" disabled={sending || Boolean(editing)} onClick={() => { setAutocompleteOpen(false); setPopover(popover === 'sticker' ? null : 'sticker'); }} aria-label=\"Stickers\" aria-expanded={popover === 'sticker'} title=\"Stickers\"><Sticker size={18} /></button>\n <button type=\"button\" className={`chat-composer-btn ${recording ? 'is-active' : ''}`} onClick={voice.start} disabled={recording || sending || Boolean(editing)} aria-label=\"Grabar nota de voz\" title=\"Grabar nota de voz\"><Mic size={18} /></button>\n </div>\n <span className=\"chat-composer-hint\">{sending ? 'Enviando…' : editing ? 'Enter para guardar · Esc para cancelar' : attachments.length ? 'Máx. 10 MB · temporal, sin historial' : disabled ? 'Sin conexión · prepara tus archivos' : 'Enter para enviar · Shift+Enter nueva línea'}</span>\n <button type=\"button\" className=\"chat-composer-send\" onClick={() => { if (canSend && !recording) onSend(); }} disabled={!canSend || recording}\n aria-label={sending ? 'Enviando mensaje' : editing ? 'Guardar edición' : 'Enviar mensaje'} aria-busy={sending} title={sending ? 'Enviando…' : editing ? 'Guardar edición' : 'Enviar mensaje'}>{sending ? <Loader2 size={18} className=\"chat-send-spinner\" aria-hidden=\"true\" /> : editing ? <Check size={17} /> : <Send size={17} />}</button>\n </div>\n {popover === 'games' && <div ref={gameMenuRef} className=\"chat-game-menu\" role=\"menu\" aria-label=\"Juegos\" onKeyDown={handleGameMenuKeyDown}\n onBlur={(event) => {\n // Close when keyboard focus leaves (e.g. Tab). A null relatedTarget is left to the\n // outside-pointer handler so Safari's non-focusing button clicks still reach the item.\n const next = event.relatedTarget;\n if (!next || gameMenuRef.current?.contains(next) || gameButtonRef.current?.contains(next)) return;\n setPopover(null);\n }}>\n {onInviteGame && raceMenu === 'track' && <>\n <span className=\"chat-game-menu-title\">Carreras LIVE · circuito</span>\n {[{ id: 'random', name: 'Aleatorio', emoji: '🎲' }, ...RACING_TRACKS].map(({ id, name, emoji }) => (\n <button key={id} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => { setRaceTrack(id); setRaceMenu('class'); }}><span aria-hidden=\"true\">{emoji}</span><span>{name}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setRaceMenu(null)}><span>← Volver</span></button>\n </>}\n {onInviteGame && raceMenu === 'class' && <>\n <span className=\"chat-game-menu-title\">Carreras LIVE · categoría</span>\n {RACE_CLASS_MENU.map(({ id, hint }) => (\n <button key={id} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => chooseGame(() => onInviteGame('racing_live', { trackId: raceTrack, speedClass: id }))}><Flag size={16} aria-hidden=\"true\" /><span><strong>{id}</strong> · {hint}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setRaceMenu('track')}><span>← Volver</span></button>\n </>}\n {onInviteGame && tankMenu === 'map' && <>\n <span className=\"chat-game-menu-title\">Tanques LIVE · mapa</span>\n {TANK_MAP_MENU.map(({ id, label, hint }) => (\n <button key={id} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => { setTankMap(id); setTankMenu('lives'); }}><Crosshair size={16} aria-hidden=\"true\" /><span><strong>{label}</strong> · {hint}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setTankMenu(null)}><span>← Volver</span></button>\n </>}\n {onInviteGame && tankMenu === 'lives' && <>\n <span className=\"chat-game-menu-title\">Tanques LIVE · vidas</span>\n {TANK_LIVES_MENU.map(({ lives, hint }) => (\n <button key={lives} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => chooseGame(() => onInviteGame('tanks_live', { mapId: tankMap, lives }))}><span aria-hidden=\"true\">{'❤️'.repeat(lives)}</span><span><strong>{lives} {lives === 1 ? 'vida' : 'vidas'}</strong> · {hint}</span></button>))}\n <hr className=\"chat-game-menu-separator\" />\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" onClick={() => setTankMenu('map')}><span>← Volver</span></button>\n </>}\n {onInviteGame && !raceMenu && !tankMenu && <>\n <span className=\"chat-game-menu-title\">Invitar a jugar</span>\n {GAME_MENU.filter((item) => gameTypes.includes(item.type)).map(({ type, label, Icon }) => (\n <button key={type} type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\" disabled={gameInviteDisabled}\n onClick={() => (type === 'racing_live' ? setRaceMenu('track') : type === 'tanks_live' ? setTankMenu('map') : chooseGame(() => onInviteGame(type)))}><Icon size={16} aria-hidden=\"true\" /><span>{label}</span></button>))}\n </>}\n {onOpenBattleshipPreview && !raceMenu && !tankMenu && <>\n {onInviteGame && <hr className=\"chat-game-menu-separator\" />}\n <button type=\"button\" role=\"menuitem\" className=\"chat-game-menu-item\"\n onClick={() => chooseGame(onOpenBattleshipPreview)}><Box size={16} aria-hidden=\"true\" /><span>Vista previa 3D (sin rival)</span></button>\n </>}\n </div>}\n {popover === 'effects' && <EffectPicker onSend={onSendEffect} disabled={disabled || Boolean(editing)} onClose={() => setPopover(null)} />}\n {popover === 'emoji' && <div onKeyDownCapture={(event) => { if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); setPopover(null); textareaRef.current?.focus(); } }}>\n <EmojiPicker isOpen disabled={disabled} onSelect={(emoji) => { const node = textareaRef.current; const start = node?.selectionStart ?? value.length; const end = node?.selectionEnd ?? start; onChange(value.slice(0, start) + emoji + value.slice(end)); requestAnimationFrame(() => node?.setSelectionRange(start + emoji.length, start + emoji.length)); setPopover(null); textareaRef.current?.focus(); }} onClose={() => setPopover(null)} />\n </div>}\n {pickerKind && <div className={`chat-gif-picker-wrapper${pickerKind === 'sticker' ? ' chat-sticker-picker-wrapper' : ''}`} style={{ height: Math.min(pickerHeight, pickerAvailableHeight) }} role=\"dialog\" aria-label={pickerKind === 'sticker' ? 'Buscar stickers' : 'Buscar GIFs'} onKeyDown={(event) => {\n if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); setPopover(null); textareaRef.current?.focus(); }\n }}>\n <button type=\"button\" className=\"chat-gif-resize-handle\" aria-label={pickerKind === 'sticker' ? 'Cambiar altura del selector de stickers' : 'Cambiar altura del selector de GIFs'}\n title=\"Arrastra hacia arriba para ampliar · flechas para ajustar\"\n onPointerDown={(event) => {\n if (event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n pickerResizeRef.current = { y: event.clientY, height: Math.min(pickerHeight, pickerAvailableHeight) };\n event.currentTarget.setPointerCapture(event.pointerId);\n }}\n onPointerMove={(event) => {\n const start = pickerResizeRef.current;\n if (start) setPickerHeight(Math.min(pickerAvailableHeight, Math.max(220, start.height + start.y - event.clientY)));\n }}\n onPointerUp={(event) => {\n pickerResizeRef.current = null;\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n }}\n onPointerCancel={() => { pickerResizeRef.current = null; }}\n onLostPointerCapture={() => { pickerResizeRef.current = null; }}\n onKeyDown={(event) => {\n if (!['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) return;\n event.preventDefault();\n event.stopPropagation();\n setPickerHeight((height) => Math.min(pickerAvailableHeight, Math.max(220,\n event.key === 'End' ? pickerAvailableHeight : event.key === 'Home' ? 220 : Math.min(height, pickerAvailableHeight) + (event.key === 'ArrowUp' ? 30 : -30))));\n }}><GripHorizontal size={18} /></button>\n {pickerKind === 'sticker' ? <StickerPicker\n onSelect={(sticker) => { onAddAttachment?.(sticker); textareaRef.current?.focus(); }}\n onClose={() => setPopover(null)}\n disabled={disabled}\n /> : <GifPicker\n onSelect={(gif) => { onAddAttachment?.(gif); textareaRef.current?.focus(); }}\n onClose={() => setPopover(null)}\n disabled={disabled}\n />}\n </div>}\n <EmojiAutocomplete\n textareaRef={textareaRef}\n value={value}\n onInsert={handleAutocompleteInsert}\n onClose={handleAutocompleteClose}\n isOpen={autocompleteOpen}\n />\n </div>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { ChevronUp, Gamepad2 } from 'lucide-react';\nimport useChatGames from './useChatGames';\nimport useGamePanelStore from './useGamePanelStore';\nimport ConnectedGameCard from './ConnectedGameCard';\nimport { getGameTitle, getShortGameStatus, isTerminalGame, sameUser } from './gameStatus';\n\nexport default function ChatGamePanel({ gameKey, currentUserId }) {\n const game = useChatGames((state) => state.games[gameKey]);\n const minimized = useGamePanelStore((state) => Boolean(state.panels[gameKey]?.minimized));\n if (!game) return null;\n const { setMinimized, dismiss } = useGamePanelStore.getState();\n const myTurn = game.game !== 'racing_live' && game.status === 'active' && sameUser(currentUserId, game.turnId);\n const title = getGameTitle(game);\n const keepMounted = game.game === 'tanks_live' || game.game === 'racing_live';\n const canDismiss = isTerminalGame(game) && !game.pendingEvent;\n return (\n <section className={`chat-game-panel${minimized ? ' chat-game-panel--minimized' : ''}`} aria-label={`Partida activa de ${title}`}>\n {minimized && (\n <button type=\"button\" className={`chat-game-panel-bar${myTurn ? ' chat-game-panel-bar--my-turn' : ''}`} onClick={() => setMinimized(gameKey, false)} aria-label={`Mostrar tablero de ${title}`}>\n <Gamepad2 size={15} aria-hidden=\"true\" />\n <span>{title} · {getShortGameStatus(game, currentUserId)}</span>\n <ChevronUp size={15} aria-hidden=\"true\" />\n </button>\n )}\n {(keepMounted || !minimized) && <div hidden={minimized}>\n <ConnectedGameCard suspended={minimized} gameKey={gameKey} currentUserId={currentUserId} variant=\"panel\"\n onMinimize={() => setMinimized(gameKey, true)} onDismiss={canDismiss ? () => dismiss(gameKey) : undefined} />\n </div>}\n </section>\n );\n}\n","/* eslint-disable react/prop-types */\nimport { Suspense, useEffect, useRef, useState } from 'react';\nimport { Grip, ArrowLeft } from 'lucide-react';\nimport { useChatUnread } from '../../core/unread/unreadMessages';\nimport useChatTextSize from '../hooks/useChatTextSize';\nimport useFocusTrap from '../hooks/useFocusTrap';\nimport useResizable from '../hooks/useResizable';\nimport ChatHeader from './ChatHeader';\nimport ChatSidebar from './ChatSidebar';\nimport ChatEmptyState from './ChatEmptyState';\nimport MessageList from './MessageList';\nimport MessageComposer from './MessageComposer';\nimport { ChatEffects } from '../../effects/ChatEffects.jsx';\nimport ChatGamePanel from '../../games/shared/ChatGamePanel';\n\n\nexport default function ChatWindow({\n effectsConfig, effectScope, effectIdentityScope, onSendEffect, effectError,\n BattleshipPreviewComponent = null,\n placement = 'floating',\n theme,\n standalone, onDetach, onInstall, installHelp, onDismissInstallHelp,\n title,\n subtitle,\n headerType,\n headerSecondary,\n headerPresence,\n currentUserName, myPresence, onSetPresence,\n isOpen,\n isMaximized,\n isMinimized,\n onClose,\n onMinimize,\n onToggleMaximize,\n rooms,\n users,\n messages,\n onInviteGame, gameInviteDisabled, gameTypes, gameError, gamePanelKey,\n currentUserId,\n currentUserIds,\n onSelectRoom,\n onSelectUser,\n selectedId,\n inputValue,\n onInputChange,\n onSend,\n attachments,\n onAddAttachment,\n onRemoveAttachment,\n status,\n disabled,\n onSearch, searchResults, searchStatus, searchQuery, presenceStatus,\n onCreateGroup,\n attachmentError, sending, reply, onReply, onCancelReply,\n privateRooms,\n knownUsers,\n unreadCounts,\n onlineUsers,\n editing, onStartEditLast, onCancelEdit, onEditMessage, onReact,\n}) {\n const [textSize, setTextSize] = useChatTextSize();\n const dialogRef = useRef(null);\n const [showSidebar, setShowSidebar] = useState(true);\n const [battleshipPreview, setBattleshipPreview] = useState(false);\n useEffect(() => { setBattleshipPreview(false); }, [selectedId]);\n const [isFullscreen, setFullscreen] = useState(() => window.matchMedia('(max-width: 640px)').matches);\n useEffect(() => {\n const media = window.matchMedia('(max-width: 640px)');\n const update = () => setFullscreen(media.matches);\n media.addEventListener('change', update);\n return () => media.removeEventListener('change', update);\n }, []);\n // Wide windows show list and conversation side by side; small ones show one pane at a time.\n const wide = !isFullscreen && (isMaximized || standalone);\n const resizable = !standalone && !isFullscreen && !isMaximized;\n const { size, isResizing, handleProps: resizeHandleProps } = useResizable({ initial: { width: 420, height: 740 }, min: { width: 360, height: 380 }, enabled: resizable, targetRef: dialogRef });\n const listVisible = wide ? showSidebar : showSidebar || selectedId == null;\n useEffect(() => {\n if (selectedId != null && !wide) setShowSidebar(false);\n }, [selectedId, wide]);\n useEffect(() => {\n const update = () => {\n const showingConversation = isOpen && !isMinimized && selectedId != null && (wide || !listVisible);\n useChatUnread.getState().setVisibleRoom(showingConversation\n && document.visibilityState === 'visible' && document.hasFocus() ? selectedId : null);\n };\n update();\n window.addEventListener('focus', update);\n window.addEventListener('blur', update);\n document.addEventListener('visibilitychange', update);\n return () => {\n window.removeEventListener('focus', update);\n window.removeEventListener('blur', update);\n document.removeEventListener('visibilitychange', update);\n useChatUnread.getState().setVisibleRoom(null);\n };\n }, [isOpen, isMinimized, selectedId, wide, listVisible]);\n const selectRoom = (id) => { if (sending) return; if (!wide) setShowSidebar(false); onSelectRoom?.(id); };\n const trapFocus = useFocusTrap(dialogRef, { active: isFullscreen, autoFocus: isOpen && !isMinimized });\n if (isMinimized) {\n return (\n <button type=\"button\" className={`mc-chat chat-window ${placement === 'floating' ? 'chat-window--floating ' : ''}chat-window--minimized`} data-chat-theme={theme} onClick={onMinimize} aria-label=\"Abrir chat\">\n <span style={{ width: '32px', height: '32px', borderRadius: '50%', background: 'var(--chat-primary)', color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, margin: 'auto' }}>\n {title?.charAt(0).toUpperCase()}\n </span>\n </button>\n );\n }\n\n if (!isOpen) return null;\n return (\n <ChatEffects roomId={selectedId} scope={effectScope} identityScope={effectIdentityScope} messages={messages} currentUserIds={currentUserIds} config={{ ...effectsConfig, enabled: effectsConfig?.enabled !== false && (headerType === 'private' || effectsConfig?.allowGroups === true) }} visible={isOpen && !isMinimized && selectedId != null && (wide || !listVisible)} targetRef={dialogRef}>\n <div ref={dialogRef} className={`mc-chat chat-window ${placement === 'floating' ? 'chat-window--floating' : ''} ${standalone ? 'chat-window--standalone' : ''} ${isMaximized ? 'chat-window--maximized' : 'chat-window--compact'} ${wide ? `chat-window--wide${listVisible ? '' : ' chat-window--hide-sidebar'}` : (listVisible ? 'chat-window--show-sidebar' : '')} ${isResizing ? 'chat-window--resizing' : ''}`} style={{ '--chat-message-font-size': `${textSize}px`, ...(resizable ? { '--chat-window-width': `${size.width}px`, '--chat-window-height': `${size.height}px` } : {}) }} data-chat-theme={theme} role=\"dialog\" aria-modal={isFullscreen || undefined} aria-label={title} onKeyDown={trapFocus} tabIndex={-1}>\n {resizable && <button type=\"button\" className=\"chat-resize-handle\"\n aria-label=\"Cambiar tamaño del chat\" title=\"Arrastra para ajustar el tamaño · también puedes usar las flechas\"\n {...resizeHandleProps}>\n <Grip size={13} aria-hidden=\"true\" />\n </button>}\n <ChatHeader\n textSize={textSize} onTextSizeChange={setTextSize}\n onDetach={onDetach} onInstall={onInstall}\n title={title}\n subtitle={subtitle}\n type={headerType}\n secondary={headerSecondary}\n presence={headerPresence}\n onClose={onClose}\n onMinimize={onMinimize}\n onMaximize={onToggleMaximize}\n onRestore={onToggleMaximize}\n isMaximized={isMaximized}\n showSidebar={listVisible} onToggleSidebar={() => setShowSidebar(!listVisible)}\n />\n {installHelp && <div className=\"chat-install-help\" role=\"status\"><span>{installHelp}</span><button type=\"button\" className=\"chat-btn\" onClick={onDismissInstallHelp} aria-label=\"Cerrar ayuda de instalación\">×</button></div>}\n <div className=\"chat-body\">\n <ChatSidebar\n rooms={rooms}\n users={users}\n onlineUsers={onlineUsers}\n privateRooms={privateRooms}\n knownUsers={knownUsers}\n selectedId={selectedId}\n onSelect={selectRoom}\n onSelectUser={onSelectUser}\n onSearch={onSearch} searchResults={searchResults} searchStatus={searchStatus} searchQuery={searchQuery} presenceStatus={presenceStatus}\n onCreateGroup={onCreateGroup}\n unreadCounts={unreadCounts}\n currentUserId={currentUserId}\n currentUserIds={currentUserIds}\n currentUserName={currentUserName} myPresence={myPresence} onSetPresence={onSetPresence}\n />\n <div className=\"chat-messages-wrapper\">\n {selectedId != null ? (\n <>\n {!wide && <button type=\"button\" className=\"chat-back-btn\" onClick={() => setShowSidebar(true)} aria-label=\"Volver a conversaciones\"><ArrowLeft size={16} aria-hidden=\"true\" /><span>Conversaciones</span></button>}\n <MessageList key={`messages:${selectedId}`} messages={messages} currentUserId={currentUserId} onReply={onReply} panelGameKey={gamePanelKey} onReact={onReact} onEditMessage={onEditMessage} editingId={editing?.messageId} />\n {gamePanelKey && !battleshipPreview && <ChatGamePanel key={gamePanelKey} gameKey={gamePanelKey} currentUserId={currentUserId} />}\n {battleshipPreview && BattleshipPreviewComponent && <div className=\"bs-proto-overlay\">\n <Suspense fallback={<p className=\"bs-proto-overlay__loading\" role=\"status\">Cargando vista previa 3D…</p>}>\n <BattleshipPreviewComponent compact={!isMaximized || isFullscreen} onClose={() => setBattleshipPreview(false)} />\n </Suspense>\n </div>}\n <div className=\"chat-connection-status\" role=\"status\">\n <span className={`chat-connection-dot ${status === 'connected' ? 'chat-connection-dot--connected' : 'chat-connection-dot--disconnected'}`} />\n <span>{status === 'connected' ? 'Conectado' : 'Sin conexión · puedes preparar archivos y notas de voz'}</span>\n </div>\n {effectError && <p className=\"chat-game-launch-error\" role=\"alert\">{effectError}</p>}\n {gameError && <p className=\"chat-game-launch-error\" role=\"alert\">{gameError}</p>}\n <MessageComposer key={`composer:${selectedId}`}\n onSendEffect={onSendEffect}\n onInviteGame={onInviteGame} gameInviteDisabled={gameInviteDisabled} gameTypes={gameTypes}\n onOpenBattleshipPreview={BattleshipPreviewComponent ? () => setBattleshipPreview(true) : undefined}\n reply={reply} onCancelReply={onCancelReply}\n editing={editing} onStartEditLast={onStartEditLast} onCancelEdit={onCancelEdit}\n value={inputValue}\n onChange={onInputChange}\n onSend={onSend}\n disabled={disabled}\n attachments={attachments}\n sending={sending}\n attachmentError={attachmentError}\n onAddAttachment={onAddAttachment}\n onRemoveAttachment={onRemoveAttachment}\n />\n </>\n ) : (\n <ChatEmptyState />\n )}\n </div>\n </div>\n </div>\n </ChatEffects>\n );\n}\n","import { useEffect, useState } from 'react';\n\nlet installPrompt = null;\nconst hasWindow = () => typeof window !== 'undefined';\nconst notifyInstall = () => { if (hasWindow()) window.dispatchEvent(new Event('chat-install-change')); };\n\n// Ref-counted, idempotent: listeners are registered once; the last stop() removes them.\nlet installUsers = 0;\nlet removeInstallListeners = null;\nexport function startChatApp() {\n if (!hasWindow()) return () => {};\n if (installUsers++ === 0) {\n const onPrompt = (event) => {\n event.preventDefault();\n installPrompt = event;\n notifyInstall();\n };\n const onInstalled = () => {\n installPrompt = null;\n notifyInstall();\n };\n window.addEventListener('beforeinstallprompt', onPrompt);\n window.addEventListener('appinstalled', onInstalled);\n removeInstallListeners = () => {\n window.removeEventListener('beforeinstallprompt', onPrompt);\n window.removeEventListener('appinstalled', onInstalled);\n };\n }\n let stopped = false;\n return function stop() {\n if (stopped) return;\n stopped = true;\n if (--installUsers === 0) {\n removeInstallListeners?.();\n removeInstallListeners = null;\n installPrompt = null;\n }\n };\n}\n\nexport function useChatInstall() {\n const standalone = () => hasWindow() && (window.matchMedia('(display-mode: standalone)').matches || Boolean(navigator.standalone));\n const [installed, setInstalled] = useState(standalone);\n const [available, setAvailable] = useState(Boolean(installPrompt));\n const [installHelp, setInstallHelp] = useState('');\n useEffect(() => {\n const media = window.matchMedia('(display-mode: standalone)');\n const update = () => { setInstalled(standalone()); setAvailable(Boolean(installPrompt)); };\n window.addEventListener('chat-install-change', update);\n media.addEventListener('change', update);\n return () => { window.removeEventListener('chat-install-change', update); media.removeEventListener('change', update); };\n }, []);\n const install = async () => {\n if (!window.isSecureContext) {\n setInstallHelp('Para instalar el chat, abre la aplicación mediante HTTPS o localhost.');\n return;\n }\n if (!installPrompt) {\n setInstallHelp('Abre el menú del navegador y elige “Instalar LIRA Chat” o “Añadir al Dock / pantalla de inicio”. Si no aparece, abre esta ventana de chat en una pestaña del navegador.');\n return;\n }\n const prompt = installPrompt;\n installPrompt = null;\n notifyInstall();\n try {\n await prompt.prompt();\n await prompt.userChoice;\n } catch {\n setInstallHelp('No se pudo iniciar la instalación. Puedes usar la opción de instalar del menú del navegador.');\n }\n };\n return { installed, available, install, installHelp, dismissInstallHelp: () => setInstallHelp('') };\n}\n\nlet chatPopup = null;\nexport function openChatWindow({ path = '/chat', windowName = 'lira-independent-chat' } = {}) {\n if (chatPopup && !chatPopup.closed) { chatPopup.focus(); return true; }\n const width = Math.min(520, window.screen.availWidth);\n const height = Math.min(800, window.screen.availHeight);\n chatPopup = window.open(path, windowName, `popup=yes,width=${width},height=${height},resizable=yes,scrollbars=yes`);\n if (!chatPopup) return false;\n // The window restores its own session and socket; it never depends on the opener.\n chatPopup.opener = null;\n chatPopup.focus();\n return true;\n}\n\nexport function registerChatWorker({ enabled = true, path = '/chat', swUrl = '/chat-sw.js' } = {}) {\n if (enabled && hasWindow() && 'serviceWorker' in navigator && window.isSecureContext && window.location.pathname === path) {\n navigator.serviceWorker.register(swUrl, { scope: path }).catch((error) => console.warn('Chat service worker:', error));\n }\n}\n","import { useState, useEffect, useRef, useMemo } from 'react';\nimport { useShallow } from 'zustand/react/shallow';\nimport { useChatUnread } from '../../core/unread/unreadMessages.js';\nimport useChatGames from '../../games/shared/useChatGames.js';\nimport { isGameMessage } from '../../games/shared/protocol.js';\nimport { isWebrtcMessage } from '../../net/webrtc/protocol.js';\nimport useGamePanelStore from '../../games/shared/useGamePanelStore.js';\nimport { isLiveGame, isTerminalGame } from '../../games/shared/gameStatus.js';\nimport { useChatStore, useChatIdentity, useChatConfig, useChatConnection } from '../../provider/hooks.js';\nimport { setDesktopConversation } from '../../notifications/desktopNotifications.js';\nimport { useChatInstall } from '../../pwa/chatApp.js';\nimport { shareGif } from '../../media/klipy/klipy.js';\nimport { shareSticker } from '../../media/klipy/klipyStickers.js';\nimport { encodeEffect, decodeEffect, effectMessageText } from '../../effects/protocol.js';\nimport { useChatMessageExtras, isStickerAttachment, encodeEdit, encodeReaction, groupReactions, findLastOwnEditable, messageId, isMessageAction } from '../../core/extras/messageExtras.js';\n\n// Matched by the backend relay limit; files are never persisted.\nconst MAX_PREVIEW_BYTES = 10 * 1024 * 1024;\n\n/**\n * Chat data logic: store subscriptions, timeline, composer and actions.\n * `isOpen`/`isMinimized` come from useChatLayout (desktop notifications and presence refresh).\n */\nexport default function useChatController({ isOpen = false, isMinimized = false } = {}) {\n const installation = useChatInstall();\n const { effects: rawEffectsConfig, features } = useChatConfig();\n const gamesFeatures = features?.games;\n const gameTypes = useMemo(() => ['connect4', 'battleship', 'tanks', 'tanks_live', 'racing_live'].filter((type) => (type === 'racing_live' ? gamesFeatures?.racingLive === true : type === 'tanks_live' ? gamesFeatures?.tanksLive === true : type === 'tanks' ? gamesFeatures?.tanks === true : gamesFeatures?.[type] !== false)), [gamesFeatures]);\n const effectsConfig = rawEffectsConfig === false ? { enabled: false } : rawEffectsConfig ?? {};\n const effectCooldowns = useRef(new Map());\n const effectPending = useRef(false);\n const [effectError, setEffectError] = useState('');\n const { chatMessages, chatState, onlineUsers, rawPrivateRooms, userSearchQuery, userSearchResults,\n userSearchStatus, presenceStatus, rawKnownUsers, myPresence } = useChatStore(useShallow((state) => ({\n chatMessages: state.chatMessages,\n chatState: state.chatState,\n onlineUsers: state.onlineUsers,\n rawPrivateRooms: state.privateRooms,\n userSearchQuery: state.userSearchQuery,\n userSearchResults: state.userSearchResults,\n userSearchStatus: state.userSearchStatus,\n presenceStatus: state.presenceStatus,\n rawKnownUsers: state.knownUsers,\n myPresence: state.myPresence,\n })));\n const chatIdentity = useChatIdentity();\n const effectConnection = useChatConnection();\n const websocketStatus = chatIdentity.status;\n const { selectChat, fetchGroups, searchUsers, setUserSearchQuery, sendChatMessage, createGroup, openPrivateChat, setMyPresence } = useChatStore(useShallow((state) => ({\n selectChat: state.selectChat,\n fetchGroups: state.fetchGroups,\n searchUsers: state.searchUsers,\n setUserSearchQuery: state.setUserSearchQuery,\n sendChatMessage: state.sendChatMessage,\n createGroup: state.createGroup,\n openPrivateChat: state.openPrivateChat,\n setMyPresence: state.setMyPresence,\n })));\n const unreadCounts = useChatUnread((state) => state.counts);\n const unreadRooms = useChatUnread((state) => state.ledger.rooms);\n // Keep private pending conversations reachable after reloading, even offline.\n const privateRooms = useMemo(() => ({ ...Object.fromEntries(Object.entries(unreadRooms)\n .map(([room, info]) => [info.peerId, room])), ...rawPrivateRooms }), [unreadRooms, rawPrivateRooms]);\n const knownUsers = useMemo(() => ({ ...Object.fromEntries(Object.values(unreadRooms)\n .map((info) => [info.peerId, { user_id: info.peerId, username: info.username }])), ...rawKnownUsers }), [unreadRooms, rawKnownUsers]);\n const [reply, setReply] = useState(null);\n const [editing, setEditing] = useState(null);\n const [gameError, setGameError] = useState('');\n const edits = useChatMessageExtras((s) => s.edits);\n const reactions = useChatMessageExtras((s) => s.reactions);\n useEffect(() => { setReply(null); setEffectError(''); }, [chatState.currentChat?.id, chatIdentity.userId]);\n const [inputValue, setInputValue] = useState('');\n // selectRoom and the identity reset already clear the input.\n useEffect(() => { setEditing(null); }, [chatState.currentChat?.id, chatIdentity.userId]);\n const [attachments, setAttachments] = useState([]);\n const [sending, setSending] = useState(false);\n const sendingRef = useRef(false);\n const objectUrls = useRef(new Set());\n const [attachmentError, setAttachmentError] = useState('');\n const attachmentRef = useRef([]);\n const activeRoom = chatState.currentChat?.id;\n const selectedId = activeRoom ?? null;\n // Same `${backend}:${userId}` scope the host transport reports (games and desktop notifications).\n const gameScope = chatIdentity.scope;\n const gameKeys = useChatGames(useShallow((state) => Object.keys(state.games).filter((key) => {\n const game = state.games[key];\n return game.scope === gameScope && String(game.roomId) === String(activeRoom);\n })));\n const gameMessages = useMemo(() => gameKeys.map((key) => {\n const game = useChatGames.getState().games[key];\n return { id: `game:${key}`, gameKey: key, room_id: activeRoom, timestamp: game.createdAt };\n }), [gameKeys, activeRoom]);\n const hasLiveGame = useChatGames((state) => Object.values(state.games).some((game) =>\n game.scope === gameScope && String(game.roomId) === String(activeRoom) && isLiveGame(game)));\n const gamePanels = useGamePanelStore((state) => state.panels);\n // One interactive board per room: the live game, else the latest finished one not dismissed.\n const gamePanelKey = useChatGames((state) => {\n const games = Object.values(state.games).filter((game) => game.scope === gameScope && String(game.roomId) === String(activeRoom));\n const live = games.find(isLiveGame);\n if (live) return live.key;\n // Only the newest finished game may reopen; dismissing it must not fall back to older ones.\n const latest = games.filter(isTerminalGame)\n .sort((a, b) => (Date.parse(b.createdAt) || 0) - (Date.parse(a.createdAt) || 0))[0];\n return latest && !gamePanels[latest.key]?.dismissed ? latest.key : null;\n });\n useEffect(() => { setGameError(''); }, [activeRoom, gameScope]);\n useEffect(() => {\n setDesktopConversation({ scope: gameScope, room: activeRoom, open: isOpen && !isMinimized });\n return () => setDesktopConversation(null);\n }, [gameScope, activeRoom, isOpen, isMinimized]);\n const visible = isOpen && !isMinimized;\n const handleSelectUser = (item) => {\n if (sendingRef.current) return;\n const recipientId = item?.user_id ?? item?.id;\n if (!recipientId) return;\n const existingRoom = privateRooms[recipientId];\n if (existingRoom) {\n selectRoom(existingRoom, 'private');\n } else {\n openPrivateChat(recipientId);\n }\n };\n\n const identity = chatIdentity.userId;\n const currentUserIds = chatIdentity.ids;\n // Names for reaction tooltips (ReactionBar reads this instead of global stores).\n const people = useMemo(() => ({\n ownIds: currentUserIds,\n resolveName: (id) => {\n const known = knownUsers?.[id];\n if (known?.username || known?.name) return known.name || known.username;\n const online = onlineUsers.find((user) => String(user.user_id ?? user.id) === String(id));\n return online?.name || online?.username || null;\n },\n }), [currentUserIds, knownUsers, onlineUsers]);\n useEffect(() => {\n setAttachments([]);\n attachmentRef.current = [];\n objectUrls.current.forEach((url) => URL.revokeObjectURL(url));\n objectUrls.current.clear();\n setInputValue('');\n setAttachmentError('');\n }, [identity]);\n\n useEffect(() => {\n if (websocketStatus === 'connected') fetchGroups();\n }, [websocketStatus, fetchGroups]);\n\n // Refresh on connection/open, without another request when the chat closes.\n const presenceTrigger = useRef({ connected: false, visible: false });\n useEffect(() => {\n const connected = websocketStatus === 'connected';\n const previous = presenceTrigger.current;\n presenceTrigger.current = { connected, visible };\n if (connected && (!previous.connected || (visible && !previous.visible))) searchUsers('');\n }, [websocketStatus, visible, searchUsers]);\n useEffect(() => {\n if (!visible || websocketStatus !== 'connected' || !userSearchQuery) return undefined;\n const timer = setTimeout(() => searchUsers(userSearchQuery), 300);\n return () => clearTimeout(timer);\n }, [userSearchQuery, websocketStatus, visible, searchUsers]);\n\n // Public channels are joined in the store on GROUPS_LIST; private rooms need no CHAT_JOIN.\n\n useEffect(() => {\n attachmentRef.current = attachments;\n }, [attachments]);\n useEffect(() => {\n const urls = objectUrls.current;\n return () => { urls.forEach((url) => URL.revokeObjectURL(url)); urls.clear(); };\n }, []);\n\n const messages = useMemo(() => chatMessages.map((envelope) => {\n const body = envelope.data ?? envelope.payload;\n return body && typeof body === 'object' ? { ...envelope, ...body } : envelope;\n }).filter((message) =>\n !['CHAT_JOINED', 'CHAT_LEFT'].includes(message.event)\n && message.room_id != null && String(message.room_id) === String(activeRoom)\n && !isGameMessage(message.message ?? message.text)\n && !isWebrtcMessage(message.message ?? message.text)\n && !isMessageAction(message.message ?? message.text)\n && (typeof message.message === 'string' || typeof message.text === 'string' || message.attachments?.length || message.attachment)\n ).map((message) => {\n const id = messageId(message);\n if (!id) return message;\n const edit = edits[id];\n const merged = edit ? { ...message, message: edit.text, edited: true, editedAt: edit.editedAt } : message;\n return { ...merged, reactionGroups: groupReactions(reactions[id], currentUserIds) };\n }), [chatMessages, activeRoom, edits, reactions, currentUserIds]);\n const timeline = useMemo(() => {\n // Insert game anchors without changing the arrival order of ordinary messages.\n const result = [...messages];\n for (const game of gameMessages) {\n const time = Date.parse(game.timestamp);\n const index = result.findIndex((message) => Date.parse(message.timestamp) > time);\n result.splice(index < 0 ? result.length : index, 0, game);\n }\n return result;\n }, [messages, gameMessages]);\n\n const selectRoom = (id, type) => {\n if (id == null || sendingRef.current || String(id) === String(activeRoom)) return;\n // Auto-detect type: private_ prefix or privateRooms values\n const inferredType = (type || (String(id).startsWith('private_') ? 'private' : 'group'));\n selectChat(id, inferredType);\n setInputValue('');\n attachmentRef.current.forEach((item) => { if (item.preview?.startsWith('blob:')) { URL.revokeObjectURL(item.preview); objectUrls.current.delete(item.preview); } });\n attachmentRef.current = [];\n setAttachments([]);\n setAttachmentError('');\n };\n const startEdit = (message) => {\n if (sendingRef.current || !message || message.localOnly || message.sending || decodeEffect(message.message ?? message.text)) return false;\n const id = messageId(message);\n const text = message.message ?? message.text;\n if (!id || typeof text !== 'string' || !text.trim() || !currentUserIds.includes(String(message.user_id))) return false;\n const match = text.match(/^> ([^\\n]{1,240})\\n\\n/);\n const quote = match ? match[0] : '';\n setInputValue(text.slice(quote.length));\n setReply(null);\n setAttachmentError('');\n setEditing({ messageId: id, original: message, quote });\n return true;\n };\n const cancelEdit = () => { setEditing(null); setInputValue(''); };\n const handleReact = (message, emoji) => {\n const id = messageId(message);\n if (!id || !emoji || websocketStatus !== 'connected') return;\n const mine = (reactions[id]?.[emoji] || []).some((userId) => currentUserIds.includes(String(userId)));\n void sendChatMessage(String(message.room_id ?? activeRoom), encodeReaction({ targetId: id, emoji, on: !mine }), [])\n .catch((error) => setAttachmentError(error.message));\n };\n const handleSend = async () => {\n if (activeRoom == null || sendingRef.current || websocketStatus !== 'connected') return;\n if (editing) {\n const text = inputValue.trim();\n const original = editing.original?.message ?? editing.original?.text ?? '';\n if (!text || editing.quote + text === original) { cancelEdit(); return; }\n sendingRef.current = true;\n setSending(true);\n setAttachmentError('');\n try {\n await sendChatMessage(activeRoom, encodeEdit({ targetId: editing.messageId, text: editing.quote + text }), []);\n setEditing(null);\n setInputValue('');\n } catch (error) {\n setAttachmentError(error.message);\n } finally {\n sendingRef.current = false;\n setSending(false);\n }\n return;\n }\n const outgoingAttachments = [...attachmentRef.current];\n const text = inputValue.trim();\n if (!text && !outgoingAttachments.length) return;\n sendingRef.current = true;\n setSending(true);\n setAttachmentError('');\n try {\n // Reply is ordinary quoted text under the existing backend contract.\n const quoted = reply ? `> ${String(reply.username || 'Usuario').replace(/[\\r\\n]/g, ' ').slice(0, 50)}: ${String(reply.message || reply.text || '[Archivo adjunto]').replace(/\\s+/g, ' ').slice(0, 180)}\\n\\n` : '';\n await sendChatMessage(activeRoom, quoted + text, outgoingAttachments);\n // Register KLIPY usage only for media that was actually sent (never on mere selection).\n outgoingAttachments.forEach((item) => {\n if (item.kind !== 'gif' || !item.slug) return;\n if (isStickerAttachment(item)) void shareSticker(item.slug, { query: item.shareQuery || '' });\n else void shareGif(item.slug, { query: item.shareQuery || '' });\n });\n setReply(null);\n outgoingAttachments.forEach((item) => {\n if (item.preview?.startsWith('blob:')) { URL.revokeObjectURL(item.preview); objectUrls.current.delete(item.preview); }\n });\n attachmentRef.current = [];\n setAttachments([]);\n setInputValue('');\n } catch (error) {\n setAttachmentError(error.message);\n } finally {\n sendingRef.current = false;\n setSending(false);\n }\n };\n const handleAddAttachment = (file) => {\n if (sendingRef.current) return;\n if (attachmentRef.current.length >= 1) {\n setAttachmentError('Envía un archivo o GIF por mensaje.');\n return;\n }\n let item;\n if (file.kind === 'gif') {\n try {\n const url = new URL(file.url);\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error('invalid');\n item = { ...file, preview: url.href, url: url.href };\n } catch {\n setAttachmentError('Introduce un enlace HTTPS válido para el GIF.');\n return;\n }\n } else {\n if (!(file instanceof Blob) || (!file.size || file.size > MAX_PREVIEW_BYTES)) {\n setAttachmentError('Máximo 10 MB por archivo.');\n return;\n }\n const preview = URL.createObjectURL(file);\n objectUrls.current.add(preview);\n item = { file, name: file.name || 'Nota de voz', size: file.size, type: file.type || 'application/octet-stream', preview };\n }\n const next = [...attachmentRef.current, item];\n attachmentRef.current = next;\n setAttachments(next);\n setAttachmentError('');\n };\n const removeAttachment = (index) => {\n if (sendingRef.current) return;\n const item = attachmentRef.current[index];\n if (item?.preview?.startsWith('blob:')) { URL.revokeObjectURL(item.preview); objectUrls.current.delete(item.preview); }\n const next = attachmentRef.current.filter((_, i) => i !== index);\n attachmentRef.current = next;\n setAttachments(next);\n setAttachmentError('');\n };\n const room = chatState.availableGroups?.find((group) => String(group.id) === String(activeRoom));\n const isPrivate = chatState.currentChat?.type === 'private';\n const users = onlineUsers;\n let title = 'Chat';\n let headerSecondary;\n let headerPresence = null;\n if (activeRoom != null) {\n if (isPrivate) {\n const userId = Object.keys(privateRooms).find((key) => privateRooms[key] === activeRoom);\n const user = (userId && knownUsers[userId]) || onlineUsers.find((item) => String(item.user_id ?? item.id) === String(userId));\n title = user?.name || user?.username || (userId ? `Usuario ${String(userId).slice(0, 8)}` : 'Conversación privada');\n if (user?.username && user.username !== title) headerSecondary = user.username;\n // Offline peers are absent from onlineUsers; a missing status means plain online.\n const peer = userId != null && onlineUsers.find((item) => String(item.user_id ?? item.id) === String(userId));\n headerPresence = peer ? peer.status || 'online' : null;\n } else {\n title = room?.name || String(activeRoom);\n }\n }\n\n // Props for ChatWindow that do not depend on window layout.\n const windowProps = {\n effectsConfig,\n effectIdentityScope: chatIdentity.scope,\n effectScope: `${chatIdentity.scope}:${effectConnection.connectionId ?? effectConnection.status}`,\n effectError,\n onSendEffect: effectsConfig.enabled !== false && (isPrivate || effectsConfig.allowGroups) ? async (effectId, countdown) => {\n if (activeRoom == null || websocketStatus !== 'connected' || sendingRef.current || editing || effectPending.current) return { ok: false, error: 'No se puede enviar un efecto ahora.' };\n const key = `${chatIdentity.scope}:${activeRoom}`;\n const last = effectCooldowns.current.get(key) ?? 0;\n const wait = (effectsConfig.cooldownMs ?? 5000) - (Date.now() - last);\n if (wait > 0) { const error = `Espera ${Math.ceil(wait / 1000)} s para enviar otro efecto.`; setEffectError(error); return { ok: false, error }; }\n effectPending.current = true; setEffectError('');\n try {\n await sendChatMessage(activeRoom, encodeEffect({ effectId, ...(countdown ? { endsAt: Date.now() + countdown.durationMs, sound: countdown.sound } : {}) }), []);\n effectCooldowns.current.set(key, Date.now());\n return { ok: true };\n } catch (error) { const message = error.message || 'No se pudo enviar el efecto.'; setEffectError(message); return { ok: false, error: message }; }\n finally { effectPending.current = false; }\n } : undefined,\n title,\n headerType: isPrivate ? 'private' : 'group',\n headerSecondary,\n headerPresence,\n currentUserName: chatIdentity.name ?? undefined,\n myPresence,\n onSetPresence: setMyPresence,\n subtitle: websocketStatus,\n onInstall: !installation.installed ? installation.install : undefined,\n installHelp: installation.installHelp,\n onDismissInstallHelp: installation.dismissInstallHelp,\n rooms: chatState.availableGroups || [],\n users,\n onlineUsers,\n presenceStatus,\n searchResults: userSearchResults,\n searchStatus: userSearchStatus,\n searchQuery: userSearchQuery,\n onSearch: setUserSearchQuery,\n privateRooms,\n knownUsers,\n messages: timeline,\n gamePanelKey,\n gameError,\n gameInviteDisabled: hasLiveGame || websocketStatus !== 'connected',\n gameTypes,\n onInviteGame: isPrivate && activeRoom != null ? (gameType = 'connect4', options = {}) => {\n const opponentId = Object.keys(privateRooms).find((key) => String(privateRooms[key]) === String(activeRoom));\n if (!opponentId) { setGameError('Abre de nuevo la conversación privada para invitar a jugar.'); return; }\n setGameError('');\n void useChatGames.getState().invite({ roomId: String(activeRoom), opponentId, gameType, ...(gameType === 'racing_live' ? { ...(options.speedClass ? { speedClass: options.speedClass } : {}), ...(options.trackId ? { trackId: options.trackId } : {}) } : {}), ...(gameType === 'tanks_live' ? { ...(options.mapId ? { mapId: options.mapId } : {}), ...(options.lives ? { lives: options.lives } : {}) } : {}) }).catch((error) => setGameError(error.message));\n } : undefined,\n currentUserId: identity,\n currentUserIds,\n unreadCounts,\n onSelectRoom: (id) => selectRoom(id),\n onSelectUser: handleSelectUser,\n editing,\n onStartEditLast: () => { const message = findLastOwnEditable(messages, currentUserIds); return message ? startEdit(message) : false; },\n onCancelEdit: () => { if (!sendingRef.current) cancelEdit(); },\n onEditMessage: (message) => { startEdit(message); },\n onReact: handleReact,\n reply,\n onReply: (message) => { if (!sendingRef.current) setReply({ ...message, message: effectMessageText(message.message ?? message.text) }); },\n onCancelReply: () => { if (!sendingRef.current) setReply(null); },\n selectedId,\n inputValue,\n onInputChange: (value) => { if (!sendingRef.current) setInputValue(value); },\n onSend: handleSend,\n onCreateGroup: (name) => { if (websocketStatus === 'connected' && name.trim()) createGroup(name.trim()); },\n attachments,\n onAddAttachment: handleAddAttachment,\n onRemoveAttachment: removeAttachment,\n sending,\n attachmentError,\n status: websocketStatus,\n disabled: sending || websocketStatus !== 'connected',\n };\n\n return { identity, people, windowProps, setAttachmentError };\n}\n","import { createStore, useStore } from 'zustand';\n\n// Uncontrolled open state shared by ChatButton and ChatWindow (when no `open` prop is given).\nexport const chatUiStore = createStore((set) => ({\n isOpen: false,\n open: () => set({ isOpen: true }),\n close: () => set({ isOpen: false }),\n toggle: () => set((state) => ({ isOpen: !state.isOpen })),\n}));\n\nconst identity = (state) => state;\nexport const useChatUi = (selector = identity) => useStore(chatUiStore, selector);\n\nexport default chatUiStore;\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { openChatWindow } from '../../pwa/chatApp.js';\nimport { useChatConfig } from '../../provider/hooks.js';\nimport { chatUiStore, useChatUi } from './chatUiStore.js';\n\n// Escape only acts when the key comes from the chat dialog or from no focused element.\nconst isChatEscapeTarget = (target) => !target || target === document || target === document.body\n || document.documentElement === target\n || (typeof target.closest === 'function' && Boolean(target.closest('.chat-window')));\n\n/**\n * Window layout state for the connected chat.\n * mode: 'floating' | 'modal' | 'embedded' | 'page'. Embedded and page are always open.\n * Open state is controlled by `open`/`onOpenChange` when `open` is given, else by chatUiStore.\n */\nexport default function useChatLayout({ mode = 'floating', open, onOpenChange } = {}) {\n const config = useChatConfig();\n const alwaysOpen = mode === 'embedded' || mode === 'page';\n const controlled = open !== undefined;\n const storeOpen = useChatUi((state) => state.isOpen);\n const isOpen = alwaysOpen || Boolean(controlled ? open : storeOpen);\n const [isMaximized, setMaximized] = useState(false);\n const [isMinimized, setMinimized] = useState(false);\n\n const latest = useRef({});\n latest.current = { controlled, onOpenChange, onConfigOpenChange: config?.callbacks?.onOpenChange };\n const setOpen = useCallback((value) => {\n const { controlled: isControlled, onOpenChange: handler, onConfigOpenChange } = latest.current;\n if (!isControlled) chatUiStore.setState({ isOpen: value });\n handler?.(value);\n onConfigOpenChange?.(value);\n }, []);\n\n useEffect(() => {\n if (isOpen) setMinimized(false);\n }, [isOpen]);\n\n const canMinimize = mode === 'floating';\n const minimize = useCallback(() => { setMinimized(true); setOpen(false); }, [setOpen]);\n const restore = useCallback(() => { setMinimized(false); setOpen(true); }, [setOpen]);\n const close = useCallback(() => { setMinimized(false); setOpen(false); }, [setOpen]);\n const toggleMinimize = useCallback(() => { if (isMinimized) restore(); else minimize(); }, [isMinimized, restore, minimize]);\n const toggleMaximize = useCallback(() => setMaximized((value) => !value), []);\n const pwa = config?.pwa;\n // Returns false when the browser blocked the popup.\n const detach = useCallback(() => {\n if (!openChatWindow({ path: pwa?.path, windowName: pwa?.windowName })) return false;\n setMinimized(false);\n setOpen(false);\n return true;\n }, [pwa, setOpen]);\n\n useEffect(() => {\n if (!isOpen || alwaysOpen) return undefined;\n const handleKey = (event) => {\n if (event.key !== 'Escape' || event.defaultPrevented || !isChatEscapeTarget(event.target)) return;\n event.preventDefault();\n if (canMinimize) minimize();\n else close();\n };\n document.addEventListener('keydown', handleKey);\n return () => document.removeEventListener('keydown', handleKey);\n }, [isOpen, alwaysOpen, canMinimize, minimize, close]);\n\n return {\n mode,\n standalone: mode === 'page',\n isOpen,\n isMinimized: canMinimize && isMinimized,\n isMaximized,\n setMaximized,\n setOpen,\n minimize,\n restore,\n close,\n toggleMinimize,\n toggleMaximize,\n detach,\n };\n}\n","/* eslint-disable react/prop-types */\nimport { useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport ChatWindowShell from '../components/ChatWindow.jsx';\nimport { ChatPeopleContext } from '../chatPeopleContext.js';\nimport useFocusTrap from '../hooks/useFocusTrap.js';\nimport { useChatConfig } from '../../provider/hooks.js';\nimport useChatController from './useChatController.js';\nimport useChatLayout from './useChatLayout.js';\n\nconst POPUP_BLOCKED = 'El navegador bloqueó la ventana. Permite ventanas emergentes para este sitio.';\n\nconst portalTarget = (config) => {\n if (typeof document === 'undefined') return null;\n const container = typeof config?.portalContainer === 'function' ? config.portalContainer() : config?.portalContainer;\n return container || document.body;\n};\n\n/** Modal frame: backdrop (click closes), focus trapped inside the dialog. */\nfunction ModalFrame({ open, onClose, theme, children }) {\n const frameRef = useRef(null);\n const trap = useFocusTrap(frameRef, { active: open, autoFocus: open });\n if (!open) return null;\n return (\n <div className=\"mc-chat-portal mc-chat-modal-backdrop\" data-chat-theme={theme}\n onMouseDown={(event) => { if (event.target === event.currentTarget) onClose(); }}>\n <div ref={frameRef} className=\"mc-chat-modal\" onKeyDown={trap}>{children}</div>\n </div>\n );\n}\n\n/**\n * Connected chat window (must be inside LiraChatProvider).\n * placement: 'floating' (portal, minimize/maximize/detach, Escape minimizes) |\n * 'modal' (portal + backdrop + focus trap, Escape/backdrop close) | 'embedded' (inline, always open).\n * Open state: controlled with `open`/`onOpenChange`, else shared chatUiStore (ChatButton).\n */\nexport default function ChatWindow({\n placement = 'floating', open, onOpenChange, theme, className, BattleshipPreviewComponent = null,\n}) {\n const config = useChatConfig();\n const mode = placement === 'modal' || placement === 'embedded' ? placement : 'floating';\n const layout = useChatLayout({ mode, open, onOpenChange });\n const chat = useChatController({ isOpen: layout.isOpen, isMinimized: layout.isMinimized });\n const floating = mode === 'floating';\n const canDetach = floating && config?.features?.detach !== false;\n\n const shell = (\n <ChatWindowShell key={chat.identity} {...chat.windowProps}\n BattleshipPreviewComponent={BattleshipPreviewComponent}\n placement={mode} theme={theme}\n isOpen={layout.isOpen}\n isMaximized={floating && layout.isMaximized}\n isMinimized={layout.isMinimized}\n onDetach={canDetach ? () => { if (!layout.detach()) chat.setAttachmentError(POPUP_BLOCKED); } : undefined}\n onClose={mode === 'embedded' ? undefined : layout.close}\n onMinimize={floating ? layout.toggleMinimize : undefined}\n onToggleMaximize={floating ? layout.toggleMaximize : undefined} />\n );\n const content = <ChatPeopleContext.Provider value={chat.people}>{shell}</ChatPeopleContext.Provider>;\n\n if (mode === 'embedded') {\n return <div className={`mc-chat-embedded${className ? ` ${className}` : ''}`}>{content}</div>;\n }\n const target = portalTarget(config);\n if (!target) return null;\n if (mode === 'modal') {\n return createPortal(\n <ModalFrame open={layout.isOpen} onClose={layout.close} theme={theme}>\n {className ? <div className={className}>{content}</div> : content}\n </ModalFrame>,\n target,\n );\n }\n return createPortal(className ? <div className={className}>{content}</div> : content, target);\n}\n","/* eslint-disable react/prop-types */\nimport { createPortal } from 'react-dom';\nimport ChatWindowShell from '../components/ChatWindow.jsx';\nimport { ChatPeopleContext } from '../chatPeopleContext.js';\nimport { useChatConfig } from '../../provider/hooks.js';\nimport useChatController from './useChatController.js';\nimport useChatLayout from './useChatLayout.js';\n\n/**\n * Full-page chat (detached window / PWA route). Always open, viewport-sized,\n * no minimize/maximize/detach. Must be inside LiraChatProvider.\n * Portaled like the floating window (document.body or config.portalContainer).\n */\nexport default function ChatPage({ theme, className, BattleshipPreviewComponent = null }) {\n const config = useChatConfig();\n const layout = useChatLayout({ mode: 'page' });\n const chat = useChatController({ isOpen: true, isMinimized: false });\n if (typeof document === 'undefined') return null;\n const target = (typeof config?.portalContainer === 'function' ? config.portalContainer() : config?.portalContainer) || document.body;\n const content = (\n <ChatPeopleContext.Provider value={chat.people}>\n <ChatWindowShell key={chat.identity} {...chat.windowProps}\n BattleshipPreviewComponent={BattleshipPreviewComponent}\n placement=\"page\" theme={theme} standalone\n isOpen={layout.isOpen} isMaximized={layout.isMaximized} isMinimized={false} />\n </ChatPeopleContext.Provider>\n );\n return createPortal(className ? <div className={className}>{content}</div> : content, target);\n}\n","/* eslint-disable react/prop-types */\nimport { MessageCircle } from 'lucide-react';\nimport { useChatUnread, totalUnread } from '../../core/unread/unreadMessages.js';\nimport { chatUiStore, useChatUi } from './chatUiStore.js';\n\n/**\n * Chat launcher with the total unread badge. Without `onClick` it toggles chatUiStore\n * (the uncontrolled ChatWindow); with `onClick` the host owns the open state and may pass `pressed`.\n * Does not require LiraChatProvider (unread counts live in the package unread store).\n */\nexport default function ChatButton({ className, label = 'Chat', onClick, pressed, badgeClassName, iconSize = 17 }) {\n const unread = useChatUnread(totalUnread);\n const storeOpen = useChatUi((state) => state.isOpen);\n const isPressed = pressed ?? (onClick ? undefined : storeOpen);\n return (\n <button type=\"button\" className={className ?? 'mc-chat mc-chat-button'}\n onClick={(event) => { if (onClick) onClick(event); else chatUiStore.getState().toggle(); }}\n aria-label={unread ? `${label}, ${unread} mensajes nuevos` : label}\n aria-pressed={isPressed} title={label}>\n <MessageCircle size={iconSize} aria-hidden=\"true\" />\n {unread > 0 && <span className={badgeClassName ?? 'mc-chat-button__badge'}>{unread > 99 ? '99+' : unread}</span>}\n </button>\n );\n}\n","/*\n * Mirrors the total chat unread count on the installed app icon (Badging API).\n * Works from window context; no service worker changes needed.\n * Support: Chromium/Edge installed PWAs on Windows/macOS/ChromeOS, macOS Safari 17+\n * \"Add to Dock\" web apps, iOS/iPadOS 16.4+ Home Screen web apps only after notification\n * permission is granted. Not supported: Android Chrome (badge dots come only from\n * notifications), Firefox, or regular browser tabs (calls are no-ops or reject).\n */\nimport { useChatUnread, totalUnread } from '../core/unread/unreadMessages.js';\n\nconst running = new WeakMap();\n\n// onFail lets the caller forget the applied value so the next store change retries it.\nconst call = (nav, method, onFail, ...args) => {\n try {\n const result = nav[method](...args);\n if (result && typeof result.catch === 'function') result.catch(onFail);\n } catch { /* NotAllowedError / SecurityError (iframes, insecure contexts, iOS without permission). */ onFail(); }\n};\n\n/** True when startAppBadge() is already mirroring `store` (someone else owns its stop()). */\nexport const isAppBadgeRunning = (store = useChatUnread) => running.has(store);\n\nexport function startAppBadge({ store = useChatUnread, nav = globalThis.navigator, schedule = queueMicrotask } = {}) {\n if (running.has(store)) return running.get(store);\n if (!nav || !('setAppBadge' in nav)) {\n const noop = () => {};\n running.set(store, noop);\n return noop;\n }\n let last;\n let pending = false;\n const apply = () => {\n pending = false;\n const state = store.getState();\n const total = state.scope ? totalUnread(state) : 0;\n if (total === last) return;\n last = total;\n const retry = () => { if (last === total) last = undefined; };\n if (total > 0) call(nav, 'setAppBadge', retry, total);\n else if ('clearAppBadge' in nav) call(nav, 'clearAppBadge', retry);\n else call(nav, 'setAppBadge', retry, 0);\n };\n apply();\n const unsubscribe = store.subscribe(() => {\n if (pending) return;\n pending = true;\n schedule(apply);\n });\n const stop = () => {\n unsubscribe();\n running.delete(store);\n };\n running.set(store, stop);\n return stop;\n}\n","import { useEffect } from 'react';\nimport { startDesktopNotifications } from '../../notifications/desktopNotifications.js';\nimport { startAppBadge, isAppBadgeRunning } from '../../notifications/appBadge.js';\nimport { initChatSounds } from '../../notifications/chatSounds.js';\nimport { startConnect4Sounds, isConnect4SoundsRunning } from '../../games/connect4/connect4Sounds.js';\nimport { useChatConfig } from '../../provider/hooks.js';\n\n/**\n * Renders nothing. While mounted keeps desktop notifications, the app icon badge and\n * chat/game sounds running. Safe when the host also starts them: desktop notifications are\n * ref-counted, and idempotent services already started elsewhere are left to their owner.\n */\nexport default function ChatNotifications() {\n const notifications = useChatConfig()?.notifications;\n const enabled = notifications !== false;\n const desktop = enabled && notifications?.desktop !== false;\n const badge = enabled && notifications?.appBadge !== false;\n const sound = enabled && notifications?.sound !== false;\n\n useEffect(() => (desktop ? startDesktopNotifications() : undefined), [desktop]);\n useEffect(() => {\n if (!badge || isAppBadgeRunning()) return undefined;\n return startAppBadge();\n }, [badge]);\n useEffect(() => {\n if (!sound) return undefined;\n initChatSounds(); // idempotent, no teardown\n if (isConnect4SoundsRunning()) return undefined;\n return startConnect4Sounds();\n }, [sound]);\n return null;\n}\n","import { randomUuid } from '../ids/randomUuid.js';\n// File bytes only live in connected browsers. The server relays 32 KB frames.\nconst MAX_BYTES = 10 * 1024 * 1024;\nconst sessions = new WeakMap();\nconst sessionFor = (socket) => {\n if (!sessions.has(socket)) sessions.set(socket, { pending: new Map(), files: new Map() });\n return sessions.get(socket);\n};\n\nexport function relayRequest(socket, action, payload) {\n if (socket?.readyState !== WebSocket.OPEN) return Promise.reject(new Error('Sin conexión'));\n const state = sessionFor(socket);\n const request_id = randomUuid();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n state.pending.delete(request_id);\n reject(new Error('El servidor no confirmó el envío. Conservamos el borrador.'));\n }, 15000);\n state.pending.set(request_id, { resolve, reject, timer });\n socket.send(JSON.stringify({ action, payload: { ...payload, request_id } }));\n });\n}\n\nexport function consumeRelayEvent(socket, event) {\n const state = sessionFor(socket);\n const data = event.data || event.payload || {};\n if (event.event === 'CHAT_ACK' || event.event === 'ERROR' || event.type === 'ERROR') {\n const pending = state.pending.get(data.request_id);\n if (pending) {\n clearTimeout(pending.timer);\n state.pending.delete(data.request_id);\n if (event.event === 'CHAT_ACK') pending.resolve();\n else pending.reject(new Error(data.message || 'No se pudo enviar'));\n return true;\n }\n // Unknown ACKs belong to another requester (e.g. the shared-socket adapter); let them through.\n return false;\n }\n if (event.event !== 'CHAT_FILE') return false;\n const now = Date.now();\n for (const [id, file] of state.files) {\n if (now - file.created > 60000) state.files.delete(id);\n }\n if (!Number.isInteger(data.size) || data.size <= 0 || data.size > MAX_BYTES) return true;\n if (data.index === 0) {\n if (state.files.size >= 4) return true;\n state.files.set(data.id, { parts: [], bytes: 0, index: 0, created: now, room: data.room_id, user: data.user_id });\n }\n const file = state.files.get(data.id);\n if (!file || file.index !== data.index || file.room !== data.room_id || file.user !== data.user_id) return true;\n const raw = atob(data.chunk);\n const bytes = Uint8Array.from(raw, (c) => c.charCodeAt(0));\n file.bytes += bytes.length;\n if (file.bytes > data.size || bytes.length > 32768) { state.files.delete(data.id); return true; }\n file.parts.push(bytes);\n file.index++;\n if (data.final && file.bytes === data.size) file.blob = new Blob(file.parts, { type: data.type });\n return true;\n}\n\nexport function hydrateRelayMessage(socket, message) {\n const state = sessionFor(socket);\n return { ...message, attachments: (message.attachments || []).map((item) => {\n if (item.kind === 'gif') return item;\n const file = state.files.get(item.id);\n state.files.delete(item.id);\n if (!file?.blob || file.room !== message.room_id || file.user !== message.user_id) return { ...item, name: `${item.name} (no disponible)` };\n return { ...item, url: URL.createObjectURL(file.blob) };\n }) };\n}\n\nexport function closeRelay(socket) {\n const state = sessions.get(socket);\n if (!state) return;\n state.pending.forEach(({ reject, timer }) => { clearTimeout(timer); reject(new Error('Conexión interrumpida. Reintenta el envío.')); });\n state.pending.clear();\n state.files.clear();\n}\n\nexport async function sendRelayMessage(socket, roomId, message, attachments = []) {\n if (attachments.length > 1) throw new Error('Envía un archivo o GIF por mensaje.');\n const outgoing = [];\n for (const attachment of attachments) {\n if (attachment.kind === 'gif') {\n outgoing.push({ kind: 'gif', url: attachment.url, name: attachment.name });\n continue;\n }\n const file = attachment.file;\n if (!(file instanceof Blob) || !file.size || file.size > MAX_BYTES) throw new Error('El archivo debe pesar entre 1 byte y 10 MB.');\n const id = randomUuid();\n for (let start = 0, index = 0; start < file.size; start += 32768, index++) {\n const bytes = new Uint8Array(await file.slice(start, start + 32768).arrayBuffer());\n const chunk = btoa(String.fromCharCode(...bytes));\n await relayRequest(socket, 'CHAT_FILE', {\n id, room_id: roomId, size: file.size, type: file.type || 'application/octet-stream',\n name: attachment.name, index, chunk,\n });\n }\n outgoing.push({ id });\n }\n await relayRequest(socket, 'CHAT_MESSAGE', { room_id: roomId, message, attachments: outgoing });\n}\n","import { lazy } from 'react';\n\n// Public WebRTC surface (TANQUES LIVE groundwork). The lab UI is a separate chunk.\nexport { createPeerLink, DEFAULT_ICE_SERVERS } from './createPeerLink.js';\nexport { rtcSignals, createChatSignaling } from './rtcSignals.js';\nexport { withSignalFaults } from './signalFaults.js';\nexport { WEBRTC_PREFIX, MAX_SIGNAL_LENGTH, isWebrtcMessage, encodeSignal, decodeSignal } from './protocol.js';\nexport const WebRtcLab = lazy(() => import('./WebRtcLab.jsx'));\n","// @minicode-dev/chat public API. Only what is exported here is supported; internal\n// paths may change between versions. See README.md and, in the LIRA repo,\n// docs/MBSoft-Chat-NPM-Migration.md for the migration status.\nimport './styles.css';\n\nexport const MINICODE_CHAT_VERSION = '0.1.0';\n\n// Provider, configuration and hooks\nexport { LiraChatProvider } from './provider/LiraChatProvider.jsx';\nexport { ChatContext, useChatContext } from './provider/ChatContext.js';\nexport { useChatStore, useChatStoreApi, useChatConfig, useChatTransport, useChatConnection, useChatUnreadTotal, useChatIdentity } from './provider/hooks.js';\nexport { normalizeConfig, normalizeUser, DEFAULT_CONFIG } from './config/normalizeConfig.js';\n\n// Transport\nexport { createStandaloneTransport } from './core/transport/createStandaloneTransport.js';\nexport { TRANSPORT_STATUSES, assertTransport } from './core/transport/chatTransport.js';\nexport { chatConnectionStore, setChatConnectionStatus, useChatConnectionStatus } from './core/connection/connectionStore.js';\n\n// Chat domain store (messages, rooms, presence, user search) over a ChatTransport\nexport { createChatStore, MAX_CHAT_MESSAGES } from './core/chat/createChatStore.js';\n\n// Protocol helpers (wire format is frozen; see test/contract)\nexport {\n EDIT_PREFIX, REACT_PREFIX, STICKER_NAME_PREFIX, encodeEdit, encodeReaction, parseMessageAction,\n isMessageAction, isStickerAttachment, groupReactions,\n} from './core/extras/messageExtras.js';\n\n// Media configuration\nexport { configureKlipy } from './media/klipy/klipy.js';\nexport { setChatAssetsBaseUrl, getChatAssetsBaseUrl } from './assets/chatAssets.js';\n\n// Connected components (decision §11, option A). Must be rendered inside LiraChatProvider,\n// except ChatButton and chatUiStore, which only use package-level stores.\nexport { default as ChatWindow } from './ui/connected/ChatWindow.jsx';\nexport { default as ChatPage } from './ui/connected/ChatPage.jsx';\nexport { default as ChatButton } from './ui/connected/ChatButton.jsx';\nexport { default as ChatNotifications } from './ui/connected/ChatNotifications.jsx';\nexport { chatUiStore, useChatUi } from './ui/connected/chatUiStore.js';\n\n// Unread counters (package singleton; also used by host badges)\nexport { useChatUnread, totalUnread, unreadScope, startUnreadStorageSync } from './core/unread/unreadMessages.js';\n\n// Host integration: background services a host starts once (see LIRA src/chat/startChat.js).\n// All starters are idempotent or ref-counted and return stop().\nexport { startDesktopNotifications } from './notifications/desktopNotifications.js';\nexport { startAppBadge } from './notifications/appBadge.js';\nexport { startChatApp, registerChatWorker, openChatWindow, useChatInstall } from './pwa/chatApp.js';\nexport { startGifLibrarySync } from './media/gif-search/gifLibrary.js';\nexport { startEmojiPreferencesSync } from './media/emoji/emojiPreferences.js';\nexport { chatGamesStore, useChatGames } from './games/shared/useChatGames.js';\nexport { startConnect4Sounds } from './games/connect4/connect4Sounds.js';\n// File relay over a raw WebSocket (hosts that share their own socket, like LIRA).\nexport { consumeRelayEvent, hydrateRelayMessage, closeRelay, sendRelayMessage } from './core/relay/fileRelay.js';\n// Battleship 3D preview (three.js) stays out of the main chunk.\nexport const loadBattleshipPreview = () => import('./games/battleship/BattleshipPrototype.jsx');\n\n// UI primitives (presentational)\nexport { default as ChatWindowShell } from './ui/components/ChatWindow.jsx';\nexport { default as MessageList } from './ui/components/MessageList.jsx';\nexport { default as MessageBubble } from './ui/components/MessageBubble.jsx';\nexport { default as MessageComposer } from './ui/components/MessageComposer.jsx';\nexport { default as EmojiPicker } from './ui/components/EmojiPicker.jsx';\nexport { default as GifPicker } from './ui/components/GifPicker.jsx';\nexport { default as StickerPicker } from './ui/components/StickerPicker.jsx';\nexport { ChatPeopleContext } from './ui/chatPeopleContext.js';\n\n// Original audiovisual chat effects (ordinary versioned text messages).\nexport { EFFECT_CATALOG, getChatEffect } from './effects/catalog.js';\nexport { EFFECT_PREFIX, encodeEffect, decodeEffect } from './effects/protocol.js';\n\n// WebRTC peer links signaled through the chat (LIRA_WEBRTC_V1:) and the lab UI (lazy chunk).\nexport {\n createPeerLink, DEFAULT_ICE_SERVERS, rtcSignals, createChatSignaling, withSignalFaults,\n WEBRTC_PREFIX, MAX_SIGNAL_LENGTH, isWebrtcMessage, encodeSignal, decodeSignal, WebRtcLab,\n} from './net/webrtc/index.js';\n"],"mappings":"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"}