WhatsApp Web Plus

Making WhatsApp web more accessible for visually impaired users

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         WhatsApp Web Plus
// @author       Muhammad Gagah
// @namespace    https://github.com/muhammadGagah/whatsapp-web-plus
// @version      2.6.73
// @description  Making WhatsApp web more accessible for visually impaired users
// @match        https://web.whatsapp.com/*
// @run-at       document-start
// @grant        none
// @license      MIT
// ==/UserScript==
// Generated from src/; do not edit this file directly.
(() => {
  // src/config.js
  var SCRIPT_VERSION = "2.6.73";
  var IS_DEBUG_BUILD = false;
  var SHORTCUT_RENDER_RETRIES = 12;
  var ALT_T_DOUBLE_PRESS_MS = 300;
  var CHAT_LIST_TOP_FALLBACK_MAX_Y = 1e3;
  var CLEAN_UI_HIDDEN_ATTRIBUTE = "data-wa-plus-clean-ui-hidden";
  var STORAGE_KEYS = Object.freeze({
    privacy: "wa-plus-privacy",
    cleanUi: "wa-plus-clean-ui",
    originalDark: "wa-plus-original-dark",
    language: "wa-plus-language",
    reduceAnnouncements: "wa-plus-reduce-announcements",
    automaticReading: "wa-plus-automatic-reading",
    statusReadingCleanup: "wa-plus-status-reading-cleanup",
    senderDeviceAnnouncements: "wa-plus-sender-device-announcements",
    openChatsAtFirstUnread: "wa-plus-open-chats-at-first-unread",
    remapVoiceRecording: "wa-plus-remap-voice-recording",
    remapPreviousChat: "wa-plus-remap-previous-chat",
    remapNextChat: "wa-plus-remap-next-chat",
    chatActivity: "wa-plus-chat-activity-monitor",
    audioExperiment: "wa-plus-audio-experiment",
    audioExperimentProfile: "wa-plus-audio-experiment-profile",
    audioExperimentReports: "wa-plus-audio-experiment-reports",
    callAudioExperiment: "wa-plus-call-audio-experiment",
    callAudioExperimentProfile: "wa-plus-call-audio-experiment-profile",
    customUnreadDivider: "wa-plus-custom-unread-divider",
    customTypingText: "wa-plus-custom-typing-text",
    customRecordingAudioText: "wa-plus-custom-recording-audio-text",
    customDeliveryStatus: "wa-plus-custom-delivery-status",
    customDesktopPromo: "wa-plus-custom-desktop-promo",
    customRecentSearches: "wa-plus-custom-recent-searches",
    customClearAll: "wa-plus-custom-clear-all",
    customNavChats: "wa-plus-custom-nav-chats",
    customNavStatus: "wa-plus-custom-nav-status",
    customNavCommunities: "wa-plus-custom-nav-communities",
    customNavChannels: "wa-plus-custom-nav-channels",
    customNavMetaAI: "wa-plus-custom-nav-meta-ai",
    customMessageContextInstruction: "wa-plus-custom-message-context-instruction",
    customUnknownContactPrefix: "wa-plus-custom-unknown-contact-prefix",
    customParticipantPrefix: "wa-plus-custom-participant-prefix",
    customQuotePrefix: "wa-plus-custom-quote-prefix",
    customOnlineStatus: "wa-plus-custom-online-status",
    customLastSeenPrefix: "wa-plus-custom-last-seen-prefix",
    customChatStatusLabels: "wa-plus-custom-chat-status-labels",
    customViewStatus: "wa-plus-custom-view-status",
    customParticipantSeparator: "wa-plus-custom-participant-separator",
    customStatusPauseLabels: "wa-plus-custom-status-pause-labels",
    customStatusReadMoreLabels: "wa-plus-custom-status-read-more-labels",
    customStatusMediaFallback: "wa-plus-custom-status-media-fallback",
    customScrollToBottom: "wa-plus-custom-scroll-to-bottom",
    customDeliveryPending: "wa-plus-custom-delivery-pending",
    customDeliverySent: "wa-plus-custom-delivery-sent",
    customDeliveryDelivered: "wa-plus-custom-delivery-delivered",
    customDeliveryRead: "wa-plus-custom-delivery-read"
  });
  var SELECTORS = Object.freeze({
    side: "div#side",
    main: "div#main",
    messageInput: 'div#main footer div[contenteditable="true"]',
    navChats: '[data-testid="navbar-primary-section"] button[aria-label="Chats"], [data-testid="navbar-primary-section"] button[aria-label="Chat"]',
    navStatus: '[data-testid="navbar-primary-section"] button[aria-label="Status"], [data-testid="navbar-primary-section"] button[aria-label="Updates in Status"]',
    statusPlayerRoot: '[data-testid="status-player-uie"]',
    statusActiveMarker: '[data-animate-status-viewer="true"]',
    statusContactName: '[data-testid="status-player-contact-name"]',
    statusText: '[data-testid="status-text"]',
    statusVideo: '[data-testid="status-video"]',
    statusVoice: '[data-testid="ptt-status"]',
    statusAudio: "audio",
    statusImage: '[data-testid="status-image"]',
    statusAttribution: '[data-testid="status-subtitle-attribution-content"]',
    statusTitle: '[data-testid="music-attribution-song-metadata"]',
    statusProgressSegment: '[data-testid="status-progress-bar-segment"]',
    navCommunities: '[data-testid="navbar-primary-section"] button[aria-label="Communities"], [data-testid="navbar-primary-section"] button[aria-label="Komunitas"]',
    navChannels: '[data-testid="navbar-primary-section"] button[aria-label="Channels"], [data-testid="navbar-primary-section"] button[aria-label="Saluran"]',
    navMetaAI: '[data-testid="navbar-primary-section"] button[aria-label="Meta AI"]',
    videoPlayerClose: '[data-testid="move_resize_component"] button[aria-label="Close"], [data-testid="move_resize_component"] button[aria-label="Tutup"], [data-testid="move_resize_component"] button[data-icon="x"], [data-testid="media-viewer-modal"] button[aria-label="Close"], [data-testid="media-viewer-modal"] button[aria-label="Tutup"], [data-testid="media-viewer-modal"] button[data-icon="x"]',
    audioPlayerClose: '#side button[data-icon="x"], #side button[aria-label="Close"], #side button[aria-label="Tutup"]',
    statusListFirstRow: '[data-testid="status-list-drawer"] [data-testid="status-row-cell"]',
    communityListFirstRow: '[data-testid="community-tab-drawer"] [data-testid="community-tab-community-cell"]',
    channelListFirstRow: '[data-testid="newsletter-tab-drawer"] [data-testid="newsletter-tab-newsletter-cell"]',
    chatListScroller: "#pane-side",
    chatList: '[data-testid="chat-list"], [aria-label="Chat list"][role="grid"], [aria-label="Daftar chat"][role="grid"]',
    chatListInSide: '#side [data-testid="chat-list"], #side [aria-label="Chat list"][role="grid"], #side [aria-label="Daftar chat"][role="grid"]',
    chatSearch: '#side input[role="textbox"][type="text"], #side [data-testid="chat-list-search-container"] input',
    conversationMessages: '[data-testid="conversation-panel-messages"]',
    cellFrame: '[data-testid="cell-frame-container"]'
  });
  var OWNERS = Object.freeze({
    chatLabel: "chat-label",
    chatHidden: "chat-hidden",
    chatStructure: "chat-structure",
    messageGrid: "message-grid",
    messageCell: "message-cell",
    metaAIMessageName: "meta-ai-message-name",
    cleanUiHidden: "clean-ui-hidden",
    statusViewer: "status-viewer"
  });
  var CHAT_LABEL_NOISE_RE = Object.freeze({
    iconName: /^(?:wds-)?ic-(?:expand-more|read|check|dblcheck|msg-time|notifications-off)\b/i,
    rawIconName: /^(?:wds-)?ic-[a-z0-9-]+$/i,
    structuralName: /^(?:default|status|msg|chat-msg-symbol|read-receipt|sender|lock)-?[a-z0-9-]*$/i,
    ignoredIconIdentity: /expand-more|read-receipt|dblcheck|checkmark|default-(?:group|user|broadcast)-refreshed/i,
    potentialIconTestId: /(?:icon|symbol|mute|pin|document|image|video|voice|phone|call|sticker|gif)/i
  });
  var CHAT_PREVIEW_ICON_LABELS = Object.freeze([
    { pattern: /keyboard-voice|voice-filled|ptt|audio-ptt|voice-message/i, labelKey: "voiceMessage" },
    { pattern: /document-refreshed|document-thin|ic-document|file-document|\bdocument\b/i, labelKey: "document" },
    { pattern: /video-call/i, labelKey: "videoCall" },
    { pattern: /phone-callback|phone-incoming|voice-call|\bcall\b/i, labelKey: "voiceCall" },
    { pattern: /ic-image|image-refreshed|media-image|\bimage\b/i, labelKey: "image" },
    { pattern: /ic-video|video-refreshed|\bvideo\b/i, labelKey: "video" },
    { pattern: /sticker/i, labelKey: "sticker" },
    { pattern: /\bgif\b/i, labelKey: "gif" }
  ]);
  var FOCUSABLE_SELECTOR = 'a[href], button, input, textarea, select, details, iframe, object, embed, [contenteditable="true"], [tabindex], [role="button"], [role="link"], [role="textbox"], [role="checkbox"], [role="menuitem"]';
  var CHAT_ROW_NATIVE_TEXT_SELECTOR = '[data-testid="cell-frame-label"], [data-testid="cell-frame-title"], [data-testid="cell-frame-primary-detail"], [data-testid="cell-frame-secondary"], [data-testid="last-msg-status"], [role="gridcell"], [aria-label], [title]';
  var CLEAN_UI_PROTECTED_SELECTOR = '#side, #pane-side, #main, nav, [role="navigation"], [role="tooltip"], [data-testid="chat-list"], [aria-label="Chat list"], [aria-label="Daftar chat"], [role="grid"]';
  var DESKTOP_APP_PROMO_COPY_RE = /^Get extra features like voice and video calling, screen sharing and more\.?$/i;
  var MESSAGE_TEXT_CONTENT_SELECTOR = '[data-testid="msg-container"] [data-testid="selectable-text"]';
  var MESSAGE_MEDIA_CONTENT_SELECTOR = [
    '[data-testid="msg-container"] img[alt]',
    '[data-testid="msg-container"] video',
    '[data-testid="msg-container"] audio',
    '[data-testid="msg-container"] a[href]',
    '[data-testid="msg-container"] [data-testid*="audio"]',
    '[data-testid="msg-container"] [data-testid*="document"]',
    '[data-testid="msg-container"] [data-testid*="image"]',
    '[data-testid="msg-container"] [data-testid*="video"]',
    '[data-testid="msg-container"] [data-testid*="sticker"]',
    '[data-testid="msg-container"] [data-testid*="poll"]',
    '[data-testid="msg-container"] [data-testid*="location"]',
    '[data-testid="msg-container"] [data-testid*="contact"]'
  ].join(", ");
  var PHONE_RE = /(?:\+\s*)?\d[\d\s()./‐‑‒–—―-]{5,}\d/g;
  var PHONE_URL_RE = /\b(?:https?:\/\/)?(?:wa\.me\/|phone=)(?:\+\s*)?\d[\d\s()./‐‑‒–—―-]{5,}\d\b/gi;
  var WEB_URL_RE = /(?:https?:\/\/|www\.)[^\s<>"']+/gi;

  // src/locales/en.js
  var en_default = {
    settings: "WhatsApp Web Plus settings",
    language: "Language",
    accessibility: "Accessibility",
    voiceRecording: "Voice message recording",
    voiceCalls: "Voice calls",
    keyboardShortcuts: "Shortcut remapping",
    appearance: "Appearance",
    privacyMode: "Privacy mode",
    reduceAnnouncements: "Remove repeated or unhelpful screen-reader announcements",
    automaticReading: "Automatically read new messages",
    statusReadingCleanup: "Clean Status reading",
    senderDeviceAnnouncements: "Announce sender device",
    audioProfiles: "Voice-message recording profile",
    audioProfileWhatsApp: "WhatsApp default (no processing)",
    audioProfileNatural: "Natural (raw 48 kilohertz, no equalizer)",
    audioProfileClear: "Clear (balanced)",
    audioProfileClearPlus: "Clear Plus (stronger and more even)",
    audioProfileNoiseFilter: "Noise filter (noisy rooms)",
    callAudioProfiles: "Call microphone profile",
    callAudioProfileWhatsApp: "WhatsApp default (WhatsApp controls audio)",
    callAudioProfileRaw: "Raw (requests browser input processing off; use headphones)",
    callAudioProfileNatural: "Natural (browser call processing only)",
    callAudioProfileClear: "Clear (light voice equalizer)",
    callAudioProfileNoiseFilter: "Noise filter (stronger background-noise reduction)",
    copyCallDiagnostics: "Copy voice and video call microphone configuration diagnostics",
    callDiagnosticsCopied: "Voice and video call microphone configuration diagnostics copied to the clipboard.",
    callDiagnosticsCopyFailed: "Voice and video call microphone configuration diagnostics could not be copied.",
    callDiagnosticsUnavailable: "No voice or video call microphone configuration diagnostics are available yet. Make or answer a call, then try again.",
    copyVoiceMessageDiagnostics: "Copy focused voice-message audio diagnostics",
    voiceMessageDiagnosticsAnalyzing: "Analyzing the focused voice message.",
    voiceMessageDiagnosticsCopied: "Focused voice-message audio diagnostics copied to the clipboard.",
    voiceMessageDiagnosticsCopyFailed: "Focused voice-message audio diagnostics could not be copied.",
    voiceMessageDiagnosticsUnavailable: "No focused voice message was found. Focus a voice message, then open this menu again.",
    openChatsAtFirstUnread: "Open chats at first unread message",
    remapVoiceRecording: "Use Alt+M to start voice recording",
    remapPreviousChat: "Use Alt+Up Arrow for previous chat",
    remapNextChat: "Use Alt+Down Arrow for next chat",
    customLanguageStrings: "Custom language strings",
    unreadDividerText: "Unread divider text: {value}",
    typingIndicatorText: "Typing indicator text: {value}",
    recordingAudioIndicatorText: "Recording voice message indicator text: {value}",
    deliveryStatusText: "Additional delivery status labels, separated by comma or |: {value}",
    deliveryPendingText: "Pending delivery status text: {value}",
    deliverySentText: "Sent delivery status text: {value}",
    deliveryDeliveredText: "Delivered delivery status text: {value}",
    deliveryReadText: "Read delivery status text: {value}",
    desktopAppPromoText: "Desktop app promo title: {value}",
    desktopAppPromoDefault: "Download WhatsApp for Windows",
    recentSearchesText: "Recent searches button text: {value}",
    clearAllText: "Clear all button text: {value}",
    navChatsText: "Chats button accessible name: {value}",
    navStatusText: "Status button accessible name: {value}",
    navCommunitiesText: "Communities button accessible name: {value}",
    navChannelsText: "Channels button accessible name: {value}",
    navMetaAIText: "Meta AI button accessible name: {value}",
    messageContextInstructionText: "Message context-menu instruction: {value}",
    unknownContactPrefixText: "Unknown-contact prefix: {value}",
    participantPrefixText: "Participant word or prefix: {value}",
    quotePrefixText: "Quoted-message-from phrase: {value}",
    onlineStatusText: "Online status text: {value}",
    lastSeenPrefixText: "Last seen prefix: {value}",
    chatStatusLabelsText: "Chat status labels, separated by |: {value}",
    viewStatusText: "View status action text: {value}",
    participantSeparatorText: "Participant list separator: {value}",
    statusPauseLabelsText: "Status Pause control names, separated by |: {value}",
    statusReadMoreLabelsText: "Status Read more/less control names, separated by |: {value}",
    statusMediaFallbackText: "Status media fallback name: {value}",
    scrollToBottomText: "Scroll to bottom button accessible name: {value}",
    editCustomText: "Edit {name}",
    customTextInstruction: "Enter custom text. Leave blank to reset to default.",
    customTextSaved: "{name} saved",
    customTextReset: "{name} reset to default",
    defaultLabel: "(default)",
    customValueSet: "(custom value set)",
    cancel: "Cancel",
    save: "Save",
    chatActivity: "Chat activity monitor",
    cleanUi: "Clean UI",
    originalDark: "Original dark mode",
    openUpdate: "Open WhatsApp Web Plus update in Tampermonkey",
    updateOpenFailed: "Could not open the Tampermonkey update page",
    chats: "Chats",
    status: "Status",
    communities: "Communities",
    channels: "Channels",
    metaAi: "Meta AI",
    participant: "Participant",
    phoneLink: "Phone number link",
    messageHistory: "Message history",
    unknownContact: "Maybe",
    deliveryPending: "Pending",
    deliverySent: "Sent",
    deliveryDelivered: "Delivered",
    deliveryRead: "Read",
    sentFromDevice: "Sent from {device}",
    deviceIPhone: "iPhone",
    deviceMac: "Mac",
    deviceIPad: "iPad",
    deviceAndroid: "Android",
    deviceWebDesktop: "WhatsApp Web or Desktop",
    messageStatusSingle: "Message status: {status}",
    messageStatusPlural: "{count} messages status: {status}",
    typingActivity: "{name} {verb} typing{suffix}",
    typingActivityCount: "{count} participants are typing{suffix}",
    recordingAudioActivity: "{name} {verb} recording a voice message{suffix}",
    recordingAudioActivityCount: "{count} participants are recording a voice message{suffix}",
    andOthers: "{names} and {count} others",
    online: "online",
    lastSeen: "last seen{details}",
    recordingAudio: "recording a voice message{details}",
    unreadMessages: "unread messages",
    newMessages: "new messages",
    mutedChat: "muted chat",
    pinnedChat: "pinned chat",
    archivedChat: "archived chat",
    draft: "draft",
    typingStatus: "typing",
    voiceMessage: "voice message",
    document: "document",
    videoCall: "video call",
    voiceCall: "voice call",
    image: "image",
    video: "video",
    statusMediaFallback: "Media",
    statusSummarySeparator: ". ",
    statusPauseDefaultLabels: "Pause",
    statusReadMoreDefaultLabels: "Read more",
    statusReadLessDefaultLabels: "Read less",
    scrollToBottomDefault: "Scroll to bottom",
    sticker: "sticker",
    gif: "GIF",
    buttonNotFound: "{name} button not found",
    didNotOpen: "{name} did not open",
    listEmpty: "{name} list is empty",
    couldNotFocus: "{name} could not be focused",
    chatListEmpty: "Chat list empty",
    chatNotReady: "Chat is not ready",
    noMessages: "No messages",
    messageNotReady: "Message is not ready",
    unreadHistoryOnly: "Alt 3 only works in the message history",
    noOpenChat: "No open chat",
    unreadNotFound: "Unread message not found",
    unreadNotReady: "Unread message is not ready",
    mediaNotOpen: "Media player is not open.",
    mediaClosed: "Media player closed.",
    desktopPromoClosed: "Desktop app promotion closed.",
    messageBoxNotReady: "Message box is not ready",
    messageBoxNotOpen: "Message box is not open",
    noTitle: "No title found",
    titleNotFound: "Chat title not found",
    privacyOn: "Privacy Enabled",
    privacyOff: "Privacy Disabled",
    automaticReadingOn: "Automatic reading of messages is enabled",
    automaticReadingOff: "Automatic reading of new messages is disabled",
    chatActivityOn: "Chat activity monitor on",
    chatActivityOff: "Chat activity monitor off",
    cleanUiOn: "Clean UI enabled.",
    cleanUiOnHidden: "Clean UI enabled; extra controls hidden.",
    cleanUiOff: "Clean UI disabled.",
    darkOn: "Original Dark Mode Enabled",
    darkOff: "Original Dark Mode Disabled",
    statusTransitionDiagnosticStarted: "Status change diagnostic started. Play one video Status until it changes, then press Alt+Shift+7 again.",
    statusTransitionDiagnosticCopied: "Status change diagnostic stopped and copied. Paste it into debug_status_transition.txt.",
    statusTransitionDiagnosticCopyFailed: "Status change diagnostic stopped, but could not be copied. Press Alt+Shift+7 to retry.",
    saveError: "The setting could not be saved."
  };

  // src/locales/id.js
  var id_default = {
    settings: "Pengaturan WhatsApp Web Plus",
    language: "Bahasa",
    accessibility: "Aksesibilitas",
    voiceRecording: "Perekaman pesan suara",
    voiceCalls: "Panggilan suara",
    keyboardShortcuts: "Pemetaan ulang pintasan",
    appearance: "Tampilan",
    privacyMode: "Mode privasi",
    reduceAnnouncements: "Hapus pengumuman pembaca layar yang berulang atau tidak membantu",
    automaticReading: "Bacakan pesan baru secara otomatis",
    statusReadingCleanup: "Bersihkan pembacaan Status",
    senderDeviceAnnouncements: "Umumkan perangkat pengirim",
    audioProfiles: "Profil perekaman pesan suara",
    audioProfileWhatsApp: "Bawaan WhatsApp (tanpa pemrosesan)",
    audioProfileNatural: "Alami (mentah 48 kilohertz, tanpa ekualiser)",
    audioProfileClear: "Jernih (seimbang)",
    audioProfileClearPlus: "Jernih Plus (lebih kuat dan rata)",
    audioProfileNoiseFilter: "Peredam bising (ruangan berisik)",
    callAudioProfiles: "Profil mikrofon panggilan",
    callAudioProfileWhatsApp: "Bawaan WhatsApp (audio diatur oleh WhatsApp)",
    callAudioProfileRaw: "Mentah (meminta pemrosesan input browser dimatikan; gunakan headphone)",
    callAudioProfileNatural: "Alami (hanya pemrosesan panggilan dari browser)",
    callAudioProfileClear: "Jernih (ekualiser suara ringan)",
    callAudioProfileNoiseFilter: "Peredam bising (pengurangan suara latar lebih kuat)",
    copyCallDiagnostics: "Salin diagnostik konfigurasi mikrofon panggilan suara dan video",
    callDiagnosticsCopied: "Diagnostik konfigurasi mikrofon panggilan suara dan video disalin ke papan klip.",
    callDiagnosticsCopyFailed: "Diagnostik konfigurasi mikrofon panggilan suara dan video tidak dapat disalin.",
    callDiagnosticsUnavailable: "Belum ada diagnostik konfigurasi mikrofon panggilan suara atau video. Lakukan atau jawab panggilan, lalu coba lagi.",
    copyVoiceMessageDiagnostics: "Salin diagnostik audio pesan suara yang difokuskan",
    voiceMessageDiagnosticsAnalyzing: "Menganalisis pesan suara yang difokuskan.",
    voiceMessageDiagnosticsCopied: "Diagnostik audio pesan suara yang difokuskan disalin ke papan klip.",
    voiceMessageDiagnosticsCopyFailed: "Diagnostik audio pesan suara yang difokuskan tidak dapat disalin.",
    voiceMessageDiagnosticsUnavailable: "Tidak ada pesan suara yang difokuskan. Fokuskan pesan suara, lalu buka kembali menu ini.",
    openChatsAtFirstUnread: "Buka chat pada pesan pertama yang belum dibaca",
    remapVoiceRecording: "Gunakan Alt+M untuk mulai merekam pesan suara",
    remapPreviousChat: "Gunakan Alt+Panah atas untuk chat sebelumnya",
    remapNextChat: "Gunakan Alt+Panah bawah untuk chat berikutnya",
    customLanguageStrings: "Teks bahasa khusus",
    unreadDividerText: "Teks pemisah pesan belum dibaca: {value}",
    typingIndicatorText: "Teks indikator mengetik: {value}",
    recordingAudioIndicatorText: "Teks indikator merekam pesan suara: {value}",
    deliveryStatusText: "Label status pengiriman tambahan, pisahkan dengan koma atau |: {value}",
    deliveryPendingText: "Teks status pengiriman tertunda: {value}",
    deliverySentText: "Teks status pesan terkirim: {value}",
    deliveryDeliveredText: "Teks status pesan tersampaikan: {value}",
    deliveryReadText: "Teks status pesan dibaca: {value}",
    desktopAppPromoText: "Judul promo aplikasi desktop: {value}",
    desktopAppPromoDefault: "Unduh WhatsApp untuk Windows",
    recentSearchesText: "Teks tombol pencarian terkini: {value}",
    clearAllText: "Teks tombol hapus semua: {value}",
    navChatsText: "Nama aksesibel tombol Chat: {value}",
    navStatusText: "Nama aksesibel tombol Status: {value}",
    navCommunitiesText: "Nama aksesibel tombol Komunitas: {value}",
    navChannelsText: "Nama aksesibel tombol Saluran: {value}",
    navMetaAIText: "Nama aksesibel tombol Meta AI: {value}",
    messageContextInstructionText: "Instruksi menu konteks pesan: {value}",
    unknownContactPrefixText: "Awalan kontak tidak dikenal: {value}",
    participantPrefixText: "Kata atau awalan peserta: {value}",
    quotePrefixText: "Frasa pesan yang dikutip dari: {value}",
    onlineStatusText: "Teks status online: {value}",
    lastSeenPrefixText: "Awalan terakhir dilihat: {value}",
    chatStatusLabelsText: "Label status chat, pisahkan dengan |: {value}",
    viewStatusText: "Teks tindakan lihat status: {value}",
    participantSeparatorText: "Pemisah daftar peserta: {value}",
    statusPauseLabelsText: "Nama kontrol Jeda Status, pisahkan dengan |: {value}",
    statusReadMoreLabelsText: "Nama kontrol Baca selengkapnya/lebih sedikit Status, pisahkan dengan |: {value}",
    statusMediaFallbackText: "Nama pengganti media Status: {value}",
    scrollToBottomText: "Nama aksesibel tombol Gulir ke bawah: {value}",
    editCustomText: "Edit {name}",
    customTextInstruction: "Masukkan teks khusus. Kosongkan untuk kembali ke bawaan.",
    customTextSaved: "{name} disimpan",
    customTextReset: "{name} di-reset ke bawaan",
    defaultLabel: "(bawaan)",
    customValueSet: "(nilai khusus tersimpan)",
    cancel: "Batal",
    save: "Simpan",
    chatActivity: "Monitor aktivitas chat",
    cleanUi: "Antarmuka ringkas",
    originalDark: "Mode gelap asli",
    openUpdate: "Buka pembaruan WhatsApp Web Plus di Tampermonkey",
    updateOpenFailed: "Tidak dapat membuka halaman pembaruan Tampermonkey",
    chats: "Chat",
    status: "Status",
    communities: "Komunitas",
    channels: "Saluran",
    metaAi: "Meta AI",
    participant: "Peserta",
    phoneLink: "Tautan nomor telepon",
    messageHistory: "Riwayat pesan",
    unknownContact: "Mungkin",
    deliveryPending: "Tertunda",
    deliverySent: "Terkirim",
    deliveryDelivered: "Disampaikan",
    deliveryRead: "Dibaca",
    sentFromDevice: "Dikirim dari {device}",
    deviceIPhone: "iPhone",
    deviceMac: "Mac",
    deviceIPad: "iPad",
    deviceAndroid: "Android",
    deviceWebDesktop: "WhatsApp Web atau Desktop",
    messageStatusSingle: "Status pesan: {status}",
    messageStatusPlural: "{count} status pesan: {status}",
    typingActivity: "{name} sedang mengetik{suffix}",
    typingActivityCount: "{count} peserta sedang mengetik{suffix}",
    recordingAudioActivity: "{name} sedang merekam pesan suara{suffix}",
    recordingAudioActivityCount: "{count} peserta sedang merekam pesan suara{suffix}",
    andOthers: "{names} dan {count} lainnya",
    online: "online",
    lastSeen: "terakhir dilihat{details}",
    recordingAudio: "sedang merekam pesan suara{details}",
    unreadMessages: "pesan belum dibaca",
    newMessages: "pesan baru",
    mutedChat: "chat dibisukan",
    pinnedChat: "chat disematkan",
    archivedChat: "chat diarsipkan",
    draft: "draf",
    typingStatus: "mengetik",
    voiceMessage: "pesan suara",
    document: "dokumen",
    videoCall: "panggilan video",
    voiceCall: "panggilan suara",
    image: "gambar",
    video: "video",
    statusMediaFallback: "Media",
    statusSummarySeparator: ". ",
    statusPauseDefaultLabels: "Jeda|Pause",
    statusReadMoreDefaultLabels: "Baca selengkapnya|Read more",
    statusReadLessDefaultLabels: "Baca lebih sedikit|Read less",
    scrollToBottomDefault: "Gulir ke bawah",
    sticker: "stiker",
    gif: "GIF",
    buttonNotFound: "Tombol {name} tidak ditemukan",
    didNotOpen: "{name} tidak berhasil dibuka",
    listEmpty: "Daftar {name} kosong",
    couldNotFocus: "{name} tidak dapat difokuskan",
    chatListEmpty: "Daftar chat kosong",
    chatNotReady: "Chat belum siap",
    noMessages: "Tidak ada pesan",
    messageNotReady: "Pesan belum siap",
    unreadHistoryOnly: "Alt 3 hanya berfungsi di riwayat pesan",
    noOpenChat: "Tidak ada chat yang terbuka",
    unreadNotFound: "Pesan belum dibaca tidak ditemukan",
    unreadNotReady: "Pesan belum dibaca belum siap",
    mediaNotOpen: "Pemutar media tidak terbuka.",
    mediaClosed: "Pemutar media ditutup.",
    desktopPromoClosed: "Promo aplikasi desktop ditutup.",
    messageBoxNotReady: "Kotak pesan belum siap",
    messageBoxNotOpen: "Kotak pesan tidak terbuka",
    noTitle: "Judul tidak ditemukan",
    titleNotFound: "Judul chat tidak ditemukan",
    privacyOn: "Mode privasi aktif",
    privacyOff: "Mode privasi nonaktif",
    automaticReadingOn: "Pembacaan pesan otomatis aktif",
    automaticReadingOff: "Pembacaan pesan baru otomatis nonaktif",
    chatActivityOn: "Monitor aktivitas chat aktif",
    chatActivityOff: "Monitor aktivitas chat nonaktif",
    cleanUiOn: "Antarmuka ringkas aktif.",
    cleanUiOnHidden: "Antarmuka ringkas aktif; kontrol tambahan disembunyikan.",
    cleanUiOff: "Antarmuka ringkas nonaktif.",
    darkOn: "Mode gelap asli aktif",
    darkOff: "Mode gelap asli nonaktif",
    statusTransitionDiagnosticStarted: "Diagnostik pergantian Status dimulai. Putar satu Status video sampai berganti, lalu tekan Alt+Shift+7 lagi.",
    statusTransitionDiagnosticCopied: "Diagnostik pergantian Status dihentikan dan disalin. Tempelkan ke debug_status_transition.txt.",
    statusTransitionDiagnosticCopyFailed: "Diagnostik pergantian Status dihentikan, tetapi tidak dapat disalin. Tekan Alt+Shift+7 untuk mencoba lagi.",
    saveError: "Pengaturan tidak dapat disimpan."
  };

  // src/settings-state.js
  var LANGUAGES = Object.freeze([
    { value: "en", label: "English" },
    { value: "id", label: "Bahasa Indonesia" }
  ]);
  function readSetting(key, fallback) {
    try {
      return localStorage.getItem(key) ?? fallback;
    } catch {
      return fallback;
    }
  }
  function writeSetting(key, value) {
    try {
      localStorage.setItem(key, value);
      return true;
    } catch {
      return false;
    }
  }
  var savedLanguage = readSetting(STORAGE_KEYS.language, "");
  var language = LANGUAGES.some((item) => item.value === savedLanguage) ? savedLanguage : (typeof navigator !== "undefined" && navigator.language || "").toLowerCase().startsWith("id") ? "id" : "en";
  var reduceAnnouncements = readSetting(STORAGE_KEYS.reduceAnnouncements, "true") !== "false";
  var automaticReading = readSetting(STORAGE_KEYS.automaticReading, "false") === "true";
  var statusReadingCleanup = readSetting(STORAGE_KEYS.statusReadingCleanup, "false") === "true";
  var senderDeviceAnnouncements = readSetting(STORAGE_KEYS.senderDeviceAnnouncements, "false") === "true";
  var openChatsAtFirstUnread = readSetting(STORAGE_KEYS.openChatsAtFirstUnread, "false") === "true";
  var customTextStorageKeys = Object.freeze({
    "unread-divider": STORAGE_KEYS.customUnreadDivider,
    typing: STORAGE_KEYS.customTypingText,
    "recording-audio": STORAGE_KEYS.customRecordingAudioText,
    "delivery-status": STORAGE_KEYS.customDeliveryStatus,
    "delivery-pending": STORAGE_KEYS.customDeliveryPending,
    "delivery-sent": STORAGE_KEYS.customDeliverySent,
    "delivery-delivered": STORAGE_KEYS.customDeliveryDelivered,
    "delivery-read": STORAGE_KEYS.customDeliveryRead,
    "desktop-promo": STORAGE_KEYS.customDesktopPromo,
    "recent-searches": STORAGE_KEYS.customRecentSearches,
    "clear-all": STORAGE_KEYS.customClearAll,
    "nav-chats": STORAGE_KEYS.customNavChats,
    "nav-status": STORAGE_KEYS.customNavStatus,
    "nav-communities": STORAGE_KEYS.customNavCommunities,
    "nav-channels": STORAGE_KEYS.customNavChannels,
    "nav-meta-ai": STORAGE_KEYS.customNavMetaAI,
    "message-context-instruction": STORAGE_KEYS.customMessageContextInstruction,
    "unknown-contact-prefix": STORAGE_KEYS.customUnknownContactPrefix,
    "participant-prefix": STORAGE_KEYS.customParticipantPrefix,
    "quote-prefix": STORAGE_KEYS.customQuotePrefix,
    "online-status": STORAGE_KEYS.customOnlineStatus,
    "last-seen-prefix": STORAGE_KEYS.customLastSeenPrefix,
    "chat-status-labels": STORAGE_KEYS.customChatStatusLabels,
    "view-status": STORAGE_KEYS.customViewStatus,
    "participant-separator": STORAGE_KEYS.customParticipantSeparator,
    "status-pause-labels": STORAGE_KEYS.customStatusPauseLabels,
    "status-read-more-labels": STORAGE_KEYS.customStatusReadMoreLabels,
    "status-media-fallback": STORAGE_KEYS.customStatusMediaFallback,
    "scroll-to-bottom": STORAGE_KEYS.customScrollToBottom
  });
  var customText = Object.fromEntries(Object.entries(customTextStorageKeys).map(([key, storageKey]) => [key, readSetting(storageKey, "")]));
  var navCustomKeys = Object.freeze({
    navChats: "nav-chats",
    navStatus: "nav-status",
    navCommunities: "nav-communities",
    navChannels: "nav-channels",
    navMetaAI: "nav-meta-ai"
  });
  var shortcutRemapStorageKeys = Object.freeze({
    "voice-recording": STORAGE_KEYS.remapVoiceRecording,
    "previous-chat": STORAGE_KEYS.remapPreviousChat,
    "next-chat": STORAGE_KEYS.remapNextChat
  });
  var shortcutRemaps = {
    "voice-recording": readSetting(STORAGE_KEYS.remapVoiceRecording, "true") !== "false",
    "previous-chat": readSetting(STORAGE_KEYS.remapPreviousChat, "false") === "true",
    "next-chat": readSetting(STORAGE_KEYS.remapNextChat, "false") === "true"
  };
  var messages = Object.freeze({ en: en_default, id: id_default });
  var regexCache = /* @__PURE__ */ new Map();
  var DELIVERY_STATUS_DEFINITIONS = Object.freeze([
    { key: "deliveryPending", customKey: "delivery-pending", rank: 0, values: ["Pending", "Tertunda"] },
    { key: "deliverySent", customKey: "delivery-sent", rank: 1, values: ["Sent", "Terkirim"] },
    { key: "deliveryDelivered", customKey: "delivery-delivered", rank: 2, values: ["Delivered", "Disampaikan", "Tersampaikan"] },
    { key: "deliveryRead", customKey: "delivery-read", rank: 3, values: ["Read", "Dibaca"] }
  ]);
  function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  }
  function getCachedRegex(key, source, flags) {
    const cacheKey = `${key}\0${source}\0${flags}`;
    let regex = regexCache.get(cacheKey);
    if (!regex) {
      regex = new RegExp(source, flags);
      regexCache.set(cacheKey, regex);
    }
    return regex;
  }
  function getCustomText(key) {
    return customText[key] || "";
  }
  function setCustomText(key, value) {
    const cleanValue = String(value || "").trim();
    const storageKey = customTextStorageKeys[key];
    if (!storageKey) return false;
    if (!writeSetting(storageKey, cleanValue)) return false;
    customText[key] = cleanValue;
    regexCache.clear();
    return true;
  }
  function getPatternParts(customKey, defaults, separator = null) {
    const parts = [...defaults];
    const value = getCustomText(customKey);
    if (!value) return parts;
    const customParts = separator ? value.split(separator) : [value];
    customParts.reverse().forEach((part) => {
      const trimmed = part.trim();
      if (trimmed) parts.unshift(escapeRegExp(trimmed));
    });
    return parts;
  }
  function getNavSelector(selectorKey) {
    const defaultSelector = SELECTORS[selectorKey] || "";
    const customKey = navCustomKeys[selectorKey];
    const customLabel = customKey && getCustomText(customKey);
    if (!customLabel) return defaultSelector;
    return `[data-testid="navbar-primary-section"] button[aria-label="${CSS.escape(customLabel)}"]`;
  }
  function getNavButton(selectorKey) {
    const selector = getNavSelector(selectorKey);
    return selector ? document.querySelector(selector) : null;
  }
  function getScrollToBottomSelector() {
    const labels = LANGUAGES.map(({ value }) => tForLanguage("scrollToBottomDefault", value));
    const customLabel = getCustomText("scroll-to-bottom");
    if (customLabel) labels.unshift(customLabel);
    return [...new Set(labels)].map((label) => `button[aria-label="${CSS.escape(label)}"]`).join(", ");
  }
  function getUnreadDividerRegex() {
    const parts = ["unread messages?", "new messages?", "pesan (?:yang )?belum dibaca", "belum dibaca", "pesan baru"];
    const customUnreadDivider = getCustomText("unread-divider");
    if (customUnreadDivider) parts.unshift(escapeRegExp(customUnreadDivider));
    return getCachedRegex("unread-divider", `^(?:\\d+\\+?\\s+)?(?:${parts.join("|")})$`, "i");
  }
  function getTypingParts() {
    const parts = ["typing", "mengetik", "sedang mengetik"];
    const customTypingText = getCustomText("typing");
    if (customTypingText) parts.unshift(escapeRegExp(customTypingText));
    return parts;
  }
  function getTypingRegex() {
    return getCachedRegex("typing", `(?:^|\\s)(?:${getTypingParts().join("|")})(?:\\u2026|\\.{3})?$`, "iu");
  }
  function getGenericTypingPattern() {
    return getTypingParts().join("|");
  }
  function getGenericTypingRegex() {
    return getCachedRegex("typing-generic", `^(?:${getGenericTypingPattern()})(?:\\u2026|\\.{3})?$`, "iu");
  }
  function getRecordingAudioParts() {
    const parts = [
      "recording audio",
      "recording (?:a )?voice message",
      "sedang merekam audio",
      "(?:sedang )?merekam pesan suara"
    ];
    const customRecordingAudioText = getCustomText("recording-audio");
    if (customRecordingAudioText) parts.unshift(escapeRegExp(customRecordingAudioText));
    return parts;
  }
  function getRecordingAudioRegex() {
    return getCachedRegex(
      "recording-audio",
      `(?:^|\\s)(?:${getRecordingAudioParts().join("|")})(?:\\u2026|\\.{3})?$`,
      "iu"
    );
  }
  function getGenericRecordingAudioPattern() {
    return getRecordingAudioParts().join("|");
  }
  function getGenericRecordingAudioRegex() {
    return getCachedRegex(
      "recording-audio-generic",
      `^(?:${getGenericRecordingAudioPattern()})(?:\\u2026|\\.{3})?$`,
      "iu"
    );
  }
  function getDeliveryStatusPattern() {
    const parts = DELIVERY_STATUS_DEFINITIONS.flatMap(({ customKey, values }) => getPatternParts(customKey, values));
    const customDeliveryStatus = getCustomText("delivery-status");
    if (customDeliveryStatus) {
      customDeliveryStatus.split(/[,|]/).forEach((item) => {
        const trimmed = item.trim();
        if (trimmed) parts.unshift(escapeRegExp(trimmed));
      });
    }
    return parts.join("|");
  }
  function getDeliveryStatusRegex() {
    return getCachedRegex("delivery-status", `^(?:${getDeliveryStatusPattern()})$`, "i");
  }
  function getDesktopPromoRegex() {
    const parts = [
      "Download WhatsApp for (?:Windows|Mac|macOS)",
      "Dapatkan WhatsApp untuk Windows",
      ...LANGUAGES.map(({ value }) => escapeRegExp(tForLanguage("desktopAppPromoDefault", value)))
    ];
    const customDesktopPromo = getCustomText("desktop-promo");
    if (customDesktopPromo) parts.unshift(escapeRegExp(customDesktopPromo));
    return getCachedRegex("desktop-promo", `^(?:${parts.join("|")})$`, "i");
  }
  function getRecentSearchesRegex() {
    const parts = ["recent searches", "pencarian (?:terkini|terbaru)", "b\xFAsquedas recientes", "letzte suchanfragen"];
    const customRecentSearches = getCustomText("recent-searches");
    if (customRecentSearches) parts.unshift(escapeRegExp(customRecentSearches));
    return getCachedRegex("recent-searches", `^(?:${parts.join("|")})$`, "i");
  }
  function getClearAllRegex() {
    const parts = ["clear all", "hapus semua", "borrar todo", "alle l\xF6schen", "effacer tout", "limpar tudo"];
    const customClearAll = getCustomText("clear-all");
    if (customClearAll) parts.unshift(escapeRegExp(customClearAll));
    return getCachedRegex("clear-all", `^(?:${parts.join("|")})$`, "i");
  }
  function getMessageContextInstructionRegex() {
    const parts = getPatternParts("message-context-instruction", [
      "For more options,\\s*press left or right arrow key to access context menu",
      "Untuk opsi lainnya,\\s*tekan tombol panah kiri atau kanan untuk mengakses menu konteks"
    ]);
    return getCachedRegex(
      "message-context-instruction",
      `\\s*(?:${parts.join("|")})\\.?\\s*$`,
      "iu"
    );
  }
  function getPrefixRegex(cacheKey, customKey, defaults, flags = "iu") {
    const parts = getPatternParts(customKey, defaults);
    return getCachedRegex(
      cacheKey,
      `^(?:${parts.join("|")})(?=$|[\\s:\uFF1A~,\uFF0C\u060C\u2014-])[\\s:\uFF1A~,\uFF0C\u060C\u2014-]*`,
      flags
    );
  }
  function getUnknownContactRegex() {
    return getPrefixRegex(
      "unknown-contact-prefix",
      "unknown-contact-prefix",
      ["Maybe", "Mungkin", "Talvez"]
    );
  }
  function getParticipantPrefixRegex() {
    return getPrefixRegex(
      "participant-prefix",
      "participant-prefix",
      ["Participant", "Peserta"]
    );
  }
  function getParticipantWordRegex() {
    const parts = getPatternParts("participant-prefix", ["Participant", "Peserta"]);
    return getCachedRegex(
      "participant-word",
      `(?:^|\\s)(?:${parts.join("|")})(?=$|[\\s:\uFF1A~,\uFF0C\u060C\u2014-])[\\s:\uFF1A~,\uFF0C\u060C\u2014-]*`,
      "giu"
    );
  }
  function getQuotePrefixRegex() {
    const parts = getPatternParts("quote-prefix", [
      "to quoted message from",
      "quoted message from",
      "ke pesan yang dikutip dari",
      "pesan yang dikutip dari"
    ]);
    return getCachedRegex("quote-prefix", `(?:${parts.join("|")})\\s*`, "iu");
  }
  function getOnlineStatusRegex() {
    const parts = getPatternParts("online-status", ["online"]);
    return getCachedRegex("online-status", `^(?:${parts.join("|")})$`, "iu");
  }
  function getLastSeenRegex() {
    const parts = getPatternParts("last-seen-prefix", ["last seen", "terakhir dilihat"]);
    return getCachedRegex("last-seen-prefix", `^(?:${parts.join("|")})(.*)$`, "iu");
  }
  function getRecordingAudioStatusRegex() {
    return getCachedRegex(
      "recording-audio-status",
      `^(?:${getGenericRecordingAudioPattern()})(.*)$`,
      "iu"
    );
  }
  function getChatStatusRegex() {
    const parts = [
      ...getPatternParts("chat-status-labels", [
        "muted chat",
        "chat dibisukan",
        "pinned chat",
        "chat disematkan",
        "archived chat",
        "chat diarsipkan",
        "draft",
        "draf"
      ], /[|]/),
      ...getTypingParts()
    ];
    return getCachedRegex(
      "chat-status-labels",
      `^(?:${parts.join("|")})(?:\\u2026|\\.{3})?$`,
      "iu"
    );
  }
  function getViewStatusRegex() {
    const parts = getPatternParts("view-status", ["(?:view|lihat) status"]);
    return getCachedRegex("view-status", `^(?:${parts.join("|")})(?=$|\\s)`, "iu");
  }
  function getMetaAIRegex(exact = false) {
    const parts = getPatternParts("nav-meta-ai", ["Meta AI"]);
    return getCachedRegex(
      exact ? "meta-ai-exact" : "meta-ai-contained",
      exact ? `^(?:${parts.join("|")})\\s*[:\uFF1A]?$` : `(?:${parts.join("|")})`,
      "iu"
    );
  }
  function splitParticipantList(value) {
    const separators = [","];
    const customSeparator = getCustomText("participant-separator");
    if (customSeparator) separators.unshift(escapeRegExp(customSeparator));
    return String(value || "").split(getCachedRegex("participant-separator", `\\s*(?:${separators.join("|")})\\s*`, "u")).map((part) => part.trim()).filter(Boolean);
  }
  function getLanguage() {
    return language;
  }
  function getSupportedLanguage(value) {
    const code = String(value || "").toLowerCase().split("-")[0];
    return LANGUAGES.some((item) => item.value === code) ? code : "";
  }
  function setLanguage(value) {
    if (!LANGUAGES.some((item) => item.value === value)) return false;
    if (!writeSetting(STORAGE_KEYS.language, value)) return false;
    language = value;
    return true;
  }
  function isAnnouncementReductionEnabled() {
    return reduceAnnouncements;
  }
  function setAnnouncementReduction(value) {
    const nextValue = !!value;
    if (!writeSetting(STORAGE_KEYS.reduceAnnouncements, String(nextValue))) return false;
    reduceAnnouncements = nextValue;
    return true;
  }
  function isAutomaticReadingEnabled() {
    return automaticReading;
  }
  function setAutomaticReading(value) {
    const nextValue = !!value;
    if (!writeSetting(STORAGE_KEYS.automaticReading, String(nextValue))) return false;
    automaticReading = nextValue;
    return true;
  }
  function isStatusReadingCleanupEnabled() {
    return statusReadingCleanup;
  }
  function setStatusReadingCleanup(value) {
    const nextValue = !!value;
    if (!writeSetting(STORAGE_KEYS.statusReadingCleanup, String(nextValue))) return false;
    statusReadingCleanup = nextValue;
    return true;
  }
  function tForLanguage(key, targetLanguage, values = {}) {
    const target = getSupportedLanguage(targetLanguage) || "en";
    const template = messages[target][key] || messages.en[key] || key;
    return template.replace(/\{(\w+)\}/g, (_, name) => values[name] ?? `{${name}}`);
  }
  function t(key, values = {}) {
    return tForLanguage(key, language, values);
  }
  function isSenderDeviceAnnouncementEnabled() {
    return senderDeviceAnnouncements;
  }
  function setSenderDeviceAnnouncement(value) {
    const nextValue = !!value;
    if (!writeSetting(STORAGE_KEYS.senderDeviceAnnouncements, String(nextValue))) return false;
    senderDeviceAnnouncements = nextValue;
    return true;
  }
  function shouldOpenChatsAtFirstUnread() {
    return openChatsAtFirstUnread;
  }
  function setOpenChatsAtFirstUnread(value) {
    const nextValue = !!value;
    if (!writeSetting(STORAGE_KEYS.openChatsAtFirstUnread, String(nextValue))) return false;
    openChatsAtFirstUnread = nextValue;
    return true;
  }
  function isShortcutRemapEnabled(name) {
    return shortcutRemaps[name] === true;
  }
  function setShortcutRemap(name, value) {
    const storageKey = shortcutRemapStorageKeys[name];
    if (!storageKey) return false;
    const nextValue = !!value;
    if (!writeSetting(storageKey, String(nextValue))) return false;
    shortcutRemaps[name] = nextValue;
    return true;
  }
  function getDeliveryStatusKey(value) {
    const normalized = String(value || "").trim().toLowerCase();
    const builtInDefinition = DELIVERY_STATUS_DEFINITIONS.find(({ values }) => values.some((item) => item.toLowerCase() === normalized));
    if (builtInDefinition) return builtInDefinition.key;
    const customDefinition = DELIVERY_STATUS_DEFINITIONS.find(({ customKey }) => {
      const customValue = getCustomText(customKey).toLowerCase();
      return customValue && customValue === normalized;
    });
    return customDefinition?.key || "";
  }
  function getDeliveryStatusRank(value) {
    const key = getDeliveryStatusKey(value);
    return DELIVERY_STATUS_DEFINITIONS.find((definition) => definition.key === key)?.rank ?? -1;
  }
  function translateDeliveryStatus(value, targetLanguage = "") {
    const key = getDeliveryStatusKey(value);
    return key ? targetLanguage ? tForLanguage(key, targetLanguage) : t(key) : value;
  }
  function translateDeliveryStatusInText(value, targetLanguage = "") {
    const text = String(value || "");
    const pattern = getDeliveryStatusPattern();
    return text.replace(
      getCachedRegex("delivery-status-text", `(^|\\s)(${pattern})(?=\\s*$)`, "i"),
      (_, prefix, status) => `${prefix}${translateDeliveryStatus(status, targetLanguage)}`
    );
  }
  function getTypingSuffix(value) {
    const match = String(value || "").match(/(\u2026|\.{3})$/);
    return match?.[1] || "";
  }
  function isolateBidiText(value) {
    const text = String(value || "");
    return /[\u0590-\u08ff\ufb1d-\ufdff\ufe70-\ufefc]/u.test(text) ? `\u2068${text}\u2069` : text;
  }
  function translateNamedActivity(value, pattern, cacheKey, messageKey) {
    const text = String(value || "").trim();
    const match = text.match(getCachedRegex(
      cacheKey,
      `^(.*?)\\s+(?:(is|are|sedang)\\s+)?(?:${pattern})(\\u2026|\\.{3})?$`,
      "iu"
    ));
    return match ? t(messageKey, {
      name: isolateBidiText(match[1]),
      verb: match[2]?.toLowerCase() === "are" ? "are" : "is",
      suffix: match[3] || ""
    }) : text;
  }
  function translateTypingActivity(value) {
    return translateNamedActivity(value, getGenericTypingPattern(), "typing-activity", "typingActivity");
  }
  function translateRecordingAudioActivity(value) {
    return translateNamedActivity(
      value,
      getGenericRecordingAudioPattern(),
      "recording-audio-activity",
      "recordingAudioActivity"
    );
  }
  function translateActivityStatus(value) {
    const text = String(value || "").trim();
    if (getOnlineStatusRegex().test(text)) return t("online");
    const lastSeen = text.match(getLastSeenRegex());
    if (lastSeen) return t("lastSeen", { details: lastSeen[1] });
    const recording = text.match(getRecordingAudioStatusRegex());
    if (recording) return t("recordingAudio", { details: recording[1] });
    if (getRecordingAudioRegex().test(text)) return translateRecordingAudioActivity(text);
    return translateTypingActivity(text);
  }

  // src/privacy.js
  var isPrivacyMode = readSetting(STORAGE_KEYS.privacy, "false") === "true";
  var _origSetAttribute = Element.prototype.setAttribute;
  var _origRemoveAttribute = Element.prototype.removeAttribute;
  var privacyAttributes = /* @__PURE__ */ new Map();
  var senderDeviceLabels = /* @__PURE__ */ new Map();
  function hasActiveState(el) {
    const current2 = el && el.getAttribute("aria-current");
    return !!el && (el.getAttribute("aria-pressed") === "true" || el.getAttribute("aria-selected") === "true" || current2 !== null && current2 !== "false" || el.getAttribute("data-navbar-item-selected") === "true");
  }
  function isStatusTabActive() {
    return hasActiveState(getNavButton("navStatus"));
  }
  function getChatMainForElement(el) {
    if (!el || !el.closest || isStatusTabActive()) return null;
    const main = el.closest(SELECTORS.main);
    if (!main) return null;
    const hasComposer = !!main.querySelector('footer div[contenteditable="true"]');
    const hasConversationMessages = !!main.querySelector(SELECTORS.conversationMessages);
    return hasComposer || hasConversationMessages ? main : null;
  }
  function getPrivacyContext(el) {
    if (!getChatMainForElement(el)) return false;
    const link = el.matches?.('a[href], [role="link"]') ? el : el.closest?.('a[href], [role="link"]');
    if (link) return link.closest?.(SELECTORS.conversationMessages) ? "link" : false;
    if (el.closest('[data-testid="group-chat-profile-picture"]')) return "identity-name";
    return el.closest(SELECTORS.conversationMessages) ? "message" : "identity";
  }
  function getHostLanguage(el) {
    if (!el) return "";
    const taggedLanguage = el?.closest?.("[lang]")?.getAttribute?.("lang");
    return getSupportedLanguage(taggedLanguage || document.documentElement?.lang);
  }
  function tForHost(key, el, values = {}) {
    const hostLanguage = getHostLanguage(el);
    if (hostLanguage) return tForLanguage(key, hostLanguage, values);
    const customKey = key === "participant" ? "participant-prefix" : key === "unknownContact" ? "unknown-contact-prefix" : "";
    return customKey && getCustomText(customKey) || t(key, values);
  }
  function replaceOutsideWebUrls(text, pattern, replacement) {
    let result = "";
    let lastIndex = 0;
    WEB_URL_RE.lastIndex = 0;
    let match;
    while ((match = WEB_URL_RE.exec(text)) !== null) {
      result += text.slice(lastIndex, match.index).replace(pattern, replacement);
      result += match[0];
      lastIndex = match.index + match[0].length;
    }
    result += text.slice(lastIndex).replace(pattern, replacement);
    return result;
  }
  function removePhonesOutsideWebUrls(text) {
    return replaceOutsideWebUrls(text, PHONE_RE, replacePhoneCandidateWith(""));
  }
  function replacePhonesOutsideWebUrls(text, el = null) {
    return replaceOutsideWebUrls(text, PHONE_RE, replacePhoneCandidateWith(tForHost("participant", el)));
  }
  function replacePhoneUrlWith(replacement) {
    return (match, offset, source) => {
      const trailingHour = match.match(/\s+\d{1,2}$/);
      const hasTrailingTime = trailingHour && /^:\d{2}\b/.test(source.slice(offset + match.length));
      return replacement + (hasTrailingTime ? trailingHour[0] : "");
    };
  }
  function maskMessagePhoneLinks(text, el = null) {
    return text.replace(PHONE_URL_RE, replacePhoneUrlWith(tForHost("phoneLink", el)));
  }
  function maskPhoneBearingWebUrls(text, el = null) {
    WEB_URL_RE.lastIndex = 0;
    return text.replace(WEB_URL_RE, (url) => {
      PHONE_RE.lastIndex = 0;
      let match;
      while ((match = PHONE_RE.exec(url)) !== null) {
        if (isPhoneCandidate(match[0], match.index, url)) return tForHost("phoneLink", el);
      }
      return url;
    });
  }
  function maskMessagePhones(text, el = null) {
    return maskMessagePhoneLinks(
      replacePhonesOutsideWebUrls(maskPhoneBearingWebUrls(text, el), el),
      el
    );
  }
  function maskPhoneLinkName(text, el) {
    const label = tForHost("phoneLink", el);
    return text.replace(PHONE_URL_RE, replacePhoneUrlWith(label)).replace(PHONE_RE, replacePhoneCandidateWith(label));
  }
  function maskPhoneNumbers(text, el = null) {
    const participant = tForHost("participant", el);
    return text.replace(PHONE_URL_RE, replacePhoneUrlWith(participant)).replace(PHONE_RE, replacePhoneCandidateWith(participant));
  }
  function replacePhoneCandidateWith(replacement) {
    return (match, offset, source) => {
      const trailingHour = match.match(/\s+\d{1,2}$/);
      const hasTrailingTime = trailingHour && /^:\d{2}\b/.test(source.slice(offset + match.length));
      const phone = hasTrailingTime ? match.slice(0, -trailingHour[0].length) : match;
      const candidateSource = hasTrailingTime ? source.slice(0, offset + phone.length) : source;
      const masked = typeof replacement === "function" ? replacement(phone, offset, candidateSource) : replacement;
      return isPhoneCandidate(phone, offset, candidateSource) ? masked + (hasTrailingTime ? trailingHour[0] : "") : match;
    };
  }
  function isPhoneCandidate(raw, offset, source) {
    const before = source[offset - 1] || "";
    const after = source[offset + raw.length] || "";
    if (/[A-Za-z0-9_]/.test(before) || /[A-Za-z0-9_]/.test(after)) return false;
    const trimmed = raw.trim();
    const digits = trimmed.replace(/\D/g, "");
    if (digits.length > 16) return false;
    if (trimmed.startsWith("+") || digits.startsWith("00")) return digits.length >= 7;
    return digits.length >= 9;
  }
  function filterMessageIdentities(text, el) {
    const message = el && el.closest && el.closest(".focusable-list-item");
    if (!message || !message.querySelector) {
      return el ? maskMessagePhones(text, el) : maskMessagePhoneLinks(text);
    }
    const copyable = message.querySelector(".copyable-text[data-pre-plain-text]");
    const prePlainText = copyable && copyable.getAttribute("data-pre-plain-text");
    const senderMatch = prePlainText && prePlainText.match(/^\[[^\]]+\]\s+(.+?):\s*$/);
    const authorEl = message.querySelector('[data-testid="author"][aria-label]');
    const author = authorEl && (authorEl.getAttribute("aria-label") || "").trim();
    const authorPhone = authorEl && authorEl.nextElementSibling ? (authorEl.nextElementSibling.textContent || "").trim() : "";
    const senderLabelEl = message.querySelector('span[aria-label$=":"]');
    const senderLabelState = senderLabelEl && privacyAttributes.get(senderLabelEl)?.get("aria-label");
    const senderLabel = senderLabelEl && (senderLabelState?.raw || senderLabelEl.getAttribute("aria-label") || "").replace(/:\s*$/, "").trim();
    const metadataSender = senderMatch && senderMatch[1] || authorPhone;
    const bodyEl = message.querySelector('.copyable-text[data-pre-plain-text] [data-testid="selectable-text"]');
    const body = bodyEl && normalizeText(bodyEl.textContent || "");
    const bodyCandidates = body ? [...new Set([body, body.replace(/^@\s*/, "")].filter(Boolean))] : [];
    const bodyStart = bodyCandidates.reduce((found, candidate) => {
      if (found >= 0) return found;
      return text.indexOf(candidate);
    }, -1);
    const sender = metadataSender || (bodyStart !== 0 ? senderLabel : "");
    const senderStart = sender ? text.indexOf(sender) : -1;
    const inferredUnknownSender = senderStart > 0 && bodyStart > 0 && senderStart + sender.length <= bodyStart && getUnknownContactRegex().test(text) ? text.slice(0, senderStart + sender.length).trim() : "";
    const senderCandidates = sender ? [...new Set([author && `${author} ${sender}`, inferredUnknownSender, sender].filter(Boolean))] : [author].filter(Boolean);
    const senderIdentity = senderCandidates.sort((a, b) => b.length - a.length).find((candidate) => text.startsWith(candidate));
    if (senderIdentity) {
      text = applyPrivacyFilter(senderIdentity, "identity", el) + text.slice(senderIdentity.length);
    }
    const directQuotePrefix = getQuotePrefixRegex().exec(text);
    const directQuotedSenderStart = directQuotePrefix ? directQuotePrefix.index + directQuotePrefix[0].length : -1;
    const directQuotedSenderEnd = directQuotedSenderStart >= 0 ? text.indexOf(":", directQuotedSenderStart) : -1;
    if (directQuotedSenderEnd > directQuotedSenderStart) {
      const directQuotedSender = text.slice(directQuotedSenderStart, directQuotedSenderEnd).trim();
      return maskMessagePhones(text.slice(0, directQuotedSenderStart) + applyPrivacyFilter(directQuotedSender, "identity", el) + text.slice(directQuotedSenderEnd), el);
    }
    const quotedAuthorEl = message.querySelector('[data-testid="quoted-message"] [data-testid="author"][aria-label]');
    const quotedAuthor = quotedAuthorEl && (quotedAuthorEl.getAttribute("aria-label") || "").trim();
    const quotedAuthorPhone = quotedAuthorEl && quotedAuthorEl.nextElementSibling ? (quotedAuthorEl.nextElementSibling.textContent || "").trim() : "";
    const quotedSenderEl = message.querySelector('[data-testid="quoted-message"] [dir="auto"]');
    const quotedSender = quotedSenderEl && (quotedSenderEl.textContent || "").trim();
    const quotedSenderCandidates = [...new Set([
      quotedAuthor && quotedAuthorPhone && `${quotedAuthor} ${quotedAuthorPhone}`,
      quotedAuthor,
      quotedSender
    ].filter(Boolean).flatMap((senderValue) => [senderValue, senderValue.replace(/\s+·\s+.*$/, "")]))];
    const quotePrefixIndex = text.search(getQuotePrefixRegex());
    const quoteSearchStart = quotePrefixIndex >= 0 ? quotePrefixIndex : 0;
    let quotedSenderStart = -1;
    let quotedSenderIdentity = "";
    quotedSenderCandidates.forEach((candidate) => {
      const start = text.indexOf(`${candidate}:`, quoteSearchStart);
      if (start > quotedSenderStart) {
        quotedSenderStart = start;
        quotedSenderIdentity = candidate;
      }
    });
    if (quotedSenderStart >= 0) {
      text = text.slice(0, quotedSenderStart) + applyPrivacyFilter(quotedSenderIdentity, "identity", el) + text.slice(quotedSenderStart + quotedSenderIdentity.length);
    }
    const currentBody = bodyCandidates.find((candidate) => text.includes(candidate));
    if (!currentBody) return maskMessagePhones(text, el);
    const currentBodyStart = text.indexOf(currentBody);
    const currentBodyEnd = currentBodyStart + currentBody.length;
    return maskMessagePhones(text.slice(0, currentBodyStart), el) + maskMessagePhones(currentBody, el) + maskMessagePhones(text.slice(currentBodyEnd), el);
  }
  function applyPrivacyFilter(text, context, el) {
    if (context === "message") return filterMessageIdentities(text, el);
    if (context === "link") return maskPhoneLinkName(text, el);
    if (context === "identity-name") return removePhonesOutsideWebUrls(text);
    const participant = tForHost("participant", el);
    const unknownContact = tForHost("unknownContact", el);
    const hadUnknownPrefix = getUnknownContactRegex().test(text);
    const hadParticipantPrefix = getParticipantPrefixRegex().test(text);
    if (hadParticipantPrefix) {
      return removePhonesOutsideWebUrls(text.replace(PHONE_URL_RE, participant));
    }
    text = text.replace(PHONE_URL_RE, hadUnknownPrefix ? "" : participant);
    if (hadUnknownPrefix || hadParticipantPrefix) {
      text = text.replace(getUnknownContactRegex(), "").trim();
      text = text.replace(getParticipantPrefixRegex(), "").trim();
      text = removePhonesOutsideWebUrls(text);
      text = text.replace(getParticipantWordRegex(), " ").trim();
      text = text.replace(/^\s*\(\s*\)\s*/, "").trim();
      text = text.replace(/^~\s*/, "").trim();
      if (!text || text.length < 2) return unknownContact;
      text = `${unknownContact} ${text}`;
    } else {
      text = replacePhonesOutsideWebUrls(text, el);
    }
    text = text.replace(new RegExp(`(?:${participant})(?:\\s+${participant})+`, "gi"), participant);
    return text;
  }
  function normalizeText(text) {
    if (!text || typeof text !== "string") return text;
    return text.replace(/\s{2,}/g, " ").trim();
  }
  function cleanString(text, applyPrivacy2 = false, el = null) {
    text = normalizeText(text);
    if (!text) return text;
    if (isPrivacyMode && applyPrivacy2) {
      text = applyPrivacyFilter(text, applyPrivacy2, el);
    }
    return normalizeText(text);
  }
  function rememberPrivacyAttribute(el, name, raw, masked) {
    let attributes = privacyAttributes.get(el);
    if (!attributes) {
      attributes = /* @__PURE__ */ new Map();
      privacyAttributes.set(el, attributes);
    }
    attributes.set(name, { raw, masked });
  }
  function getDirectMetaAISender(message) {
    if (!message || !message.querySelectorAll) return null;
    const candidates = message.querySelectorAll("span[aria-label]");
    const metaAIRegex = getMetaAIRegex(true);
    return Array.from(candidates).find(
      (sender) => metaAIRegex.test((sender.getAttribute("aria-label") || "").trim()) && !sender.closest('[data-testid="quoted-message"]') && !sender.closest(
        '.copyable-text.selectable-text, [data-testid="msg-meta"], a, button, [role="link"], [role="button"]'
      )
    ) || null;
  }
  function hasDirectMetaAISender(message) {
    return !!getDirectMetaAISender(message);
  }
  function getSenderDeviceKey(messageId) {
    const id = String(messageId || "").toUpperCase().match(/(?:^|_)([0-9A-F]+)$/)?.[1] || "";
    if (/^3A[0-9A-F]{18}$/.test(id)) return "deviceIPhone";
    if (/^3B[0-9A-F]{18}$/.test(id)) return "deviceMac";
    if (/^3C[0-9A-F]{18}$/.test(id)) return "deviceIPad";
    if (/^3EB0[0-9A-F]{18}$/.test(id)) return "deviceWebDesktop";
    if (/^[0-9A-F]{32}$/.test(id)) return "deviceAndroid";
    return "";
  }
  function appendSenderDevice(summary, messageId, el = null) {
    if (!summary || !isSenderDeviceAnnouncementEnabled()) return summary;
    const deviceKey = getSenderDeviceKey(messageId);
    if (!deviceKey) return summary;
    const suffix = tForHost("sentFromDevice", el, { device: tForHost(deviceKey, el) });
    if (summary.endsWith(suffix)) return summary;
    return `${summary}${/[.!?]$/.test(summary) ? "" : "."} ${suffix}`;
  }
  function getSenderDeviceMessageId(message) {
    const wrapper = message.closest?.('[data-testid^="conv-msg-"][data-id]');
    return wrapper?.getAttribute("data-id") || "";
  }
  function isSenderDeviceMessageLabel(el, name) {
    return name === "aria-label" && el.matches?.(".focusable-list-item") && el.closest?.(SELECTORS.conversationMessages) && !hasDirectMetaAISender(el);
  }
  function refreshSenderDeviceLabels() {
    const main = document.querySelector(SELECTORS.main);
    if (main) cleanElementAttributes(main);
  }
  function prepareNamedAttribute(el, name, value) {
    let raw = String(value);
    const isMessageLabel = isSenderDeviceMessageLabel(el, name);
    const deviceState = name === "aria-label" && senderDeviceLabels.get(el);
    if (isMessageLabel && deviceState && raw === deviceState.appliedValue) {
      raw = deviceState.baseValue;
    } else if (!isMessageLabel && deviceState) {
      senderDeviceLabels.delete(el);
    }
    const context = isPrivacyMode ? getPrivacyContext(el) : false;
    if (!isMessageLabel && !context) return raw;
    raw = cleanString(raw, false, el);
    if (name === "aria-label" && el.matches?.(".focusable-list-item") && el.closest?.(SELECTORS.conversationMessages) && !hasDirectMetaAISender(el) && el.querySelector?.('[data-testid="icon-down-context"][role="button"][aria-label]')) {
      raw = raw.replace(getMessageContextInstructionRegex(), "").trim();
    }
    const hostLanguage = isMessageLabel && getHostLanguage(el);
    if (hostLanguage) raw = translateDeliveryStatusInText(raw, hostLanguage);
    const baseValue = raw;
    if (isPrivacyMode && context) {
      const masked = applyPrivacyFilter(raw, context, el);
      if (masked !== raw) rememberPrivacyAttribute(el, name, raw, masked);
      raw = masked;
    }
    const decorated = isMessageLabel && hostLanguage ? appendSenderDevice(raw, getSenderDeviceMessageId(el), el) : raw;
    if (decorated !== raw) senderDeviceLabels.set(el, { baseValue, appliedValue: decorated });
    else senderDeviceLabels.delete(el);
    return decorated;
  }
  Element.prototype.setAttribute = function(name, value) {
    if ((name === "aria-label" || name === "title") && value && typeof value === "string") {
      value = prepareNamedAttribute(this, name, value);
    }
    return _origSetAttribute.call(this, name, value);
  };
  var _origAriaLabelDesc = Object.getOwnPropertyDescriptor(Element.prototype, "ariaLabel");
  if (_origAriaLabelDesc && _origAriaLabelDesc.set) {
    Object.defineProperty(Element.prototype, "ariaLabel", {
      get: _origAriaLabelDesc.get,
      set: function(value) {
        if (value && typeof value === "string") {
          value = prepareNamedAttribute(this, "aria-label", value);
        }
        return _origAriaLabelDesc.set.call(this, value);
      },
      configurable: true,
      enumerable: true
    });
  }
  function cleanNamedAttribute(el, attrName) {
    const value = el.getAttribute(attrName);
    if (!value) return;
    const privacyState = privacyAttributes.get(el)?.get(attrName);
    const deviceState = senderDeviceLabels.get(el);
    const isMessageLabel = isSenderDeviceMessageLabel(el, attrName);
    const hasPendingMessageInstruction = attrName === "aria-label" && el.matches?.(".focusable-list-item") && el.closest?.(SELECTORS.conversationMessages) && getMessageContextInstructionRegex().test(value);
    if (isPrivacyMode && privacyState && value === privacyState.masked && !deviceState && !isMessageLabel && !hasPendingMessageInstruction && !isSenderDeviceAnnouncementEnabled()) return;
    const sourceValue = isPrivacyMode && privacyState && value === privacyState.masked && !deviceState ? privacyState.raw : value;
    const cleaned = prepareNamedAttribute(el, attrName, sourceValue);
    if (value !== cleaned) _origSetAttribute.call(el, attrName, cleaned);
  }
  function maskPhoneAuthorText(el) {
    if (!isPrivacyMode || !el.matches?.('span[data-testid="author"]:not([aria-label])') || !el.closest?.(SELECTORS.conversationMessages) || el.getAttribute("aria-hidden") === "true" && !privacyAttributes.get(el)?.has("aria-hidden")) return;
    const text = normalizeText(el.textContent || "");
    const participant = tForHost("participant", el);
    const masked = maskPhoneNumbers(text, el);
    const state = privacyAttributes.get(el)?.get("aria-hidden");
    if (!text || masked === text || !masked.includes(participant)) {
      if (state && el.getAttribute("aria-hidden") === state.masked) {
        if (state.raw === null) _origRemoveAttribute.call(el, "aria-hidden");
        else _origSetAttribute.call(el, "aria-hidden", state.raw);
        const attributes = privacyAttributes.get(el);
        attributes.delete("aria-hidden");
        if (!attributes.size) privacyAttributes.delete(el);
      }
      return;
    }
    rememberPrivacyAttribute(el, "aria-hidden", el.getAttribute("aria-hidden"), "true");
    _origSetAttribute.call(el, "aria-hidden", "true");
  }
  function cleanElementAttributes(el) {
    if (!el || el.nodeType !== 1) return;
    maskPhoneAuthorText(el);
    cleanNamedAttribute(el, "aria-label");
    cleanNamedAttribute(el, "title");
    if (el.querySelectorAll) {
      el.querySelectorAll('span[data-testid="author"]:not([aria-label])').forEach(maskPhoneAuthorText);
      el.querySelectorAll("[aria-label], [title]").forEach((child) => {
        cleanNamedAttribute(child, "aria-label");
        cleanNamedAttribute(child, "title");
      });
    }
  }
  function forgetPrivacyState(rootEl) {
    for (const el of [...privacyAttributes.keys()]) {
      if (!el.isConnected || el === rootEl || rootEl.contains && rootEl.contains(el)) {
        privacyAttributes.delete(el);
      }
    }
    for (const el of [...senderDeviceLabels.keys()]) {
      if (!el.isConnected || el === rootEl || rootEl.contains && rootEl.contains(el)) {
        senderDeviceLabels.delete(el);
      }
    }
  }
  function restorePrivacyAttributes() {
    for (const [el, attributes] of privacyAttributes) {
      if (!el.isConnected) continue;
      for (const [name, state] of attributes) {
        if (el.getAttribute(name) !== state.masked) continue;
        if (state.raw === null) _origRemoveAttribute.call(el, name);
        else _origSetAttribute.call(el, name, state.raw);
      }
    }
    privacyAttributes.clear();
  }
  function refreshPrivacyAttributes() {
    if (!isPrivacyMode) return;
    restorePrivacyAttributes();
    const main = document.querySelector(SELECTORS.main);
    if (main) cleanElementAttributes(main);
  }
  function isPrivacyModeEnabled() {
    return isPrivacyMode;
  }
  function togglePrivacyMode(announce2, announceChange = true) {
    const nextValue = !isPrivacyMode;
    if (!writeSetting(STORAGE_KEYS.privacy, nextValue ? "true" : "false")) return false;
    isPrivacyMode = nextValue;
    const enabled = isPrivacyMode;
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    if (announceChange) announce2(enabled ? t("privacyOn") : t("privacyOff"));
    schedule(() => {
      if (isPrivacyMode !== enabled) return;
      if (!enabled) {
        restorePrivacyAttributes();
      }
      const main = document.querySelector(SELECTORS.main);
      if (main) cleanElementAttributes(main);
    });
    return true;
  }

  // src/owned-attributes.js
  var ownedAttributes = /* @__PURE__ */ new WeakMap();
  var ownedElements = /* @__PURE__ */ new Set();
  var ownedMutationCounts = /* @__PURE__ */ new WeakMap();
  var nativeRemoveAttribute = typeof Element !== "undefined" && Element.prototype.removeAttribute;
  if (nativeRemoveAttribute) {
    Element.prototype.removeAttribute = function(name) {
      const state = ownedAttributes.get(this)?.get(name);
      const result = nativeRemoveAttribute.call(this, name);
      if (state && state.appliedValue === null) state.hostRemoved = true;
      return result;
    };
  }
  function markOwnedMutation(el, name) {
    let attributes = ownedMutationCounts.get(el);
    if (!attributes) {
      attributes = /* @__PURE__ */ new Map();
      ownedMutationCounts.set(el, attributes);
    }
    attributes.set(name, (attributes.get(name) || 0) + 1);
  }
  function consumeOwnedMutation(el, name) {
    const attributes = ownedMutationCounts.get(el);
    const count = attributes && attributes.get(name);
    if (!count) return false;
    if (count === 1) attributes.delete(name);
    else attributes.set(name, count - 1);
    if (attributes.size === 0) ownedMutationCounts.delete(el);
    return true;
  }
  function dropOwnedAttribute(el, name) {
    const attributes = ownedAttributes.get(el);
    if (!attributes) return;
    attributes.delete(name);
    if (attributes.size === 0) {
      ownedAttributes.delete(el);
      ownedElements.delete(el);
      ownedMutationCounts.delete(el);
    }
  }
  function applyOwnedAttribute(el, name, value, owner) {
    let attributes = ownedAttributes.get(el);
    if (!attributes) {
      attributes = /* @__PURE__ */ new Map();
      ownedAttributes.set(el, attributes);
      ownedElements.add(el);
    }
    let state = attributes.get(name);
    if (state && el.getAttribute(name) !== state.appliedValue) {
      attributes.delete(name);
      state = null;
    }
    if (!state || state.owner !== owner) {
      state = {
        owner,
        originalPresent: el.hasAttribute(name),
        originalValue: el.getAttribute(name),
        appliedValue: value,
        hostRemoved: false
      };
      attributes.set(name, state);
    } else {
      state.appliedValue = value;
      state.hostRemoved = false;
    }
    if (el.getAttribute(name) !== value) {
      markOwnedMutation(el, name);
      if (value === null) _origRemoveAttribute.call(el, name);
      else _origSetAttribute.call(el, name, value);
    }
  }
  function releaseOwnedAttribute(el, name, owner) {
    const attributes = ownedAttributes.get(el);
    const state = attributes && attributes.get(name);
    if (!state || state.owner !== owner) return;
    const hostRemoved = state.hostRemoved && state.appliedValue === null && !el.hasAttribute(name);
    if (!hostRemoved && el.getAttribute(name) === state.appliedValue) {
      markOwnedMutation(el, name);
      if (state.originalPresent) _origSetAttribute.call(el, name, state.originalValue);
      else _origRemoveAttribute.call(el, name);
    }
    attributes.delete(name);
    if (attributes.size === 0) {
      ownedAttributes.delete(el);
      ownedElements.delete(el);
      ownedMutationCounts.delete(el);
    }
  }
  function releaseOwnedWithin(rootEl, owner) {
    for (const el of [...ownedElements]) {
      if (!el.isConnected) {
        const attributes2 = ownedAttributes.get(el);
        for (const [name, state] of [...attributes2 || []]) {
          if (state.owner === owner) releaseOwnedAttribute(el, name, owner);
        }
        continue;
      }
      if (rootEl && el !== rootEl && !rootEl.contains(el)) continue;
      const attributes = ownedAttributes.get(el);
      for (const [name, state] of [...attributes]) {
        if (state.owner === owner) releaseOwnedAttribute(el, name, owner);
      }
    }
  }
  function pruneDetachedOwnedElements() {
    for (const el of [...ownedElements]) {
      if (!el.isConnected) {
        const attributes = ownedAttributes.get(el);
        for (const [name, state] of [...attributes || []]) {
          releaseOwnedAttribute(el, name, state.owner);
        }
        ownedMutationCounts.delete(el);
      }
    }
  }
  function isOwnedMutation(el, name) {
    const isScriptMutation = consumeOwnedMutation(el, name);
    const attributes = ownedAttributes.get(el);
    const state = attributes && attributes.get(name);
    if (state && el.getAttribute(name) !== state.appliedValue) {
      dropOwnedAttribute(el, name);
      return isScriptMutation;
    }
    if (isScriptMutation) return true;
    return !!state;
  }

  // src/chat-accessibility.js
  var lastFocusedChatRowNode = null;
  var lastFocusedMessageNode = null;
  var lastFocusedMessageId = "";
  var announcementTimer = null;
  var userAnnouncementUntil = 0;
  var announcementGeneration = 0;
  var metaAIMessageNameId = 0;
  var MESSAGE_LOG_LIMIT = 50;
  function getNextMessageRow(marker, messageContainer) {
    const viewport = marker.closest("[data-tab]") || messageContainer;
    if (viewport !== messageContainer && !messageContainer.contains(viewport)) return null;
    let branch = marker;
    while (branch && branch !== viewport) {
      let sibling = branch.nextElementSibling;
      while (sibling) {
        const row = sibling.matches('div[role="row"]') ? sibling : sibling.querySelector('div[role="row"]');
        if (row && row.querySelector('[data-id], [role="gridcell"]')) return row;
        sibling = sibling.nextElementSibling;
      }
      branch = branch.parentElement;
    }
    return null;
  }
  function isNavbarActive(selectorKey) {
    return hasActiveState(getNavButton(selectorKey));
  }
  function isChatsTabActive() {
    if (isNavbarActive("navStatus") || isNavbarActive("navCommunities") || isNavbarActive("navChannels") || isNavbarActive("navMetaAI")) {
      return false;
    }
    const side = document.querySelector(SELECTORS.side);
    if (!side) return false;
    return !!side.querySelector(SELECTORS.chatList);
  }
  function isChatMainActive(main = document.querySelector(SELECTORS.main)) {
    if (!main || isStatusTabActive()) return false;
    return !!main.querySelector(`${SELECTORS.conversationMessages}, footer div[contenteditable="true"]`);
  }
  function getChatListContainer(rootEl = document) {
    if (rootEl.closest) {
      const closest = rootEl.closest(SELECTORS.chatListInSide);
      if (closest) return closest;
    }
    const side = rootEl.querySelector && (rootEl.querySelector(SELECTORS.side) || (rootEl.id === "side" ? rootEl : null));
    if (!side) return null;
    return side.querySelector(SELECTORS.chatList);
  }
  function isChatLabelNoise(text) {
    const normalized = (text || "").replace(/\s+/g, " ").trim();
    if (!normalized) return true;
    if (CHAT_LABEL_NOISE_RE.iconName.test(normalized)) return true;
    if (CHAT_LABEL_NOISE_RE.rawIconName.test(normalized)) return true;
    if (CHAT_LABEL_NOISE_RE.structuralName.test(normalized)) return true;
    return false;
  }
  function normalizeChatLabelPart(text) {
    let cleaned = cleanString(String(text || "").replace(/\u00a0/g, " "), false);
    cleaned = cleaned.replace(/\s+/g, " ").trim();
    if (isChatLabelNoise(cleaned)) return "";
    return cleaned;
  }
  function addChatLabelPart(parts, text) {
    const part = normalizeChatLabelPart(text);
    if (!part) return;
    const key = part.toLowerCase();
    if (parts.some((existing) => existing.toLowerCase() === key)) return;
    parts.push(part);
  }
  function getChatIconIdentity(el) {
    if (!el || !el.getAttribute) return "";
    const pieces = [
      el.getAttribute("data-icon") || "",
      el.getAttribute("data-testid") || "",
      el.getAttribute("aria-label") || "",
      el.getAttribute("title") || ""
    ];
    if (el.querySelector) {
      el.querySelectorAll("title").forEach((title) => pieces.push(title.textContent || ""));
    }
    return pieces.join(" ");
  }
  function isPotentialChatIconElement(el) {
    if (!el || !el.getAttribute) return false;
    const tag = el.tagName ? el.tagName.toUpperCase() : "";
    const testId = el.getAttribute("data-testid") || "";
    return tag === "SVG" || el.hasAttribute("data-icon") || testId === "chat-msg-symbol" || CHAT_LABEL_NOISE_RE.potentialIconTestId.test(testId);
  }
  function getChatPreviewIconLabel(el) {
    if (!isPotentialChatIconElement(el)) return "";
    const identity = getChatIconIdentity(el);
    if (!identity) return "";
    if (CHAT_LABEL_NOISE_RE.ignoredIconIdentity.test(identity)) return "";
    const hostLanguage = getSupportedLanguage(document.documentElement?.lang);
    if (!hostLanguage) {
      return cleanString(
        el.getAttribute("aria-label") || el.getAttribute("title") || el.querySelector?.("title")?.textContent || "",
        false
      );
    }
    const match = CHAT_PREVIEW_ICON_LABELS.find((item) => item.pattern.test(identity));
    return match ? tForLanguage(match.labelKey, hostLanguage) : "";
  }
  function collectChatTextParts(root, parts) {
    if (!root) return;
    const visit = (node) => {
      if (!node) return;
      if (node.nodeType === 3) {
        addChatLabelPart(parts, node.nodeValue || "");
        return;
      }
      if (node.nodeType !== 1) return;
      const el = node;
      const tag = el.tagName ? el.tagName.toUpperCase() : "";
      const testId = el.getAttribute("data-testid") || "";
      if (testId === "section-header") return;
      const role = el.getAttribute("role") || "";
      if (role === "rowheader" || role === "columnheader") return;
      const mappedIcon = getChatPreviewIconLabel(el);
      if (mappedIcon) {
        addChatLabelPart(parts, mappedIcon);
        return;
      }
      if (tag === "SVG" || tag === "TITLE" || tag === "SCRIPT" || tag === "STYLE") return;
      if (el.hasAttribute("data-icon")) return;
      if (testId === "chat-msg-symbol") return;
      if (testId === "text-highlight") {
        Array.from(el.childNodes || []).forEach(visit);
        return;
      }
      Array.from(el.childNodes || []).forEach(visit);
    };
    visit(root);
  }
  function collectChatBadgeLabels(row) {
    const unread = [];
    const status = [];
    const details = [];
    const cellFrame = row.querySelector(SELECTORS.cellFrame);
    row.querySelectorAll("[aria-label]").forEach((el) => {
      if (ownedAttributes.get(el)?.get("aria-label")?.owner === OWNERS.chatLabel) return;
      if (el === getChatRowGridcell(row)) return;
      const label = normalizeChatLabelPart(el.getAttribute("aria-label") || "");
      if (!label) return;
      if (getUnreadDividerRegex().test(label)) {
        addChatLabelPart(unread, label);
        return;
      }
      if (getChatStatusRegex().test(label)) {
        addChatLabelPart(status, label);
        return;
      }
      const isStatusAction = getViewStatusRegex().test(label);
      if (!isStatusAction && !hasFocusableSelfOrDescendant(el) && cellFrame && !cellFrame.contains(el)) {
        addChatLabelPart(details, label);
      }
    });
    return { unread, status, details };
  }
  function buildChatRowNativeLabel(row) {
    const cellFrame = row.querySelector(SELECTORS.cellFrame);
    if (!cellFrame) return "";
    const parts = [];
    const badges = collectChatBadgeLabels(row);
    badges.unread.forEach((label) => addChatLabelPart(parts, label));
    addChatLabelPart(parts, getChatRowTitle(row));
    collectChatTextParts(cellFrame.querySelector('[data-testid="cell-frame-primary-detail"]'), parts);
    collectChatTextParts(cellFrame.querySelector('[data-testid="cell-frame-secondary"]'), parts);
    badges.status.forEach((label) => addChatLabelPart(parts, label));
    badges.details.forEach((label) => addChatLabelPart(parts, label));
    return cleanString(parts.join(" "), "identity");
  }
  function getMessageGridViewport(container) {
    if (!container || !container.children) return null;
    return Array.from(container.children).find(
      (child) => child.matches("[data-tab]") && child.querySelector('div[role="row"]')
    ) || null;
  }
  function isMetaAIReply(message) {
    return hasDirectMetaAISender(message) && !!message.querySelector('[data-testid="msg-container"] .copyable-text.selectable-text');
  }
  function getMetaAIMessageNameId(el) {
    const existingId = el.getAttribute("id");
    if (existingId) return existingId;
    const id = `wa-plus-meta-ai-name-${++metaAIMessageNameId}`;
    applyOwnedAttribute(el, "id", id, OWNERS.metaAIMessageName);
    return id;
  }
  function applyMetaAIMessageName(message) {
    if (!isMetaAIReply(message)) {
      releaseOwnedWithin(message, OWNERS.metaAIMessageName);
      return false;
    }
    const labelledElements = [
      getDirectMetaAISender(message),
      message.querySelector('[data-testid="msg-container"] .copyable-text.selectable-text'),
      message.querySelector('[data-testid="msg-meta"]')
    ].filter(Boolean);
    applyOwnedAttribute(message, "aria-label", null, OWNERS.metaAIMessageName);
    applyOwnedAttribute(message, "aria-labelledby", labelledElements.map(getMetaAIMessageNameId).join(" "), OWNERS.metaAIMessageName);
    return true;
  }
  function applyOwnedMessageRole(el, role, owner) {
    let state = ownedAttributes.get(el)?.get("role");
    if (state && state.owner === owner && el.getAttribute("role") !== state.appliedValue) {
      dropOwnedAttribute(el, "role");
      state = null;
    }
    const currentRole = (el.getAttribute("role") || "").trim();
    if (currentRole && currentRole !== role) return false;
    applyOwnedAttribute(el, "role", role, owner);
    return true;
  }
  function releaseMessageAttributes(owner, keep) {
    for (const el of [...ownedElements]) {
      const attributes = ownedAttributes.get(el);
      if (!attributes || ![...attributes.values()].some((state) => state.owner === owner)) continue;
      if (el.isConnected && keep(el)) continue;
      for (const [name, state] of [...attributes]) {
        if (state.owner === owner) releaseOwnedAttribute(el, name, owner);
      }
    }
  }
  function canApplyOwnedMessageRole(el, role, owner) {
    const state = ownedAttributes.get(el)?.get("role");
    const currentRole = (el.getAttribute("role") || "").trim();
    return !currentRole || currentRole === role || state?.owner === owner && currentRole === state.appliedValue;
  }
  function ensureMessageGridLabel() {
    let label = document.getElementById("wa-plus-message-grid-label");
    if (!label) {
      label = document.createElement("span");
      label.id = "wa-plus-message-grid-label";
      applyVisuallyHiddenStyle(label);
      document.body.appendChild(label);
    }
    label.lang = getLanguage();
    label.dir = "ltr";
    label.textContent = t("messageHistory");
    return label;
  }
  function setMessageGridTabStop(messages2, target) {
    messages2.forEach(
      (message) => applyOwnedAttribute(message, "tabindex", message === target ? "0" : "-1", OWNERS.messageCell)
    );
  }
  function normalizeMessageGridTabStops(messages2, preferred = null) {
    const activeCell = document.activeElement?.closest?.('[role="gridcell"]');
    const rememberedCell = lastFocusedMessageNode?.querySelector?.(".focusable-list-item");
    const target = messages2.includes(preferred) && preferred || messages2.includes(activeCell) && activeCell || messages2.find((message) => message.getAttribute("tabindex") === "0") || messages2.includes(rememberedCell) && rememberedCell || messages2[0];
    if (target) setMessageGridTabStop(messages2, target);
  }
  function handleMessageGridKeydown(event) {
    if (event.defaultPrevented || event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return false;
    if (!["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) return false;
    const cell = event.target?.closest?.('[role="gridcell"]');
    if (!cell || event.target !== cell || ownedAttributes.get(cell)?.get("role")?.owner !== OWNERS.messageCell) return false;
    const grid = cell.closest?.('[role="grid"]');
    if (!grid || ownedAttributes.get(grid)?.get("role")?.owner !== OWNERS.messageGrid) return false;
    const cells = Array.from(grid.querySelectorAll('[role="gridcell"]')).filter(
      (candidate) => ownedAttributes.get(candidate)?.get("role")?.owner === OWNERS.messageCell
    );
    const index = cells.indexOf(cell);
    if (index < 0) return false;
    const targetIndex = event.key === "Home" ? 0 : event.key === "End" ? cells.length - 1 : Math.max(0, Math.min(cells.length - 1, index + (event.key === "ArrowUp" ? -1 : 1)));
    const target = cells[targetIndex];
    setMessageGridTabStop(cells, target);
    target.focus({ preventScroll: true });
    target.scrollIntoView({ block: "nearest" });
    event.preventDefault();
    event.stopPropagation();
    return true;
  }
  function applyMessageGridExperiment() {
    const main = document.querySelector(SELECTORS.main);
    const container = main && main.querySelector(SELECTORS.conversationMessages);
    const viewport = getMessageGridViewport(container);
    const chatReady = !!viewport && isChatMainActive(main);
    const active = isAnnouncementReductionEnabled() && chatReady;
    const rows = active ? Array.from(viewport.querySelectorAll('div[role="row"]')) : [];
    const messages2 = rows.map((row) => row.querySelector(".focusable-list-item"));
    const metaAIReplies = new Set(messages2.filter(isMetaAIReply));
    const completeGrid = active && rows.length > 0 && messages2.every(
      (message, index) => message && message.closest('div[role="row"]') === rows[index] && canApplyOwnedMessageRole(message, "gridcell", OWNERS.messageCell)
    ) && new Set(messages2).size === messages2.length && canApplyOwnedMessageRole(viewport, "grid", OWNERS.messageGrid);
    const messageSet = new Set(messages2);
    const staleMetaAIMessageNames = /* @__PURE__ */ new Set();
    for (const el of [...ownedElements]) {
      const attributes = ownedAttributes.get(el);
      if (![...(attributes || /* @__PURE__ */ new Map()).values()].some((state) => state.owner === OWNERS.metaAIMessageName)) continue;
      if (!el.isConnected) {
        ownedAttributes.delete(el);
        ownedElements.delete(el);
        continue;
      }
      const message = el.matches?.(".focusable-list-item") ? el : el.closest?.(".focusable-list-item");
      if (!message || !metaAIReplies.has(message)) {
        staleMetaAIMessageNames.add(message || el);
      }
    }
    staleMetaAIMessageNames.forEach((message) => releaseOwnedWithin(message, OWNERS.metaAIMessageName));
    metaAIReplies.forEach(applyMetaAIMessageName);
    releaseMessageAttributes(OWNERS.messageGrid, (el) => completeGrid && el === viewport);
    releaseMessageAttributes(OWNERS.messageCell, (el) => completeGrid && messageSet.has(el));
    if (!completeGrid) return;
    if (!applyOwnedMessageRole(viewport, "grid", OWNERS.messageGrid)) {
      releaseMessageAttributes(OWNERS.messageGrid, () => false);
      releaseMessageAttributes(OWNERS.messageCell, () => false);
      return;
    }
    applyOwnedAttribute(
      viewport,
      "aria-labelledby",
      ensureMessageGridLabel().id,
      OWNERS.messageGrid
    );
    applyOwnedAttribute(viewport, "aria-rowcount", "-1", OWNERS.messageGrid);
    messages2.forEach((message) => {
      applyOwnedMessageRole(message, "gridcell", OWNERS.messageCell);
    });
    normalizeMessageGridTabStops(messages2);
  }
  function applyChatMaskedLabel(el, label) {
    applyOwnedAttribute(el, "aria-labelledby", null, OWNERS.chatLabel);
    applyOwnedAttribute(el, "aria-label", label, OWNERS.chatLabel);
  }
  function applyChatMaskedHidden(el) {
    applyOwnedAttribute(el, "aria-hidden", "true", OWNERS.chatHidden);
  }
  function getChatRowGridcell(row) {
    if (!row || !row.querySelector) return null;
    return row.querySelector(':scope > [role="gridcell"]') || Array.from(row.children || []).find((el) => {
      const state = ownedAttributes.get(el)?.get("role");
      if (state?.owner !== OWNERS.chatStructure || state.originalValue !== "gridcell") return false;
      if (el.getAttribute("role") === state.appliedValue) return true;
      dropOwnedAttribute(el, "role");
      return false;
    }) || null;
  }
  function getChatRowActivator(row) {
    const gridcell = getChatRowGridcell(row);
    if (!gridcell || !gridcell.querySelector) return gridcell;
    return gridcell.querySelector(`:scope > [tabindex][aria-selected], :scope > [tabindex]:not(${SELECTORS.cellFrame})`) || gridcell;
  }
  function focusChatRow(row, onFailure, shouldContinue = () => true) {
    if (!shouldContinue() || !getChatRowActivator(row) || getActiveModal()) return false;
    const rowTitle = getChatRowTitle(row);
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    const focusTarget = (retried = false) => {
      if (!shouldContinue() || getActiveModal()) return false;
      const currentRow = row.isConnected ? row : findChatRowByTitle(getChatListRows(), rowTitle);
      if (!currentRow || !applyChatRowNativeMask(currentRow)) {
        if (!retried) {
          schedule(() => focusTarget(true));
        } else if (onFailure) {
          onFailure();
        }
        return !retried;
      }
      const currentTarget = getChatRowActivator(currentRow);
      if (!currentTarget) {
        if (onFailure) onFailure();
        return false;
      }
      if (document.activeElement === currentTarget) {
        lastFocusedChatRowNode = currentRow;
        return true;
      }
      const chatList = currentRow.closest(SELECTORS.chatListInSide);
      if (chatList) normalizeChatListTabStops(chatList, currentRow);
      currentTarget.focus({ preventScroll: true });
      if (document.activeElement !== currentTarget && !retried) {
        schedule(() => focusTarget(true));
      } else if (document.activeElement !== currentTarget) {
        if (onFailure) onFailure();
      } else {
        lastFocusedChatRowNode = currentRow;
      }
      return document.activeElement === currentTarget || !retried;
    };
    schedule(() => focusTarget());
    return true;
  }
  function restoreChatRowNativeMasks(rootEl) {
    releaseOwnedWithin(rootEl, OWNERS.chatLabel);
    releaseOwnedWithin(rootEl, OWNERS.chatHidden);
    releaseOwnedWithin(rootEl, OWNERS.chatStructure);
  }
  function restoreChatRowNativeMasksOutsideChatList() {
    for (const el of [...ownedElements]) {
      const attributes = ownedAttributes.get(el);
      if (!attributes || el.closest && el.closest(SELECTORS.chatListInSide)) continue;
      for (const [name, state] of [...attributes]) {
        if (state.owner === OWNERS.chatLabel || state.owner === OWNERS.chatHidden || state.owner === OWNERS.chatStructure) {
          releaseOwnedAttribute(el, name, state.owner);
        }
      }
    }
  }
  function hasFocusableSelfOrDescendant(el) {
    return !!el && (el.matches(FOCUSABLE_SELECTOR) || !!el.querySelector(FOCUSABLE_SELECTOR));
  }
  function hasUsefulNativeChatText(el) {
    const text = el && (el.getAttribute("aria-label") || el.getAttribute("title") || el.textContent || "");
    return !!normalizeChatLabelPart(text);
  }
  function applyChatRowDescendantMasks(row, maskRoot) {
    const desired = /* @__PURE__ */ new Set();
    maskRoot.querySelectorAll(CHAT_ROW_NATIVE_TEXT_SELECTOR).forEach((el) => {
      if (el === maskRoot) return;
      const isNestedGridcell = el.getAttribute("role") === "gridcell";
      const isStatusAction = getViewStatusRegex().test(
        el.getAttribute("aria-label") || el.getAttribute("title") || ""
      );
      if (el.parentElement && el.parentElement.closest('[aria-hidden="true"]') || hasFocusableSelfOrDescendant(el) || isStatusAction || !isNestedGridcell && !hasUsefulNativeChatText(el)) return;
      desired.add(el);
      applyChatMaskedHidden(el);
    });
    for (const el of [...ownedElements]) {
      if (!row.contains(el)) continue;
      const state = ownedAttributes.get(el)?.get("aria-hidden");
      if (state?.owner === OWNERS.chatHidden && !desired.has(el)) releaseOwnedAttribute(el, "aria-hidden", OWNERS.chatHidden);
    }
  }
  function applyChatRowNativeMask(row) {
    if (!isAnnouncementReductionEnabled()) {
      restoreChatRowNativeMasks(row);
      return false;
    }
    const gridcell = getChatRowGridcell(row);
    const cellFrame = row.querySelector(SELECTORS.cellFrame);
    const activator = getChatRowActivator(row);
    const label = buildChatRowNativeLabel(row);
    if (!gridcell || !cellFrame || !label) {
      restoreChatRowNativeMasks(row);
      return false;
    }
    const canTransferRole = activator && activator !== gridcell && applyOwnedMessageRole(activator, "gridcell", OWNERS.chatStructure);
    if (canTransferRole) {
      const transferFocus = document.activeElement === gridcell;
      releaseOwnedAttribute(gridcell, "aria-label", OWNERS.chatLabel);
      releaseOwnedAttribute(gridcell, "aria-labelledby", OWNERS.chatLabel);
      applyChatMaskedLabel(activator, label);
      applyOwnedAttribute(gridcell, "role", "presentation", OWNERS.chatStructure);
      applyOwnedAttribute(gridcell, "tabindex", null, OWNERS.chatStructure);
      applyChatRowDescendantMasks(row, activator);
      if (transferFocus) activator.focus({ preventScroll: true });
      return true;
    }
    restoreChatRowNativeMasks(row);
    applyChatMaskedLabel(gridcell, label);
    applyChatRowDescendantMasks(row, gridcell);
    return true;
  }
  function normalizeChatListTabStops(chatList, preferredRow = null) {
    const rows = Array.from(getChatListRowCandidates(chatList)).filter((row) => row.querySelector(SELECTORS.cellFrame));
    if (rows.length === 0) return;
    const visibleRows = getElementsInsideViewport(rows, getChatListViewport(chatList));
    const activeRow = document.activeElement?.closest?.('div[role="row"]');
    const target = rows.includes(preferredRow) && preferredRow || rows.includes(activeRow) && activeRow || rows.includes(lastFocusedChatRowNode) && lastFocusedChatRowNode || getPreferredChatRow(visibleRows) || rows[0];
    rows.forEach((row) => {
      const gridcell = getChatRowGridcell(row);
      const activator = getChatRowActivator(row);
      if (!gridcell || !activator || activator === gridcell) return;
      applyOwnedAttribute(gridcell, "tabindex", null, OWNERS.chatStructure);
      applyOwnedAttribute(activator, "tabindex", row === target ? "0" : "-1", OWNERS.chatStructure);
    });
  }
  function fixAccessibilityRoles(rootEl, skipGlobalWork = false) {
    if (!rootEl || !rootEl.querySelectorAll) return null;
    if (!isAnnouncementReductionEnabled()) {
      releaseMessageAttributes(OWNERS.messageGrid, () => false);
      releaseMessageAttributes(OWNERS.messageCell, () => false);
      restoreChatRowNativeMasks(rootEl);
      restoreChatRowNativeMasksOutsideChatList();
      return null;
    }
    if (!skipGlobalWork) {
      applyMessageGridExperiment();
      restoreChatRowNativeMasksOutsideChatList();
    }
    if (!isChatsTabActive()) {
      restoreChatRowNativeMasks(rootEl);
      return null;
    }
    const chatList = getChatListContainer(rootEl);
    if (!chatList) {
      restoreChatRowNativeMasks(rootEl);
      return null;
    }
    const rows = rootEl.matches && rootEl.matches('div[role="row"]') && chatList.contains(rootEl) ? [rootEl] : chatList.querySelectorAll('[data-testid^="list-item-"], div[role="row"]');
    rows.forEach((row) => {
      if (row.querySelector(SELECTORS.cellFrame)) applyChatRowNativeMask(row);
      else restoreChatRowNativeMasks(row);
    });
    return chatList;
  }
  var dirtyRoots = /* @__PURE__ */ new Set();
  var roleFixPending = false;
  function scheduleRoleFix(rootEl) {
    if (!rootEl || !rootEl.querySelectorAll) return;
    dirtyRoots.add(rootEl);
    if (roleFixPending) return;
    roleFixPending = true;
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 50));
    schedule(() => {
      roleFixPending = false;
      const roots = [...dirtyRoots];
      dirtyRoots.clear();
      let chatList = null;
      const messageDirty = roots.some(
        (root) => root.matches?.(SELECTORS.conversationMessages) || root.closest?.(SELECTORS.conversationMessages)
      );
      const chatListDirty = roots.some(
        (root) => root.matches?.(SELECTORS.side) || root.closest?.(SELECTORS.chatListInSide) || root.querySelector?.(SELECTORS.chatList)
      );
      if (messageDirty) applyMessageGridExperiment();
      if (chatListDirty) restoreChatRowNativeMasksOutsideChatList();
      roots.forEach((root) => {
        if (root.isConnected !== false) chatList = fixAccessibilityRoles(root, true) || chatList;
      });
      if (chatList && chatListDirty) normalizeChatListTabStops(chatList);
    });
  }
  function getRoleFixRoot(el) {
    if (!el || !el.closest) return null;
    return el.closest(SELECTORS.conversationMessages) || el.closest('div[role="row"]') || el.closest(SELECTORS.chatListInSide) || el.closest(`${SELECTORS.side}, ${SELECTORS.main}`);
  }
  function applyVisuallyHiddenStyle(el) {
    el.style.position = "absolute";
    el.style.width = "1px";
    el.style.height = "1px";
    el.style.padding = "0";
    el.style.margin = "-1px";
    el.style.overflow = "hidden";
    el.style.clip = "rect(0, 0, 0, 0)";
    el.style.whiteSpace = "nowrap";
    el.style.border = "0";
  }
  function ensureLiveRegion() {
    let liveRegion = document.getElementById("wa-plus-live-region");
    if (!liveRegion) {
      liveRegion = document.createElement("div");
      liveRegion.id = "wa-plus-live-region";
      _origSetAttribute.call(liveRegion, "role", "status");
      _origSetAttribute.call(liveRegion, "aria-live", "polite");
      _origSetAttribute.call(liveRegion, "aria-atomic", "true");
      applyVisuallyHiddenStyle(liveRegion);
      document.body.appendChild(liveRegion);
    }
    liveRegion.lang = getLanguage();
    liveRegion.dir = "ltr";
    ensureMessageLog();
    return liveRegion;
  }
  function ensureMessageLog() {
    let messageLog = document.getElementById("wa-plus-message-log");
    if (!messageLog) {
      messageLog = document.createElement("div");
      messageLog.id = "wa-plus-message-log";
      _origSetAttribute.call(messageLog, "role", "log");
      _origSetAttribute.call(messageLog, "aria-live", "polite");
      _origSetAttribute.call(messageLog, "aria-relevant", "additions");
      _origSetAttribute.call(messageLog, "aria-atomic", "false");
      applyVisuallyHiddenStyle(messageLog);
      document.body.appendChild(messageLog);
    }
    messageLog.lang = getLanguage();
    messageLog.dir = "ltr";
    return messageLog;
  }
  function appendMessages(messages2, generation2) {
    const values = messages2.filter(Boolean);
    if (!values.length || generation2 !== announcementGeneration) return;
    const messageLog = ensureMessageLog();
    values.forEach((text) => {
      const entry = document.createElement("div");
      entry.textContent = text;
      messageLog.appendChild(entry);
    });
    while (messageLog.childElementCount > MESSAGE_LOG_LIMIT) {
      messageLog.removeChild(messageLog.firstElementChild);
    }
  }
  function clearMessageLog() {
    const messageLog = document.getElementById("wa-plus-message-log");
    if (messageLog) messageLog.textContent = "";
  }
  function clearStatusRegion() {
    if (announcementTimer !== null) clearTimeout(announcementTimer);
    announcementTimer = null;
    userAnnouncementUntil = 0;
    const liveRegion = document.getElementById("wa-plus-live-region");
    if (liveRegion) liveRegion.textContent = "";
  }
  function invalidatePassiveAnnouncements() {
    announcementGeneration++;
    clearMessageLog();
  }
  function announce(text) {
    if (!text) return;
    userAnnouncementUntil = Date.now() + 3e3;
    const liveRegion = ensureLiveRegion();
    clearTimeout(announcementTimer);
    liveRegion.textContent = "";
    announcementTimer = setTimeout(() => {
      liveRegion.textContent = text;
      announcementTimer = setTimeout(() => {
        liveRegion.textContent = "";
      }, 3e3);
    }, 0);
  }
  function announcePassiveMessages(messages2, generation2) {
    appendMessages(messages2, generation2);
  }
  function getUserAnnouncementUntil() {
    return userAnnouncementUntil;
  }
  function hasRenderedBox(el) {
    const rect = el.getBoundingClientRect();
    return rect.height > 0 && rect.width > 0;
  }
  function rectsOverlap(inner, outer) {
    return inner.bottom > outer.top && inner.top < outer.bottom && inner.right > outer.left && inner.left < outer.right;
  }
  function getVisibleElements(elements) {
    return Array.from(elements).filter(hasRenderedBox);
  }
  function getElementsInsideViewport(elements, viewport) {
    if (!viewport) return getVisibleElements(elements);
    const viewportRect = viewport.getBoundingClientRect();
    return Array.from(elements).filter((el) => {
      if (!hasRenderedBox(el)) return false;
      return rectsOverlap(el.getBoundingClientRect(), viewportRect);
    });
  }
  function getChatListViewport(chatList) {
    return chatList.closest(SELECTORS.chatListScroller) || chatList.closest('[data-scrolltracepolicy="wa.web.chatlist"]') || chatList.parentElement || chatList;
  }
  function getChatListRowCandidates(chatList) {
    return chatList.querySelectorAll('[data-testid^="list-item-"], div[role="row"]');
  }
  function getChatRowTranslateY(row) {
    const transform = row && row.style ? row.style.transform || "" : "";
    const translateMatch = transform.match(/translateY\((-?\d+(?:\.\d+)?)px\)/i);
    if (translateMatch) return Number(translateMatch[1]);
    const matrixMatch = transform.match(/matrix\([^,]+,[^,]+,[^,]+,[^,]+,[^,]+,\s*(-?\d+(?:\.\d+)?)\)/i);
    return matrixMatch ? Number(matrixMatch[1]) : 0;
  }
  function isNearChatListTop(row) {
    return getChatRowTranslateY(row) <= CHAT_LIST_TOP_FALLBACK_MAX_Y;
  }
  function getChatListRows() {
    if (!isChatsTabActive()) return [];
    const side = document.querySelector(SELECTORS.side);
    if (!side) return [];
    const chatList = side.querySelector(SELECTORS.chatList);
    if (!chatList) return [];
    return getElementsInsideViewport(getChatListRowCandidates(chatList), getChatListViewport(chatList)).filter((row) => row.querySelector && row.querySelector(SELECTORS.cellFrame));
  }
  function getMessageRows() {
    const main = document.querySelector(SELECTORS.main);
    if (!isChatMainActive(main)) return [];
    const messageContainer = main.querySelector(SELECTORS.conversationMessages) || main;
    return getVisibleElements(messageContainer.querySelectorAll('div[role="row"]')).filter((row) => row.querySelector('.focusable-list-item, [data-testid^="conv-msg-"]'));
  }
  function focusItem(el) {
    if (!el || !el.isConnected) return false;
    if (!el.hasAttribute("tabindex") && el.tabIndex < 0) {
      _origSetAttribute.call(el, "tabindex", "-1");
    }
    el.focus({ preventScroll: true });
    return document.activeElement === el;
  }
  function getBestMessageFocusElement(row) {
    if (!row || !row.querySelector) return null;
    const messageItem = row.querySelector(
      '.focusable-list-item[tabindex="0"], .focusable-list-item[role="button"], .focusable-list-item[aria-label], .focusable-list-item'
    );
    if (messageItem) return messageItem;
    const messageWrapper = row.matches('[data-testid^="conv-msg-"][tabindex]') ? row : row.querySelector('[data-testid^="conv-msg-"][tabindex]');
    if (messageWrapper) return messageWrapper;
    return row;
  }
  function getBestInnerFocusElement(row) {
    if (!row) return null;
    if (row.closest && row.closest(`${SELECTORS.main} ${SELECTORS.conversationMessages}`)) {
      return getBestMessageFocusElement(row);
    }
    let gridcell = row.querySelector(':scope > [role="gridcell"][tabindex="0"]');
    if (gridcell) return gridcell;
    gridcell = row.querySelector('[role="gridcell"]');
    if (gridcell) return gridcell;
    const copyable = row.querySelector(".copyable-text");
    if (copyable) return copyable;
    const roleButton = row.querySelector('[role="button"]');
    if (roleButton) return roleButton;
    return row;
  }
  function getHeaderText(info) {
    if (!info) return "";
    const cleanHeaderLines = (value) => String(value || "").split(/\r?\n/).map((line) => cleanString(line, false)).filter(Boolean).join("\n");
    const visible = cleanHeaderLines(info.innerText || info.textContent || "");
    if (visible) return visible;
    const labelledBy = (info.getAttribute("aria-labelledby") || "").split(/\s+/).map((id) => {
      const label = document.getElementById(id);
      return label?.innerText || label?.textContent || "";
    }).filter(Boolean).join("\n");
    return cleanHeaderLines(
      labelledBy || info.getAttribute("aria-label") || info.getAttribute("title") || ""
    );
  }
  function getHeaderInfoButton() {
    const main = document.querySelector(SELECTORS.main);
    if (!isChatMainActive(main)) return null;
    const header = main.querySelector("header");
    if (!header) return null;
    const titleEl = header.querySelector(
      '[data-testid="conversation-info-header-chat-title"], [data-testid="chat-title"], span[title]'
    );
    if (!titleEl) return null;
    const info = titleEl.closest('[data-testid="conversation-info-header"][role="button"]') || titleEl.closest('[data-testid="conversation-info-header"]') || titleEl.closest('[role="button"]');
    return info && header.contains(info) && info.contains(titleEl) ? info : null;
  }
  function getSelectedChatRow(rows) {
    const hasCurrentState = (el) => {
      const value = el && el.getAttribute("aria-current");
      return !!value && value !== "false";
    };
    return rows.find((row) => {
      if (row.getAttribute("aria-selected") === "true" || hasCurrentState(row)) return true;
      const gridcell = getChatRowGridcell(row);
      const activator = getChatRowActivator(row);
      return gridcell && gridcell.getAttribute("aria-selected") === "true" || activator && activator.getAttribute("aria-selected") === "true" || hasCurrentState(gridcell) || hasCurrentState(activator);
    }) || null;
  }
  function getChatRowTitle(row) {
    if (!row || !row.querySelector) return "";
    const titleContainer = row.querySelector('[data-testid="cell-frame-title"]');
    const titled = titleContainer && titleContainer.querySelector("[title]");
    const value = titled ? titled.getAttribute("title") : titleContainer && titleContainer.innerText;
    return cleanString(value || "", false);
  }
  function getCurrentChatTitle() {
    const main = document.querySelector(SELECTORS.main);
    if (!main) return "";
    const header = main.querySelector("header");
    if (header) {
      const titleEl = header.querySelector(
        '[data-testid="conversation-info-header-chat-title"], [data-testid="chat-title"]'
      );
      if (titleEl) {
        const text = cleanString(titleEl.getAttribute("title") || titleEl.textContent || "", false);
        if (text) return text;
      }
    }
    const infoBtn = getHeaderInfoButton();
    if (infoBtn) {
      const titleEl = infoBtn.querySelector('[data-testid="conversation-info-header-chat-title"], [data-testid="chat-title"]');
      if (titleEl) {
        const text = cleanString(titleEl.getAttribute("title") || titleEl.textContent || "", false);
        if (text) return text;
      }
      const titled = infoBtn.querySelector("span[title]");
      if (titled) {
        const text = cleanString(titled.getAttribute("title") || titled.textContent || "", false);
        if (text) return text;
      }
      const fullText = getHeaderText(infoBtn);
      if (fullText) {
        const firstLine = fullText.split("\n")[0].trim();
        const text = cleanString(firstLine, false);
        if (text) return text;
      }
    }
    return "";
  }
  function findChatRowByTitle(rows, title) {
    if (!title) return null;
    return rows.find((row) => getChatRowTitle(row) === title) || null;
  }
  function getPreferredChatRow(rows, origin = null) {
    const selectedRow = getSelectedChatRow(rows);
    const currentChatRow = findChatRowByTitle(rows, getCurrentChatTitle());
    const startedInChatList = !!(origin && origin.closest && origin.closest(SELECTORS.chatListInSide));
    const mayUseRememberedRow = origin === null || startedInChatList;
    if (currentChatRow) return currentChatRow;
    if (selectedRow) return selectedRow;
    if (mayUseRememberedRow && rows.includes(lastFocusedChatRowNode)) return lastFocusedChatRowNode;
    const startedAtDocumentRoot = !origin || origin === document.body || origin === document.documentElement;
    return startedAtDocumentRoot ? rows[0] || null : null;
  }
  function isRenderedElement(el) {
    if (!el || !el.isConnected || el.hidden || el.inert || el.getAttribute("aria-hidden") === "true") return false;
    for (let ancestor = el.parentElement; ancestor; ancestor = ancestor.parentElement) {
      if (ancestor.hidden || ancestor.inert || ancestor.getAttribute("aria-hidden") === "true") return false;
    }
    if (typeof window.getComputedStyle === "function") {
      const style = window.getComputedStyle(el);
      if (style.display === "none" || style.visibility === "hidden") return false;
    }
    return typeof el.getClientRects !== "function" || el.getClientRects().length > 0;
  }
  function getActiveModal(preferredTarget = document.activeElement) {
    const selector = 'dialog[open], [role="dialog"], [role="alertdialog"]';
    const dialogs = Array.from(document.querySelectorAll?.(selector) || []).filter(isRenderedElement);
    if (preferredTarget) {
      const containing = [...dialogs].reverse().find((dialog) => dialog.contains?.(preferredTarget));
      if (containing) return containing;
    }
    return dialogs.at(-1) || null;
  }
  function rememberFocusedRow(target) {
    if (!target.closest) return;
    const row = target.closest('div[role="row"]');
    if (!row) return;
    const side = document.querySelector(SELECTORS.side);
    if (isAnnouncementReductionEnabled() && side && isChatsTabActive() && side.contains(row) && row.closest(SELECTORS.chatList)) {
      applyChatRowNativeMask(row);
      lastFocusedChatRowNode = row;
    }
    const main = document.querySelector(SELECTORS.main);
    if (isChatMainActive(main) && main.contains(row)) {
      lastFocusedMessageNode = row;
      const message = row.querySelector("[data-id]");
      lastFocusedMessageId = message ? message.getAttribute("data-id") : "";
      const cell = target.closest?.('[role="gridcell"]');
      const grid = cell?.closest?.('[role="grid"]');
      if (grid && ownedAttributes.get(cell)?.get("role")?.owner === OWNERS.messageCell) {
        const cells = Array.from(grid.querySelectorAll('[role="gridcell"]')).filter(
          (candidate) => ownedAttributes.get(candidate)?.get("role")?.owner === OWNERS.messageCell
        );
        normalizeMessageGridTabStops(cells, cell);
      }
    }
  }
  function refreshAnnouncementReduction() {
    if (!document.body) return;
    const chatList = fixAccessibilityRoles(document.body);
    if (chatList) normalizeChatListTabStops(chatList);
  }
  function getRememberedFocus() {
    return { lastFocusedChatRowNode, lastFocusedMessageNode, lastFocusedMessageId };
  }
  function clearRememberedChatRow() {
    lastFocusedChatRowNode = null;
  }
  function clearRememberedMessageRow() {
    lastFocusedMessageNode = null;
  }

  // src/audio-experiment.js
  var MAX_REPORTS = 12;
  var MAX_VOICE_MESSAGE_DIAGNOSTIC_BYTES = 32 * 1024 * 1024;
  var MAX_VOICE_MESSAGE_HEADER_SCAN_BYTES = 64 * 1024;
  var VOICE_CAPTURE_ARM_MS = 5e3;
  var CAPTURE_PROFILE = "native-codec-aware-v2";
  var DEFAULT_AUDIO_PROFILE = "clear";
  var DEFAULT_CALL_AUDIO_PROFILE = "clear";
  var CALL_CAPTURE_DEFAULTS = Object.freeze({
    sampleRate: 16e3,
    channelCount: 1,
    sampleSize: 16
  });
  var AUDIO_PROFILES = Object.freeze({
    natural: Object.freeze({
      id: "natural",
      processing: false
    }),
    clear: Object.freeze({
      id: "clear",
      processing: true,
      highPassHz: 70,
      highPassQ: 0.707,
      lowMidHz: 220,
      lowMidQ: 0.9,
      lowMidGainDb: -1.2,
      presenceHz: 3e3,
      presenceQ: 0.8,
      presenceGainDb: 1.1,
      outputGainDb: -1
    }),
    "clear-plus": Object.freeze({
      id: "clear-plus",
      processing: true,
      highPassHz: 85,
      highPassQ: 0.707,
      lowMidHz: 240,
      lowMidQ: 0.9,
      lowMidGainDb: -2.5,
      presenceHz: 3e3,
      presenceQ: 0.8,
      presenceGainDb: 2.5,
      outputGainDb: -2,
      compressor: Object.freeze({
        threshold: -18,
        knee: 12,
        ratio: 2,
        attack: 0.01,
        release: 0.15
      })
    }),
    "noise-filter": Object.freeze({
      id: "noise-filter",
      processing: true,
      highPassHz: 90,
      highPassQ: 0.707,
      lowMidHz: 250,
      lowMidQ: 0.9,
      lowMidGainDb: -2,
      presenceHz: 3200,
      presenceQ: 0.8,
      presenceGainDb: 2,
      outputGainDb: -2,
      inputProcessing: Object.freeze({
        noiseSuppression: true,
        voiceIsolation: true
      })
    })
  });
  var CALL_AUDIO_PROFILES = Object.freeze({
    raw: Object.freeze({
      id: "raw",
      processing: false,
      inputProcessing: Object.freeze({
        echoCancellation: false,
        noiseSuppression: false,
        autoGainControl: false,
        voiceIsolation: false
      })
    }),
    natural: Object.freeze({
      id: "natural",
      processing: false,
      inputProcessing: Object.freeze({
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true,
        voiceIsolation: false
      })
    }),
    clear: Object.freeze({
      id: "clear",
      processing: true,
      highPassHz: 70,
      highPassQ: 0.707,
      lowMidHz: 220,
      lowMidQ: 0.9,
      lowMidGainDb: -1,
      presenceHz: 3e3,
      presenceQ: 0.8,
      presenceGainDb: 1.2,
      outputGainDb: -1.5,
      inputProcessing: Object.freeze({
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true,
        voiceIsolation: false
      })
    }),
    "noise-filter": Object.freeze({
      id: "noise-filter",
      processing: true,
      highPassHz: 90,
      highPassQ: 0.707,
      lowMidHz: 250,
      lowMidQ: 0.9,
      lowMidGainDb: -1.5,
      presenceHz: 3200,
      presenceQ: 0.8,
      presenceGainDb: 1.5,
      outputGainDb: -2,
      inputProcessing: Object.freeze({
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true,
        voiceIsolation: true
      })
    })
  });
  var hooksInstalled = false;
  var armingListenersInstalled = false;
  var nativeGetUserMedia = null;
  var nativeMediaRecorderStart = null;
  var voiceCaptureArmedUntil = 0;
  var voiceMessageStreams = /* @__PURE__ */ new WeakSet();
  var voiceMessageTracks = /* @__PURE__ */ new WeakSet();
  var recorderSessions = /* @__PURE__ */ new WeakMap();
  function isAudioExperimentEnabled() {
    return Boolean(globalThis.navigator?.mediaDevices?.getUserMedia?.__waPlusNativeVoice) && readSetting(STORAGE_KEYS.audioExperiment, "false") === "true";
  }
  function setAudioExperimentEnabled(value) {
    if (value && !installAudioExperimentHooks()) return false;
    return writeSetting(STORAGE_KEYS.audioExperiment, String(Boolean(value)));
  }
  function getAudioExperimentProfile() {
    const saved = readSetting(STORAGE_KEYS.audioExperimentProfile, DEFAULT_AUDIO_PROFILE);
    return Object.prototype.hasOwnProperty.call(AUDIO_PROFILES, saved) ? saved : DEFAULT_AUDIO_PROFILE;
  }
  function setAudioExperimentProfile(value) {
    const normalized = String(value || "").toLowerCase();
    if (!Object.prototype.hasOwnProperty.call(AUDIO_PROFILES, normalized)) return false;
    return writeSetting(STORAGE_KEYS.audioExperimentProfile, normalized);
  }
  function selectAudioExperimentProfile(value) {
    const normalized = String(value || "").toLowerCase();
    if (normalized === "whatsapp") {
      return !isAudioExperimentEnabled() || setAudioExperimentEnabled(false);
    }
    if (!Object.prototype.hasOwnProperty.call(AUDIO_PROFILES, normalized)) return false;
    if (getAudioExperimentProfile() !== normalized && !setAudioExperimentProfile(normalized)) return false;
    return isAudioExperimentEnabled() || setAudioExperimentEnabled(true);
  }
  function isCallAudioExperimentEnabled() {
    return Boolean(globalThis.navigator?.mediaDevices?.getUserMedia?.__waPlusNativeVoice) && readSetting(STORAGE_KEYS.callAudioExperiment, "false") === "true";
  }
  function setCallAudioExperimentEnabled(value) {
    if (value && !installAudioExperimentHooks()) return false;
    return writeSetting(STORAGE_KEYS.callAudioExperiment, String(Boolean(value)));
  }
  function getCallAudioExperimentProfile() {
    const saved = readSetting(STORAGE_KEYS.callAudioExperimentProfile, DEFAULT_CALL_AUDIO_PROFILE);
    return Object.prototype.hasOwnProperty.call(CALL_AUDIO_PROFILES, saved) ? saved : DEFAULT_CALL_AUDIO_PROFILE;
  }
  function setCallAudioExperimentProfile(value) {
    const normalized = String(value || "").toLowerCase();
    if (!Object.prototype.hasOwnProperty.call(CALL_AUDIO_PROFILES, normalized)) return false;
    return writeSetting(STORAGE_KEYS.callAudioExperimentProfile, normalized);
  }
  function selectCallAudioExperimentProfile(value) {
    const normalized = String(value || "").toLowerCase();
    if (normalized === "whatsapp") {
      return !isCallAudioExperimentEnabled() || setCallAudioExperimentEnabled(false);
    }
    if (!Object.prototype.hasOwnProperty.call(CALL_AUDIO_PROFILES, normalized)) return false;
    if (getCallAudioExperimentProfile() !== normalized && !setCallAudioExperimentProfile(normalized)) return false;
    return isCallAudioExperimentEnabled() || setCallAudioExperimentEnabled(true);
  }
  function armNextVoiceMessageCapture() {
    if (!isAudioExperimentEnabled() && !isCallAudioExperimentEnabled()) return false;
    voiceCaptureArmedUntil = Date.now() + VOICE_CAPTURE_ARM_MS;
    return true;
  }
  function consumeVoiceMessageCaptureArm() {
    const armed = Date.now() <= voiceCaptureArmedUntil;
    voiceCaptureArmedUntil = 0;
    return armed;
  }
  function isVoiceMessageButton(target) {
    const button = target?.closest?.("button");
    return Boolean(button?.querySelector?.('[data-icon="mic-outlined"], [data-testid="mic-outlined"]'));
  }
  function handleVoiceCaptureActivation(event) {
    if (event.type === "click" && isVoiceMessageButton(event.target)) {
      armNextVoiceMessageCapture();
    }
  }
  function installVoiceCaptureArming() {
    const hostWindow = globalThis.window;
    if (armingListenersInstalled || typeof hostWindow?.addEventListener !== "function") return;
    hostWindow.addEventListener("click", handleVoiceCaptureActivation, true);
    armingListenersInstalled = true;
  }
  function jsonSafe(value) {
    if (value == null) return value;
    if (["string", "number", "boolean"].includes(typeof value)) return value;
    if (Array.isArray(value)) return value.map(jsonSafe);
    if (typeof value === "object") {
      const output = {};
      for (const key of Object.keys(value)) {
        try {
          output[key] = jsonSafe(value[key]);
        } catch {
        }
      }
      return output;
    }
    return String(value);
  }
  function readReports() {
    try {
      const parsed = JSON.parse(readSetting(STORAGE_KEYS.audioExperimentReports, "[]"));
      return Array.isArray(parsed) ? parsed : [];
    } catch {
      return [];
    }
  }
  function saveReport(report) {
    const normalized = {
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      profile: CAPTURE_PROFILE,
      audioProfile: getAudioExperimentProfile(),
      callAudioProfile: getCallAudioExperimentProfile(),
      ...jsonSafe(report)
    };
    const reports = readReports();
    reports.unshift(normalized);
    reports.length = Math.min(reports.length, MAX_REPORTS);
    writeSetting(STORAGE_KEYS.audioExperimentReports, JSON.stringify(reports));
    console.info("[WA+ Native Voice]", normalized);
    try {
      window.dispatchEvent(new CustomEvent("wa-plus-native-voice-report", { detail: normalized }));
    } catch {
    }
    return normalized;
  }
  function getAudioExperimentReports() {
    return readReports();
  }
  function getCallAudioExperimentReports() {
    return readReports().filter((report) => report?.captureKind === "voice-call");
  }
  function clearAudioExperimentReports() {
    return writeSetting(STORAGE_KEYS.audioExperimentReports, "[]");
  }
  function getAudioExperimentDiagnosticText() {
    return JSON.stringify({
      generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
      status: getAudioExperimentStatus(),
      reportsNewestFirst: getAudioExperimentReports()
    }, null, 2);
  }
  function getCallAudioExperimentDiagnosticText() {
    const status = getAudioExperimentStatus();
    return JSON.stringify({
      generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
      status: {
        activeProfile: status.callAudioEnabled ? status.callAudioProfile : "whatsapp",
        configuredProfile: status.callAudioProfile,
        captureScope: status.callCaptureScope,
        compressor: status.callCompressor,
        profiles: status.callAudioProfiles,
        hooks: status.hooks,
        supportedConstraints: status.supportedConstraints
      },
      reportsNewestFirst: getCallAudioExperimentReports()
    }, null, 2);
  }
  function findAscii(bytes, text) {
    const pattern = Array.from(text, (character) => character.charCodeAt(0));
    for (let offset = 0; offset <= bytes.length - pattern.length; offset += 1) {
      if (pattern.every((value, index) => bytes[offset + index] === value)) return offset;
    }
    return -1;
  }
  function inspectVoiceMessageBytes(arrayBuffer, mimeType) {
    const bytes = new Uint8Array(arrayBuffer);
    const headerBytes = bytes.subarray(0, MAX_VOICE_MESSAGE_HEADER_SCAN_BYTES);
    const opusOffset = findAscii(headerBytes, "OpusHead");
    let container = "unknown";
    if (findAscii(headerBytes.subarray(0, 4), "OggS") === 0) container = "ogg";
    else if (bytes.length >= 4 && bytes[0] === 26 && bytes[1] === 69 && bytes[2] === 223 && bytes[3] === 163) container = "webm";
    else if (findAscii(headerBytes.subarray(4, 12), "ftyp") >= 0) container = "mp4";
    else if (findAscii(headerBytes.subarray(0, 4), "RIFF") === 0 && findAscii(headerBytes.subarray(8, 12), "WAVE") === 0) container = "wav";
    const result = {
      container,
      codec: opusOffset >= 0 ? "opus" : null,
      mimeType: mimeType || null,
      byteLength: bytes.byteLength,
      encodedBitDepth: null
    };
    if (opusOffset >= 0 && opusOffset + 16 <= bytes.length) {
      result.opusChannels = bytes[opusOffset + 9];
      result.opusOriginalInputSampleRate = new DataView(
        arrayBuffer,
        opusOffset + 12,
        4
      ).getUint32(0, true) || null;
      result.encodedBitDepthReason = "Opus is a compressed codec and does not define PCM bits per sample.";
    }
    return result;
  }
  function getVoiceMessageScope(target) {
    if (!target?.querySelector) return null;
    return target.closest?.(
      '[data-testid="msg-container"], [data-testid^="conv-msg-"], div[role="row"]'
    ) || target;
  }
  function getVoiceMessageDomInfo(scope) {
    const signals = Array.from(scope.querySelectorAll?.("[data-testid], [data-icon]") || []).slice(0, 30).map((element) => ({
      tag: element.tagName?.toLowerCase?.() || "",
      testId: element.getAttribute?.("data-testid") || null,
      icon: element.getAttribute?.("data-icon") || null
    })).filter((item) => item.testId || item.icon);
    return {
      scopeTag: scope.tagName?.toLowerCase?.() || null,
      scopeTestId: scope.getAttribute?.("data-testid") || null,
      signals
    };
  }
  async function decodeVoiceMessage(arrayBuffer) {
    const AudioContextClass = globalThis.AudioContext || globalThis.webkitAudioContext || globalThis.window?.AudioContext || globalThis.window?.webkitAudioContext;
    if (typeof AudioContextClass !== "function") return { error: "Web Audio decoding is unavailable." };
    let context = null;
    try {
      context = new AudioContextClass({ latencyHint: "interactive" });
      const decoded = await context.decodeAudioData(arrayBuffer.slice(0));
      return {
        sampleRate: decoded.sampleRate,
        channels: decoded.numberOfChannels,
        frameLength: decoded.length,
        durationSeconds: decoded.duration
      };
    } catch (error) {
      return { error: String(error?.message || error) };
    } finally {
      try {
        await context.close?.();
      } catch {
      }
    }
  }
  async function collectFocusedVoiceMessageDiagnosticText(target) {
    const scope = getVoiceMessageScope(target);
    if (!scope) return null;
    const audio = scope.matches?.("audio") ? scope : scope.querySelector("audio");
    const voiceSignal = audio || scope.querySelector(
      '[data-testid*="audio"], [data-testid*="ptt"], [data-icon*="audio"], [data-icon*="ptt"], [data-icon*="voice"]'
    );
    if (!voiceSignal) return null;
    const sourceElement = audio?.querySelector?.("source");
    const sourceUrl = audio?.currentSrc || audio?.src || sourceElement?.src || "";
    const report = {
      generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
      target: getVoiceMessageDomInfo(scope),
      mediaElement: audio ? {
        sourceKind: sourceUrl ? sourceUrl.match(/^([a-z][a-z0-9+.-]*):/i)?.[1]?.toLowerCase() || "relative" : null,
        declaredType: sourceElement?.type || audio.getAttribute?.("type") || null,
        durationSeconds: Number.isFinite(audio.duration) ? audio.duration : null,
        readyState: audio.readyState ?? null,
        networkState: audio.networkState ?? null,
        paused: audio.paused ?? null,
        ended: audio.ended ?? null
      } : null,
      encoded: null,
      decoded: null
    };
    if (!audio) {
      report.analysisError = "The focused message looks like a voice message, but no HTML audio element is currently exposed.";
      return JSON.stringify(report, null, 2);
    }
    if (!sourceUrl) {
      report.analysisError = "The audio element does not currently expose a source URL. Start playback, then retry.";
      return JSON.stringify(report, null, 2);
    }
    if (typeof globalThis.fetch !== "function") {
      report.analysisError = "Fetch is unavailable, so the encoded audio bytes could not be inspected.";
      return JSON.stringify(report, null, 2);
    }
    try {
      const response = await globalThis.fetch(sourceUrl);
      if (!response.ok) throw new Error(`Audio fetch failed with HTTP ${response.status}`);
      const declaredLength = Number(response.headers?.get?.("content-length")) || 0;
      if (declaredLength > MAX_VOICE_MESSAGE_DIAGNOSTIC_BYTES) {
        throw new Error(`Audio exceeds the ${MAX_VOICE_MESSAGE_DIAGNOSTIC_BYTES}-byte diagnostic limit`);
      }
      const arrayBuffer = await response.arrayBuffer();
      if (arrayBuffer.byteLength > MAX_VOICE_MESSAGE_DIAGNOSTIC_BYTES) {
        throw new Error(`Audio exceeds the ${MAX_VOICE_MESSAGE_DIAGNOSTIC_BYTES}-byte diagnostic limit`);
      }
      const mimeType = response.headers?.get?.("content-type") || sourceElement?.type || audio.getAttribute?.("type") || "";
      report.encoded = inspectVoiceMessageBytes(arrayBuffer, mimeType);
      report.decoded = await decodeVoiceMessage(arrayBuffer);
      const duration = report.decoded?.durationSeconds || report.mediaElement.durationSeconds;
      report.encoded.averageBitrateBps = duration > 0 ? Math.round(arrayBuffer.byteLength * 8 / duration) : null;
    } catch (error) {
      report.analysisError = String(error?.message || error);
    }
    return JSON.stringify(report, null, 2);
  }
  function getFocusedVoiceMessageDiagnosticText(target = globalThis.document?.activeElement) {
    if (!IS_DEBUG_BUILD) return Promise.resolve(null);
    return collectFocusedVoiceMessageDiagnosticText(target);
  }
  function getSupportedConstraintsRaw() {
    try {
      return globalThis.navigator?.mediaDevices?.getSupportedConstraints?.() || {};
    } catch {
      return {};
    }
  }
  function getSupportedConstraints() {
    return jsonSafe(getSupportedConstraintsRaw());
  }
  function getTrackInfo(track) {
    if (!track) return null;
    const info = {
      id: track.id,
      kind: track.kind,
      label: track.label,
      enabled: track.enabled,
      muted: track.muted,
      readyState: track.readyState
    };
    for (const [key, getter] of [
      ["settings", "getSettings"],
      ["constraints", "getConstraints"],
      ["capabilities", "getCapabilities"]
    ]) {
      try {
        if (typeof track[getter] === "function") info[key] = jsonSafe(track[getter]());
      } catch (error) {
        info[`${key}Error`] = String(error?.message || error);
      }
    }
    return info;
  }
  function markVoiceMessageStream(stream) {
    if (!stream || typeof stream !== "object") return;
    voiceMessageStreams.add(stream);
    for (const track of stream.getAudioTracks?.() || []) voiceMessageTracks.add(track);
  }
  function consumeVoiceMessageStream(stream) {
    if (!stream || typeof stream !== "object") return false;
    const tracks = stream.getAudioTracks?.() || [];
    const marked = voiceMessageStreams.has(stream) || tracks.some((track) => voiceMessageTracks.has(track));
    if (!marked) return false;
    voiceMessageStreams.delete(stream);
    for (const track of tracks) voiceMessageTracks.delete(track);
    return true;
  }
  function getRecorderInfo(recorder) {
    return jsonSafe({
      mimeType: recorder?.mimeType || "",
      audioBitsPerSecond: recorder?.audioBitsPerSecond ?? null,
      audioBitrateMode: recorder?.audioBitrateMode ?? null,
      state: recorder?.state || "",
      streamTracks: recorder?.stream?.getAudioTracks?.().map(getTrackInfo) || []
    });
  }
  function observeVoiceMessageRecorder(recorder, timeSlice) {
    if (!recorder || recorderSessions.has(recorder)) return;
    const startedAt = performance.now();
    const session = {
      chunks: 0,
      totalBytes: 0,
      blobTypes: /* @__PURE__ */ new Set(),
      finished: false
    };
    recorderSessions.set(recorder, session);
    const handleData = (event) => {
      const blob = event?.data;
      if (!blob) return;
      session.chunks += 1;
      session.totalBytes += Number(blob.size) || 0;
      if (blob.type) session.blobTypes.add(blob.type);
    };
    const finish = (error) => {
      if (session.finished) return;
      session.finished = true;
      recorderSessions.delete(recorder);
      try {
        recorder.removeEventListener?.("dataavailable", handleData);
      } catch {
      }
      const durationMs = Math.max(0, Math.round(performance.now() - startedAt));
      saveReport({
        kind: "media-recorder-result",
        durationMs,
        timeSlice: typeof timeSlice === "number" ? timeSlice : null,
        chunks: session.chunks,
        totalBytes: session.totalBytes,
        estimatedBitrateBps: durationMs > 0 ? Math.round(session.totalBytes * 8 * 1e3 / durationMs) : null,
        blobTypes: [...session.blobTypes],
        recorder: getRecorderInfo(recorder),
        ...error ? { error: String(error?.message || error) } : {}
      });
    };
    recorder.addEventListener?.("dataavailable", handleData);
    recorder.addEventListener?.("stop", () => finish(), { once: true });
    recorder.addEventListener?.("error", (event) => finish(event?.error || "MediaRecorder error"), { once: true });
    saveReport({
      kind: "media-recorder-start",
      timeSlice: typeof timeSlice === "number" ? timeSlice : null,
      recorder: getRecorderInfo(recorder)
    });
  }
  function installMediaRecorderDiagnosticsHook() {
    const MediaRecorderClass = globalThis.MediaRecorder || globalThis.window?.MediaRecorder;
    const prototype = MediaRecorderClass?.prototype;
    if (!prototype || typeof prototype.start !== "function") return false;
    if (prototype.start.__waPlusNativeVoiceDiagnostics) return true;
    nativeMediaRecorderStart = prototype.start;
    const patchedStart = function(...args) {
      const result = nativeMediaRecorderStart.apply(this, args);
      if (consumeVoiceMessageStream(this.stream)) observeVoiceMessageRecorder(this, args[0]);
      return result;
    };
    Object.defineProperty(patchedStart, "__waPlusNativeVoiceDiagnostics", { value: true });
    try {
      Object.defineProperty(prototype, "start", {
        configurable: true,
        writable: true,
        value: patchedStart
      });
    } catch {
      try {
        prototype.start = patchedStart;
      } catch {
        return false;
      }
    }
    return prototype.start === patchedStart;
  }
  function buildAudioConstraints(constraints, strictSampleRate, profileName) {
    if (!constraints || constraints.audio === false || constraints.audio == null) return constraints;
    const originalAudio = constraints.audio === true ? {} : constraints.audio;
    if (!originalAudio || typeof originalAudio !== "object") return constraints;
    const supported = getSupportedConstraintsRaw();
    const inputProcessing = AUDIO_PROFILES[profileName]?.inputProcessing || {};
    const audio = { ...originalAudio };
    if (supported.sampleRate) {
      audio.sampleRate = strictSampleRate ? { exact: 48e3 } : { ideal: 48e3 };
    }
    if (supported.sampleSize) audio.sampleSize = { ideal: 16 };
    if (supported.channelCount) audio.channelCount = { ideal: 1 };
    if (supported.echoCancellation) audio.echoCancellation = Boolean(inputProcessing.echoCancellation);
    if (supported.noiseSuppression) audio.noiseSuppression = Boolean(inputProcessing.noiseSuppression);
    if (supported.autoGainControl) audio.autoGainControl = Boolean(inputProcessing.autoGainControl);
    if (supported.voiceIsolation) audio.voiceIsolation = Boolean(inputProcessing.voiceIsolation);
    return { ...constraints, audio };
  }
  function buildConstraintAttempts(constraints, profileName) {
    if (!constraints || constraints.audio === false || constraints.audio == null) {
      return [{ mode: "original", constraints }];
    }
    return [
      { mode: "raw-48k", constraints: buildAudioConstraints(constraints, true, profileName) },
      { mode: "raw-48k-best-effort", constraints: buildAudioConstraints(constraints, false, profileName) },
      { mode: "original", constraints }
    ];
  }
  function buildCallAudioConstraints(constraints, profileName) {
    if (!constraints || constraints.audio === false || constraints.audio == null) return constraints;
    const originalAudio = constraints.audio === true ? {} : constraints.audio;
    if (!originalAudio || typeof originalAudio !== "object") return constraints;
    const supported = getSupportedConstraintsRaw();
    const inputProcessing = CALL_AUDIO_PROFILES[profileName]?.inputProcessing || {};
    const audio = { ...originalAudio };
    if (profileName !== "raw") {
      for (const [key, value] of Object.entries(CALL_CAPTURE_DEFAULTS)) {
        if (supported[key] && !Object.prototype.hasOwnProperty.call(originalAudio, key)) {
          audio[key] = value;
        }
      }
    }
    for (const key of ["echoCancellation", "noiseSuppression", "autoGainControl", "voiceIsolation"]) {
      if (supported[key] && Object.prototype.hasOwnProperty.call(inputProcessing, key)) {
        audio[key] = inputProcessing[key];
      }
    }
    return { ...constraints, audio };
  }
  function buildCallConstraintAttempts(constraints, profileName) {
    if (!constraints || constraints.audio === false || constraints.audio == null) {
      return [{ mode: "original", constraints }];
    }
    return [
      { mode: "call-profile", constraints: buildCallAudioConstraints(constraints, profileName) },
      { mode: "original", constraints }
    ];
  }
  function dbToGain(db) {
    return Math.pow(10, db / 20);
  }
  function configureMonoNode(node) {
    try {
      node.channelCount = 1;
      node.channelCountMode = "explicit";
      node.channelInterpretation = "speakers";
    } catch {
    }
  }
  async function buildCodecAwareStream(inputStream, profileName, profiles = AUDIO_PROFILES, modePrefix = "codec-aware") {
    const profile = profiles[profileName];
    if (!profile?.processing) {
      return {
        stream: inputStream,
        processing: { mode: "natural", active: false }
      };
    }
    const AudioContextClass = window.AudioContext || window.webkitAudioContext;
    if (typeof AudioContextClass !== "function" || typeof MediaStream !== "function") {
      throw new Error("Web Audio stream processing is unavailable");
    }
    let context = null;
    const nodes = [];
    try {
      context = new AudioContextClass({ sampleRate: 48e3, latencyHint: "interactive" });
      const source = context.createMediaStreamSource(inputStream);
      const mono = context.createGain();
      const highPass = context.createBiquadFilter();
      const lowMid = context.createBiquadFilter();
      const presence = context.createBiquadFilter();
      const compressor = profile.compressor && typeof context.createDynamicsCompressor === "function" ? context.createDynamicsCompressor() : null;
      const output = context.createGain();
      const destination = context.createMediaStreamDestination();
      nodes.push(source, mono, highPass, lowMid, presence, output, destination);
      if (compressor) nodes.push(compressor);
      configureMonoNode(mono);
      configureMonoNode(destination);
      highPass.type = "highpass";
      highPass.frequency.value = profile.highPassHz;
      highPass.Q.value = profile.highPassQ;
      lowMid.type = "peaking";
      lowMid.frequency.value = profile.lowMidHz;
      lowMid.Q.value = profile.lowMidQ;
      lowMid.gain.value = profile.lowMidGainDb;
      presence.type = "peaking";
      presence.frequency.value = profile.presenceHz;
      presence.Q.value = profile.presenceQ;
      presence.gain.value = profile.presenceGainDb;
      if (compressor) {
        compressor.threshold.value = profile.compressor.threshold;
        compressor.knee.value = profile.compressor.knee;
        compressor.ratio.value = profile.compressor.ratio;
        compressor.attack.value = profile.compressor.attack;
        compressor.release.value = profile.compressor.release;
      }
      output.gain.value = dbToGain(profile.outputGainDb);
      source.connect(mono);
      mono.connect(highPass);
      highPass.connect(lowMid);
      lowMid.connect(presence);
      presence.connect(compressor || output);
      if (compressor) compressor.connect(output);
      output.connect(destination);
      if (context.state === "suspended" && typeof context.resume === "function") {
        await context.resume();
      }
      const outputAudioTracks = destination.stream?.getAudioTracks?.() || [];
      if (!outputAudioTracks.length) throw new Error("Processed stream has no audio track");
      const combinedTracks = [
        ...outputAudioTracks,
        ...inputStream.getVideoTracks?.() || []
      ];
      const processedStream = new MediaStream(combinedTracks);
      const outputTrack = outputAudioTracks[0];
      let cleaned = false;
      const cleanup = (stopInput = true) => {
        if (cleaned) return;
        cleaned = true;
        for (const node of nodes) {
          try {
            node.disconnect?.();
          } catch {
          }
        }
        if (stopInput) {
          for (const track of inputStream.getAudioTracks?.() || []) {
            try {
              track.stop?.();
            } catch {
            }
          }
        }
        try {
          context.close?.();
        } catch {
        }
      };
      if (outputTrack && typeof outputTrack.stop === "function") {
        const nativeStop = outputTrack.stop.bind(outputTrack);
        const wrappedStop = function() {
          try {
            nativeStop();
          } finally {
            cleanup();
          }
        };
        try {
          Object.defineProperty(outputTrack, "stop", {
            configurable: true,
            value: wrappedStop
          });
          if (outputTrack.stop !== wrappedStop) throw new Error("Processed track stop hook was not installed");
        } catch {
          cleanup(false);
          throw new Error("Processed track lifecycle hook is unavailable");
        }
        try {
          outputTrack.addEventListener?.("ended", cleanup, { once: true });
        } catch {
        }
      }
      for (const track of inputStream.getAudioTracks?.() || []) {
        try {
          track.addEventListener?.("ended", () => {
            try {
              outputTrack.stop?.();
            } catch {
              cleanup();
            }
          }, { once: true });
        } catch {
        }
      }
      return {
        stream: processedStream,
        processing: {
          mode: `${modePrefix}-${profileName}`,
          active: true,
          contextSampleRate: context.sampleRate,
          contextState: context.state,
          highPassHz: profile.highPassHz,
          lowMidHz: profile.lowMidHz,
          lowMidGainDb: profile.lowMidGainDb,
          presenceHz: profile.presenceHz,
          presenceGainDb: profile.presenceGainDb,
          outputGainDb: profile.outputGainDb,
          compressor: compressor ? jsonSafe(profile.compressor) : null,
          inputTracks: (inputStream.getAudioTracks?.() || []).map(getTrackInfo),
          outputTracks: outputAudioTracks.map(getTrackInfo)
        }
      };
    } catch (error) {
      for (const node of nodes) {
        try {
          node.disconnect?.();
        } catch {
        }
      }
      try {
        context?.close?.();
      } catch {
      }
      throw error;
    }
  }
  function canRetryConstraintError(error) {
    return error?.name === "OverconstrainedError";
  }
  function installGetUserMediaHook() {
    const mediaDevices = globalThis.navigator?.mediaDevices;
    if (!mediaDevices || typeof mediaDevices.getUserMedia !== "function") return false;
    if (mediaDevices.getUserMedia.__waPlusNativeVoice) return true;
    nativeGetUserMedia = mediaDevices.getUserMedia;
    const patchedGetUserMedia = async function(constraints) {
      const voiceMessageArmed = consumeVoiceMessageCaptureArm();
      const hasAudio = constraints?.audio !== false && constraints?.audio != null;
      const captureKind = voiceMessageArmed ? "voice-message" : "voice-call";
      const enabled = voiceMessageArmed ? isAudioExperimentEnabled() : isCallAudioExperimentEnabled();
      if (!hasAudio) {
        return nativeGetUserMedia.call(this, constraints);
      }
      if (!enabled) {
        if (!IS_DEBUG_BUILD || voiceMessageArmed) return nativeGetUserMedia.call(this, constraints);
        const startedAt2 = performance.now();
        try {
          const inputStream = await nativeGetUserMedia.call(this, constraints);
          if (inputStream?.getAudioTracks?.().length) {
            saveReport({
              kind: "voice-call-getUserMedia",
              captureKind,
              callAudioProfile: "whatsapp",
              constraintMode: "whatsapp-native",
              attempt: 1,
              durationMs: Math.round(performance.now() - startedAt2),
              requestedConstraints: jsonSafe(constraints),
              appliedConstraints: jsonSafe(constraints),
              supportedConstraints: getSupportedConstraints(),
              processing: { mode: "whatsapp-native", active: false },
              tracks: inputStream.getAudioTracks().map(getTrackInfo),
              returnedTracks: inputStream.getAudioTracks().map(getTrackInfo)
            });
          }
          return inputStream;
        } catch (error) {
          saveReport({
            kind: "getUserMedia-error",
            captureKind,
            callAudioProfile: "whatsapp",
            constraintMode: "whatsapp-native",
            attempt: 1,
            durationMs: Math.round(performance.now() - startedAt2),
            requestedConstraints: jsonSafe(constraints),
            error: String(error?.message || error)
          });
          throw error;
        }
      }
      const profiles = voiceMessageArmed ? AUDIO_PROFILES : CALL_AUDIO_PROFILES;
      const selectedProfile = voiceMessageArmed ? getAudioExperimentProfile() : getCallAudioExperimentProfile();
      const attempts = voiceMessageArmed ? buildConstraintAttempts(constraints, selectedProfile) : buildCallConstraintAttempts(constraints, selectedProfile);
      const startedAt = performance.now();
      let lastError = null;
      for (let index = 0; index < attempts.length; index += 1) {
        const attempt = attempts[index];
        try {
          const inputStream = await nativeGetUserMedia.call(this, attempt.constraints);
          let returnedStream = inputStream;
          let processing = { mode: "natural", active: false };
          if (inputStream?.getAudioTracks?.().length && profiles[selectedProfile]?.processing) {
            try {
              const processed = await buildCodecAwareStream(
                inputStream,
                selectedProfile,
                profiles,
                voiceMessageArmed ? "codec-aware" : "call-codec-aware"
              );
              returnedStream = processed.stream;
              processing = processed.processing;
            } catch (error) {
              processing = {
                mode: `${voiceMessageArmed ? "codec-aware" : "call-codec-aware"}-fallback-natural`,
                active: false,
                error: String(error?.message || error)
              };
              saveReport({
                kind: "audio-processing-fallback",
                captureKind,
                constraintMode: attempt.mode,
                processing
              });
            }
          }
          if (inputStream?.getAudioTracks?.().length) {
            if (voiceMessageArmed) markVoiceMessageStream(returnedStream);
            saveReport({
              kind: voiceMessageArmed ? "getUserMedia" : "voice-call-getUserMedia",
              captureKind,
              constraintMode: attempt.mode,
              attempt: index + 1,
              durationMs: Math.round(performance.now() - startedAt),
              requestedConstraints: jsonSafe(constraints),
              appliedConstraints: jsonSafe(attempt.constraints),
              supportedConstraints: getSupportedConstraints(),
              processing,
              tracks: inputStream.getAudioTracks().map(getTrackInfo),
              returnedTracks: returnedStream.getAudioTracks?.().map(getTrackInfo) || []
            });
          }
          return returnedStream;
        } catch (error) {
          lastError = error;
          saveReport({
            kind: "getUserMedia-constraint-retry",
            captureKind,
            constraintMode: attempt.mode,
            attempt: index + 1,
            durationMs: Math.round(performance.now() - startedAt),
            requestedConstraints: jsonSafe(constraints),
            rejectedConstraints: jsonSafe(attempt.constraints),
            error: String(error?.message || error)
          });
          if (!canRetryConstraintError(error)) break;
        }
      }
      saveReport({
        kind: "getUserMedia-error",
        captureKind,
        durationMs: Math.round(performance.now() - startedAt),
        requestedConstraints: jsonSafe(constraints),
        error: String(lastError?.message || lastError || "Unknown getUserMedia error")
      });
      throw lastError;
    };
    Object.defineProperty(patchedGetUserMedia, "__waPlusNativeVoice", { value: true });
    try {
      Object.defineProperty(mediaDevices, "getUserMedia", {
        configurable: true,
        writable: true,
        value: patchedGetUserMedia
      });
    } catch {
      try {
        mediaDevices.getUserMedia = patchedGetUserMedia;
      } catch {
        return false;
      }
    }
    return mediaDevices.getUserMedia === patchedGetUserMedia;
  }
  function installAudioExperimentHooks() {
    if (hooksInstalled && globalThis.navigator?.mediaDevices?.getUserMedia?.__waPlusNativeVoice) {
      installVoiceCaptureArming();
      installMediaRecorderDiagnosticsHook();
      return true;
    }
    hooksInstalled = false;
    hooksInstalled = installGetUserMediaHook();
    if (hooksInstalled) {
      installVoiceCaptureArming();
      installMediaRecorderDiagnosticsHook();
    }
    const hostWindow = globalThis.window;
    if (!hostWindow) return hooksInstalled;
    const api = Object.freeze({
      enable: () => setAudioExperimentEnabled(true),
      disable: () => setAudioExperimentEnabled(false),
      isEnabled: isAudioExperimentEnabled,
      armNextCapture: armNextVoiceMessageCapture,
      getProfile: getAudioExperimentProfile,
      setProfile: setAudioExperimentProfile,
      selectProfile: selectAudioExperimentProfile,
      getProfiles: () => Object.keys(AUDIO_PROFILES),
      enableCallAudio: () => setCallAudioExperimentEnabled(true),
      disableCallAudio: () => setCallAudioExperimentEnabled(false),
      isCallAudioEnabled: isCallAudioExperimentEnabled,
      getCallAudioProfile: getCallAudioExperimentProfile,
      setCallAudioProfile: setCallAudioExperimentProfile,
      selectCallAudioProfile: selectCallAudioExperimentProfile,
      getCallAudioProfiles: () => Object.keys(CALL_AUDIO_PROFILES),
      getReports: getAudioExperimentReports,
      getCallReports: getCallAudioExperimentReports,
      getLastReport: () => getAudioExperimentReports()[0] || null,
      clearReports: clearAudioExperimentReports,
      getDiagnosticText: getAudioExperimentDiagnosticText,
      getCallDiagnosticText: getCallAudioExperimentDiagnosticText,
      ...IS_DEBUG_BUILD ? { getFocusedVoiceMessageDiagnosticText } : {},
      getStatus: getAudioExperimentStatus
    });
    for (const name of ["WAPlusNativeVoice", "WAPlusAudioExperiment"]) {
      try {
        Object.defineProperty(hostWindow, name, { configurable: true, value: api });
      } catch {
        hostWindow[name] = api;
      }
    }
    console.info("[WA+ Native Voice] input hook installed", api.getStatus());
    return hooksInstalled;
  }
  function getAudioExperimentStatus() {
    const MediaRecorderClass = globalThis.MediaRecorder || globalThis.window?.MediaRecorder;
    const selectedProfile = AUDIO_PROFILES[getAudioExperimentProfile()];
    const selectedCallProfile = CALL_AUDIO_PROFILES[getCallAudioExperimentProfile()];
    return {
      enabled: isAudioExperimentEnabled(),
      profile: CAPTURE_PROFILE,
      audioProfile: getAudioExperimentProfile(),
      mode: "native-whatsapp-recorder",
      captureScope: "next-voice-message",
      callAudioEnabled: isCallAudioExperimentEnabled(),
      callAudioProfile: getCallAudioExperimentProfile(),
      callCaptureScope: "non-voice-message-microphone-streams",
      nativeRecorderPreserved: true,
      customEncoder: false,
      customTransport: false,
      compressor: Boolean(selectedProfile.compressor),
      constraintStrategy: ["raw-48k", "raw-48k-best-effort", "original"],
      clearProfile: jsonSafe(AUDIO_PROFILES.clear),
      audioProfiles: jsonSafe(AUDIO_PROFILES),
      callCompressor: Boolean(selectedCallProfile.compressor),
      callAudioProfiles: jsonSafe(CALL_AUDIO_PROFILES),
      hooks: {
        getUserMedia: Boolean(globalThis.navigator?.mediaDevices?.getUserMedia?.__waPlusNativeVoice),
        mediaRecorderDiagnostics: Boolean(MediaRecorderClass?.prototype?.start?.__waPlusNativeVoiceDiagnostics)
      },
      supportedConstraints: getSupportedConstraints()
    };
  }
  installAudioExperimentHooks();

  // src/status-accessibility.js
  var MAX_EXPANSION_CHECKS = 4;
  var MAX_PAUSE_CHECKS = 4;
  var STATUS_VIDEO_LIMIT_SECONDS = 30;
  var STATUS_VIDEO_LIMIT_GUARD_SECONDS = 0.5;
  var STATUS_VIDEO_END_GUARD_SECONDS = 0.35;
  var TIME_RE = new RegExp("\\p{N}{1,2}[:.]\\p{N}{2}", "u");
  var LOCALIZED_CLOCK_RE = new RegExp("(?:\\b(?:today|yesterday|hoy|ayer|hari\\s+ini|kemarin|heute|gestern|um|at|oggi|ieri|hier)\\b(?:\\s+\\p{L}[\\p{L}'\u2019-]*){0,3}\\s+)?\\p{N}{1,2}[:.]\\p{N}{2}(?:\\s*[ap]\\.?m\\.?)?", "iu");
  var GENERIC_CLOCK_RE = new RegExp("((?:[\\p{L}\\p{M}\\p{N}][\\p{L}\\p{M}\\p{N}'\u2019.,\u060C-]*\\s+){0,12}\\p{N}{1,2}[:.]\\p{N}{2}(?:\\s*[ap]\\.?m\\.?)?)", "u");
  var STATUS_PROGRESS_RE = new RegExp("^status\\s+\\p{N}{1,3}\\s+of\\s+\\p{N}{1,3}$", "iu");
  var PROGRESS_PAIR_RE = new RegExp("(\\p{N}{1,3})\\D{1,12}(\\p{N}{1,3})", "u");
  var PROGRESS_CONTROL_PREFIX_RE = /\b(?:go\s+to|goto|jump\s+to|open|ir\s+(?:a|ke)|aller\s+(?:à|au)|ke\s+status|menuju\s+status|buka\s+status|pergi\s+ke)\b/iu;
  var CONTROL_TEXT_RE = /^(?:pause|play|jeda|putar|menu|close|tutup|like|reply|balas|read more|read less|baca selengkapnya)$/iu;
  var CAPTION_NOISE_SELECTOR = [
    "button",
    '[role="button"]',
    "video",
    "audio",
    '[data-testid="status-video"]',
    '[data-testid="media-url-provider"]',
    '[data-testid="music-attribution-song-metadata"]',
    '[data-testid="status-player-contact-name"]',
    '[data-testid="status-progress-bar-segment"]',
    '[data-testid="status-media-error"]',
    '[data-testid="status-player-error"]',
    '[data-testid="media-error"]',
    '[data-testid="media-error-message"]',
    '[aria-hidden="true"]',
    "[hidden]"
  ].join(", ");
  var scheduled = false;
  var scheduleToken = 0;
  var generation = 0;
  var current = null;
  var statusAutoAdvanceGuardStarted = false;
  var statusAutoAdvanceListenerWrappers = /* @__PURE__ */ new WeakMap();
  function scheduleFrame(callback) {
    if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
      return window.requestAnimationFrame(callback);
    }
    return setTimeout(callback, 0);
  }
  function connected(element) {
    return !!element && element.isConnected !== false;
  }
  function isActiveStatusVideo(video) {
    if (!isStatusReadingCleanupEnabled() || video?.tagName !== "VIDEO") return false;
    const root = video.closest?.(SELECTORS.statusPlayerRoot);
    const statusVideos = uniqueElements([
      ...queryAll(root, SELECTORS.statusVideo),
      query(root, SELECTORS.statusVideo)
    ]);
    return connected(root) && isRenderedElement(root) && isRenderedElement(video) && statusVideos.some((statusVideo) => isRenderedElement(statusVideo) && (statusVideo === video || !!statusVideo.contains?.(video)));
  }
  function shouldSuppressStatusVideoTimeUpdate(video) {
    if (!isActiveStatusVideo(video)) return false;
    if (video?.tagName !== "VIDEO" || video.ended || !Number.isFinite(video.duration) || video.duration <= STATUS_VIDEO_LIMIT_SECONDS || !Number.isFinite(video.currentTime) || video.currentTime < STATUS_VIDEO_LIMIT_SECONDS - STATUS_VIDEO_LIMIT_GUARD_SECONDS) return false;
    return true;
  }
  function shouldPauseStatusVideoBeforeEnd(video) {
    return isActiveStatusVideo(video) && !video.ended && !video.paused && Number.isFinite(video.duration) && Number.isFinite(video.currentTime) && video.duration - video.currentTime <= STATUS_VIDEO_END_GUARD_SECONDS;
  }
  function isWhatsAppStatusAutoAdvanceListener(type, listener) {
    if (type !== "timeupdate") return false;
    if (typeof listener !== "function") return false;
    try {
      return Function.prototype.toString.call(listener).includes("status_video_max_duration");
    } catch {
      return false;
    }
  }
  function startStatusAutoAdvanceGuard() {
    if (statusAutoAdvanceGuardStarted || typeof HTMLMediaElement === "undefined") return;
    const prototype = HTMLMediaElement.prototype;
    const nativeAddEventListener = prototype.addEventListener;
    const nativeRemoveEventListener = prototype.removeEventListener;
    if (typeof nativeAddEventListener !== "function" || typeof nativeRemoveEventListener !== "function") return;
    const guardedAddEventListener = function(type, listener, options) {
      if (!isWhatsAppStatusAutoAdvanceListener(type, listener)) {
        return nativeAddEventListener.call(this, type, listener, options);
      }
      let wrappers = statusAutoAdvanceListenerWrappers.get(listener);
      if (!wrappers) {
        wrappers = /* @__PURE__ */ new Map();
        statusAutoAdvanceListenerWrappers.set(listener, wrappers);
      }
      let wrapped = wrappers.get(type);
      if (!wrapped) {
        wrapped = function(event) {
          if (shouldPauseStatusVideoBeforeEnd(this)) {
            this.pause();
            return;
          }
          if (!shouldSuppressStatusVideoTimeUpdate(this)) return listener.call(this, event);
        };
        wrappers.set(type, wrapped);
      }
      return nativeAddEventListener.call(this, type, wrapped, options);
    };
    const guardedRemoveEventListener = function(type, listener, options) {
      const wrapped = typeof listener === "function" ? statusAutoAdvanceListenerWrappers.get(listener)?.get(type) : null;
      return nativeRemoveEventListener.call(this, type, wrapped || listener, options);
    };
    Object.defineProperties(prototype, {
      addEventListener: { configurable: true, writable: true, value: guardedAddEventListener },
      removeEventListener: { configurable: true, writable: true, value: guardedRemoveEventListener }
    });
    statusAutoAdvanceGuardStarted = true;
  }
  function cleanText(value) {
    return String(value || "").replace(/\s+/gu, " ").trim();
  }
  function query(root, selector) {
    return root?.querySelector?.(selector) || null;
  }
  function queryAll(root, selector) {
    return root?.querySelectorAll ? Array.from(root.querySelectorAll(selector)) : [];
  }
  function uniqueElements(elements) {
    return [...new Set(elements.filter(Boolean))];
  }
  function queryRendered(root, selector) {
    return uniqueElements([
      ...queryAll(root, selector),
      query(root, selector)
    ]).find(isRenderedElement) || null;
  }
  function readText(element) {
    return cleanText(element?.textContent);
  }
  function aliases(customKey, defaultKey) {
    const values = [
      ...LANGUAGES.map(({ value }) => tForLanguage(defaultKey, value)),
      getCustomText(customKey)
    ];
    return values.flatMap((value) => String(value || "").split("|")).map((value) => cleanText(value).toLowerCase()).filter(Boolean);
  }
  function defaultAliases(defaultKey) {
    return LANGUAGES.flatMap(({ value }) => String(tForLanguage(defaultKey, value) || "").split("|")).map((value) => cleanText(value).toLowerCase()).filter(Boolean);
  }
  function hasAlias(value, values) {
    const normalized = cleanText(value).toLowerCase();
    return !!normalized && values.includes(normalized);
  }
  function isButton(element) {
    if (!element) return false;
    if (element.matches?.('a[href], [role="link"]') || element.closest?.('a[href], [role="link"]')) return false;
    return element.tagName === "BUTTON" || element.getAttribute?.("role") === "button";
  }
  function isFocusedInside(element) {
    const active = typeof document !== "undefined" ? document.activeElement : null;
    return !!active && (active === element || !!element?.contains?.(active));
  }
  function activateControl(control) {
    control.click();
  }
  function hasProtectedExternalFocus() {
    const active = typeof document !== "undefined" ? document.activeElement : null;
    if (!active) return false;
    return !!active.closest?.('dialog, [role="dialog"], [role="alertdialog"], [role="menu"], input, textarea, [contenteditable="true"]');
  }
  function hasProtectedControlFocus(viewer) {
    const active = typeof document !== "undefined" ? document.activeElement : null;
    if (!active || hasProtectedExternalFocus()) return !!active;
    const control = active.closest?.(
      'button, [role="button"], a[href], [role="link"], [role="menuitem"], [role="tab"]'
    );
    if (!control) return false;
    return control !== viewer.contentButton && !viewer.contentButton?.contains?.(control);
  }
  function getSummaryShell(viewer) {
    const active = typeof document !== "undefined" ? document.activeElement : null;
    if (!connected(active) || active === viewer.contentButton || active.tagName !== "DIV" || active.getAttribute?.("tabindex") === null || !isRenderedElement(active)) return null;
    if (active.closest?.(
      'button, [role="button"], a[href], [role="link"], input, textarea, select, [contenteditable="true"]'
    )) return null;
    const roleState = ownedAttributes.get(active)?.get("role");
    const role = cleanText(active.getAttribute?.("role"));
    const ownsPresentation = roleState?.owner === OWNERS.statusViewer && roleState.appliedValue === "presentation";
    if (role && !(ownsPresentation && role === "presentation")) return null;
    return active.contains?.(viewer.root) || active.contains?.(viewer.contentButton) ? active : null;
  }
  function resolveViewer(root) {
    if (!connected(root)) return null;
    const marker = root.matches?.(SELECTORS.statusActiveMarker) ? root : root.closest?.(SELECTORS.statusActiveMarker) || query(root, SELECTORS.statusActiveMarker);
    if (!connected(marker) || !isRenderedElement(root) || !isRenderedElement(marker)) return null;
    if (marker !== root && !marker.contains?.(root) && !root.contains?.(marker)) return null;
    const textNode = queryRendered(root, SELECTORS.statusText);
    const videoNode = queryRendered(root, SELECTORS.statusVideo);
    const imageNode = queryRendered(root, SELECTORS.statusImage);
    const voiceNode = videoNode || imageNode || textNode ? null : query(root, SELECTORS.statusVoice);
    const audioNode = voiceNode ? query(root, SELECTORS.statusAudio) : null;
    const mediaNode = videoNode || imageNode || voiceNode || textNode;
    const contentButton = mediaNode?.closest?.("button") || null;
    if (!connected(contentButton) || !isRenderedElement(contentButton)) return null;
    return { root, marker, textNode, videoNode, voiceNode, audioNode, imageNode, mediaNode, contentButton };
  }
  function getActiveViewer() {
    if (typeof document === "undefined") return null;
    const roots = queryAll(document, SELECTORS.statusPlayerRoot);
    if (roots.length === 0) {
      const firstRoot = document.querySelector?.(SELECTORS.statusPlayerRoot);
      if (firstRoot) roots.push(firstRoot);
    }
    for (const root of roots) {
      const viewer = resolveViewer(root);
      if (viewer) return viewer;
    }
    return null;
  }
  function getSender(viewer) {
    const contact = query(viewer.root, SELECTORS.statusContactName);
    return isRenderedElement(contact) ? readText(contact) : "";
  }
  function extractTimeValue(value) {
    const text = cleanText(value);
    if (!text) return "";
    const segments = text.split(/\s*(?:•|·|\|)\s*/u).map(cleanText).filter(Boolean);
    for (const segment of segments) {
      const genericClock2 = segment.match(GENERIC_CLOCK_RE);
      if (genericClock2) return cleanText(genericClock2[1]);
      const localizedClock2 = segment.match(LOCALIZED_CLOCK_RE);
      if (localizedClock2) return cleanText(localizedClock2[0]);
    }
    const genericClock = text.match(GENERIC_CLOCK_RE);
    if (genericClock) return cleanText(genericClock[1]);
    const localizedClock = text.match(LOCALIZED_CLOCK_RE);
    if (localizedClock) return cleanText(localizedClock[0]);
    const clock = text.match(TIME_RE);
    return clock ? clock[0] : "";
  }
  function descendantElements(root) {
    const elements = [];
    const visit = (element) => {
      if (!element) return;
      elements.push(element);
      for (const child of Array.from(element.children || [])) visit(child);
    };
    visit(root);
    return elements;
  }
  function findTimeInElement(element, sender) {
    for (const candidate of descendantElements(element)) {
      if (!isRenderedElement(candidate)) continue;
      let text = readText(candidate);
      const messagePrefix = cleanText(`Message to ${sender}`);
      if (messagePrefix && text.toLowerCase().startsWith(messagePrefix.toLowerCase())) {
        text = text.slice(messagePrefix.length).trim();
      } else if (sender) {
        const senderIndex = text.toLowerCase().indexOf(cleanText(sender).toLowerCase());
        const clockIndex = text.search(TIME_RE);
        if (senderIndex >= 0 && clockIndex > senderIndex) text = text.slice(senderIndex + cleanText(sender).length).trim();
      }
      const directTime = text.split(/\s*(?:•|·|\|)\s*/u).map(cleanText).map((segment) => ({ segment, time: extractTimeValue(segment) })).find(({ segment, time: time2 }) => time2 && !/\bmessage\s+to\b/iu.test(segment))?.time;
      const time = directTime || extractTimeValue(text);
      if (time) return time;
    }
    return "";
  }
  function findTime(viewer, sender) {
    const contact = query(viewer.root, SELECTORS.statusContactName);
    if (!isRenderedElement(contact)) return "";
    let ancestor = contact.parentElement;
    for (let depth = 0; ancestor && depth < 4; depth += 1) {
      for (const child of Array.from(ancestor.children || [])) {
        if (child === contact || child.contains?.(contact)) continue;
        if (child.contains?.(viewer.contentButton)) continue;
        const candidate = findTimeInElement(child, sender);
        if (candidate && candidate !== sender && !CONTROL_TEXT_RE.test(candidate)) {
          return candidate;
        }
      }
      ancestor = ancestor.parentElement;
    }
    const header = contact.parentElement;
    return isRenderedElement(header) ? extractTimeValue(readText(header).replace(sender, "").trim()) : "";
  }
  function getProgressIdentity(viewer) {
    const progressElements = uniqueElements([
      ...queryAll(viewer.root, SELECTORS.statusProgressSegment),
      query(viewer.root, SELECTORS.statusProgressSegment)
    ]).filter(isRenderedElement);
    let fallback = "";
    for (const element of progressElements) {
      let ancestor = element;
      for (let depth = 0; ancestor && depth < 4; depth += 1) {
        const label = cleanText(ancestor.getAttribute?.("aria-label"));
        if (STATUS_PROGRESS_RE.test(label)) return label;
        const match = label.match(PROGRESS_PAIR_RE);
        if (match) {
          const identity = `Status ${match[1]} of ${match[2]}`;
          if (!fallback) fallback = identity;
          if (!PROGRESS_CONTROL_PREFIX_RE.test(label)) return identity;
        }
        ancestor = ancestor.parentElement;
      }
    }
    return fallback;
  }
  function getTitle(viewer) {
    const title = query(viewer.root, SELECTORS.statusTitle);
    const titleText = isRenderedElement(title) ? readText(title) : "";
    if (titleText) return titleText;
    const attribution = query(viewer.root, SELECTORS.statusAttribution);
    return isRenderedElement(attribution) ? cloneVisibleText(attribution) : "";
  }
  function getMediaFallback() {
    return cleanText(getCustomText("status-media-fallback")) || t("statusMediaFallback");
  }
  function findPauseButton(viewer) {
    const pauseNames = aliases("status-pause-labels", "statusPauseDefaultLabels");
    return queryAll(viewer.root, 'button, [role="button"]').find((button) => {
      if (button === viewer.contentButton || !isRenderedElement(button) || button.disabled || button.getAttribute?.("aria-disabled") === "true") return false;
      if (!isButton(button)) return false;
      const name = button.getAttribute?.("aria-label") || readText(button);
      if (hasAlias(name, pauseNames)) return true;
      if (cleanText(name)) return false;
      return !!query(button, "svg title") && /ic-pause-filled/iu.test(readText(query(button, "svg title")));
    }) || null;
  }
  function findReadMoreButton(viewer) {
    const readMoreNames = aliases("status-read-more-labels", "statusReadMoreDefaultLabels");
    const readLessNames = defaultAliases("statusReadLessDefaultLabels");
    const scopes = uniqueElements([
      viewer.videoNode?.parentElement,
      viewer.contentButton?.parentElement,
      viewer.root
    ]);
    for (const scope of scopes) {
      const buttons = queryAll(scope, 'button, [role="button"]');
      for (const button of buttons) {
        if (!isRenderedElement(button) || button === viewer.contentButton || !isButton(button) || button.disabled || button.getAttribute?.("aria-disabled") === "true") continue;
        const ariaLabel = button.getAttribute?.("aria-label");
        const name = ariaLabel || readText(button);
        const strong = query(button, "strong");
        const expanded = button.getAttribute?.("aria-expanded");
        const collapsed = expanded === "false";
        const exactLabel = !!ariaLabel && readMoreNames.includes(cleanText(ariaLabel).toLowerCase());
        const strongLabel = readText(strong);
        const readMoreMatch = hasAlias(name, readMoreNames) || hasAlias(strongLabel, readMoreNames);
        const readLessMatch = hasAlias(name, readLessNames) || hasAlias(strongLabel, readLessNames);
        if (readLessMatch) continue;
        if (expanded === "true") continue;
        if (readMoreMatch && (collapsed || exactLabel || hasAlias(strongLabel, readMoreNames) && name !== strongLabel)) {
          return button;
        }
      }
    }
    return null;
  }
  function findCaptionButton(viewer) {
    const expanderNames = [
      ...aliases("status-read-more-labels", "statusReadMoreDefaultLabels"),
      ...defaultAliases("statusReadLessDefaultLabels")
    ];
    const scopes = uniqueElements([
      viewer.videoNode?.parentElement,
      viewer.contentButton?.parentElement,
      viewer.root
    ]);
    const explicitCaption = scopes.flatMap((scope) => queryAll(scope, 'button, [role="button"]')).filter((button) => {
      if (button === viewer.contentButton || !isButton(button) || !isRenderedElement(button) || button.disabled || button.getAttribute?.("aria-disabled") === "true") return false;
      const ariaLabel = button.getAttribute?.("aria-label");
      const name = ariaLabel || readText(button);
      const strongLabel = readText(query(button, "strong"));
      const hasExpandedState = button.hasAttribute?.("aria-expanded");
      return hasAlias(ariaLabel, expanderNames) || hasExpandedState || hasAlias(strongLabel, expanderNames) && name !== strongLabel;
    }).map((button) => ({ button, text: cloneVisibleText(button, { keepRootButton: true }) })).filter((candidate) => candidate.text && !CONTROL_TEXT_RE.test(candidate.text)).sort((left, right) => right.text.length - left.text.length)[0]?.button;
    if (explicitCaption) return explicitCaption;
    const sibling = viewer.contentButton?.nextElementSibling;
    if (!isRenderedElement(sibling)) return null;
    const plainCaptions = uniqueElements([
      isButton(sibling) ? sibling : null,
      ...queryAll(sibling, 'button, [role="button"]')
    ]).filter((button) => {
      if (!isButton(button) || !isRenderedElement(button) || button.disabled || button.getAttribute?.("aria-disabled") === "true" || cleanText(button.getAttribute?.("aria-label"))) return false;
      const text = cloneVisibleText(button, { keepRootButton: true });
      return text && !CONTROL_TEXT_RE.test(text);
    });
    return plainCaptions.length === 1 ? plainCaptions[0] : null;
  }
  function removeChildrenMatching(root, selector) {
    for (const element of queryAll(root, selector)) {
      element.remove?.();
      if (element.parentElement?.removeChild) element.parentElement.removeChild(element);
    }
  }
  function removeCaptionExpanderLabels(root, source) {
    const expanderNames = [
      ...aliases("status-read-more-labels", "statusReadMoreDefaultLabels"),
      ...defaultAliases("statusReadLessDefaultLabels")
    ];
    if (!hasAlias(readText(query(source, "strong")), expanderNames)) return;
    const matches = queryAll(root, "strong").filter((child2) => hasAlias(readText(child2), expanderNames));
    const child = matches.at(-1);
    if (!child) return;
    child.remove?.();
    if (child.parentElement?.removeChild) child.parentElement.removeChild(child);
  }
  function cloneVisibleText(element, options = {}) {
    if (!element) return "";
    const clone = element.cloneNode?.(true);
    if (!clone) return readText(element);
    removeChildrenMatching(clone, CAPTION_NOISE_SELECTOR);
    for (const child of queryAll(clone, "*")) {
      const style = child.getAttribute?.("style") || "";
      if (child.hidden || child.getAttribute?.("aria-hidden") === "true" || /(?:^|[;\s])(display|visibility)\s*:\s*(?:none|hidden)\b/iu.test(style)) {
        child.remove?.();
        if (child.parentElement?.removeChild) child.parentElement.removeChild(child);
      }
    }
    if (options.keepRootButton) removeCaptionExpanderLabels(clone, element);
    const imageAlts = queryAll(clone, "img[alt]").map((image) => cleanText(image.getAttribute?.("alt"))).filter(Boolean);
    return cleanText([readText(clone), ...imageAlts].join(" "));
  }
  function getCaption(viewer, record) {
    if (viewer.voiceNode) return "";
    if (!viewer.videoNode && viewer.textNode && isRenderedElement(viewer.textNode)) {
      return cloneVisibleText(viewer.textNode);
    }
    const inViewer = (node) => connected(node) && isRenderedElement(node) && (node === viewer.root || viewer.root.contains?.(node) || viewer.mediaNode?.parentElement?.contains?.(node) || viewer.contentButton?.parentElement?.contains?.(node));
    if (!inViewer(record.captionButton)) record.captionButton = findCaptionButton(viewer);
    const candidates = uniqueElements([
      inViewer(record.captionHost) ? record.captionHost : null,
      viewer.contentButton
    ]);
    return [
      inViewer(record.captionButton) ? cloneVisibleText(record.captionButton, { keepRootButton: true }) : "",
      ...candidates.map((element) => cloneVisibleText(element))
    ].sort((left, right) => right.length - left.length)[0] || "";
  }
  function getMediaIdentity(viewer) {
    const mediaElement = viewer.audioNode || (viewer.mediaNode?.matches?.("video") ? viewer.mediaNode : query(viewer.mediaNode, "video") || viewer.mediaNode);
    const stableIdentity = cleanText(
      viewer.root?.getAttribute?.("data-status-id") || viewer.mediaNode?.getAttribute?.("data-status-id") || mediaElement?.getAttribute?.("data-status-id") || viewer.root?.getAttribute?.("data-media-id") || viewer.mediaNode?.getAttribute?.("data-media-id") || mediaElement?.getAttribute?.("data-media-id") || viewer.contentButton?.getAttribute?.("data-status-id") || viewer.contentButton?.getAttribute?.("data-media-id") || ""
    );
    if (stableIdentity) return `id:${stableIdentity}`;
    if (!viewer.videoNode && !viewer.voiceNode) return "";
    const source = cleanText(mediaElement?.currentSrc || mediaElement?.getAttribute?.("src") || "");
    return source ? `src:${source}` : "";
  }
  function createIdentity(sender, time, progress) {
    return [sender, time, progress].join("\0");
  }
  function normalizeClockText(value) {
    return cleanText(value).replace(new RegExp("(?<=\\p{N})[.:](?=\\p{N})", "gu"), ":");
  }
  function timesRepresentSameClock(previous, next) {
    const previousText = cleanText(previous);
    const nextText = cleanText(next);
    if (!previousText || !nextText) return false;
    if (normalizeClockText(previousText) === normalizeClockText(nextText)) return true;
    const previousClock = previousText.match(TIME_RE)?.[0];
    const nextClock = nextText.match(TIME_RE)?.[0];
    if (!previousClock || !nextClock || normalizeClockText(previousClock) !== normalizeClockText(nextClock)) return false;
    return previousText === previousClock || nextText === nextClock;
  }
  function sameIdentity(record, viewer, identity, sender, time, progress, mediaIdentity) {
    if (!record || record.contentButton !== viewer.contentButton) return false;
    if (!sender && !time && !progress) return false;
    const mediaKind = viewer.videoNode ? "video" : viewer.voiceNode ? "audio" : viewer.textNode ? "text" : "other";
    if (record.mediaKind && record.mediaKind !== mediaKind) return false;
    if (record.mediaIdentity && mediaIdentity && record.mediaIdentity !== mediaIdentity) {
      const recordStable2 = record.mediaIdentity.startsWith("id:");
      const mediaStable2 = mediaIdentity.startsWith("id:");
      if (recordStable2 && mediaStable2 || !recordStable2 && !mediaStable2 && (!record.progress || !progress)) {
        return false;
      }
    }
    const recordStable = record.mediaIdentity?.startsWith("id:") || false;
    const mediaStable = mediaIdentity?.startsWith("id:") || false;
    if (recordStable && !mediaStable) return false;
    if (record.identity === identity) return true;
    if (record.sender && !sender || record.time && !time || record.progress && !progress) return false;
    const changed = (previous, next) => !!previous && !!next && previous !== next;
    const timeChanged = changed(record.time, time) && !timesRepresentSameClock(record.time, time);
    return !changed(record.sender, sender) && !timeChanged && !changed(record.progress, progress);
  }
  function releaseTarget(target) {
    if (!target) return;
    releaseOwnedAttribute(target, "aria-labelledby", OWNERS.statusViewer);
    releaseOwnedAttribute(target, "aria-label", OWNERS.statusViewer);
  }
  function releaseSummaryShell(shell) {
    if (!shell) return;
    releaseOwnedAttribute(shell, "role", OWNERS.statusViewer);
    releaseOwnedAttribute(shell, "tabindex", OWNERS.statusViewer);
  }
  function releaseRecordTargets(record) {
    if (!record) return;
    releaseTarget(record.summaryTarget);
    if (record.contentButton !== record.summaryTarget) releaseTarget(record.contentButton);
    releaseSummaryShell(record.summaryShell);
  }
  function releaseCurrent() {
    if (!current) return;
    releaseRecordTargets(current);
    current = null;
    generation += 1;
  }
  function ensureRecord(viewer, sender, time, title, progress) {
    const identity = createIdentity(sender, time, progress);
    const mediaIdentity = getMediaIdentity(viewer);
    const mediaKind = viewer.videoNode ? "video" : viewer.voiceNode ? "audio" : viewer.textNode ? "text" : "other";
    if (sameIdentity(current, viewer, identity, sender, time, progress, mediaIdentity)) {
      current.generation = generation;
      current.identity = identity || current.identity;
      current.sender = sender || current.sender;
      current.time = time || current.time;
      current.title = title;
      current.progress = progress || current.progress;
      if (mediaIdentity || !current.mediaIdentity?.startsWith("id:")) current.mediaIdentity = mediaIdentity;
      current.mediaKind = mediaKind;
      return current;
    }
    releaseRecordTargets(current);
    generation += 1;
    current = {
      generation,
      identity,
      sender,
      time,
      title,
      progress,
      mediaIdentity,
      mediaKind,
      contentButton: viewer.contentButton,
      summaryTarget: null,
      summaryShell: null,
      marker: viewer.marker,
      mediaNode: viewer.mediaNode,
      pauseAttempted: false,
      pauseControlFound: false,
      pauseChecks: 0,
      expandAttempted: !!viewer.textNode,
      expansionChecks: 0,
      waitingForExpansion: false,
      expansionFailed: false,
      captionButton: null,
      captionHost: null,
      expandControlFound: false,
      captionLengthBeforeExpansion: 0,
      captionBaselineCaptured: false,
      committedSignature: ""
    };
    return current;
  }
  function applyPrivacy(value, host) {
    return isPrivacyModeEnabled() ? maskPhoneNumbers(value, host) : value;
  }
  function composeLabel(viewer, record) {
    const body = getCaption(viewer, record);
    const media = viewer.textNode ? "" : viewer.voiceNode ? t("voiceMessage") : record.title || getMediaFallback();
    const fields = [record.sender, media, body, record.time].map((value) => applyPrivacy(cleanText(value), viewer.contentButton)).filter(Boolean);
    const isolatedFields = fields.map(isolateBidiText);
    const separator = t("statusSummarySeparator") || ". ";
    return isolatedFields.reduce((label, field, index) => {
      if (!label) return field;
      const joiner = /[.!?。!?]$/u.test(fields[index - 1]) && /^[.!?]/u.test(separator) ? separator.slice(1) : separator;
      return `${label}${joiner}${field}`;
    }, "");
  }
  function commitLabel(viewer, record) {
    const target = viewer.contentButton;
    if (!connected(target) || !connected(viewer.contentButton) || !connected(viewer.root) || current !== record || record.generation !== generation) return;
    if (!record.sender && !record.time) return;
    if (record.summaryTarget && record.summaryTarget !== target) releaseTarget(record.summaryTarget);
    if (record.summaryTarget !== target) record.committedSignature = "";
    record.summaryTarget = target;
    if (!connected(record.summaryShell)) record.summaryShell = null;
    const shell = record.summaryShell || getSummaryShell(viewer);
    if (shell) {
      record.summaryShell = shell;
      applyOwnedAttribute(shell, "role", "presentation", OWNERS.statusViewer);
      applyOwnedAttribute(shell, "tabindex", null, OWNERS.statusViewer);
    }
    const label = composeLabel(viewer, record);
    if (!label) return;
    const signature = `${getLanguage()}\0${isPrivacyModeEnabled()}\0${label}`;
    const labelState = ownedAttributes.get(target)?.get("aria-label");
    const labelIsCurrent = record.committedSignature === signature && target.getAttribute("aria-label") === label && !target.hasAttribute?.("aria-labelledby") && labelState?.owner === OWNERS.statusViewer;
    if (!labelIsCurrent) {
      applyOwnedAttribute(target, "aria-label", label, OWNERS.statusViewer);
      if (target.hasAttribute?.("aria-labelledby")) {
        applyOwnedAttribute(target, "aria-labelledby", null, OWNERS.statusViewer);
      }
      record.committedSignature = signature;
    }
    const active = document.activeElement;
    const focusOutsideViewer = connected(active) && active !== viewer.marker && !viewer.marker.contains?.(active);
    const focusIsLost = !connected(active) || active === document.body || active === document.documentElement || focusOutsideViewer && !hasProtectedExternalFocus();
    if (shell && active === shell || focusIsLost) target.focus({ preventScroll: true });
  }
  function syncStatusAccessibility() {
    if (!isStatusReadingCleanupEnabled()) {
      releaseCurrent();
      return;
    }
    const viewer = getActiveViewer();
    if (!viewer) {
      releaseCurrent();
      return;
    }
    const sender = getSender(viewer);
    const time = findTime(viewer, sender);
    const title = getTitle(viewer);
    const progress = getProgressIdentity(viewer);
    const record = ensureRecord(viewer, sender, time, title, progress);
    if (current !== record || record.generation !== generation) return;
    if (!sender && !time) return;
    if (viewer.videoNode && !record.captionBaselineCaptured) {
      record.captionLengthBeforeExpansion = getCaption(viewer, record).length;
      record.captionBaselineCaptured = true;
    }
    commitLabel(viewer, record);
    if (!viewer.videoNode) {
      if (record.pauseAttempted && !record.pauseControlFound) {
        if (findPauseButton(viewer)) {
          record.pauseAttempted = false;
          record.pauseChecks = 0;
        }
      }
      if (!record.pauseAttempted) {
        const pause = findPauseButton(viewer);
        if (pause) {
          record.pauseControlFound = true;
          record.pauseAttempted = true;
          const focusedReadMore = findReadMoreButton(viewer);
          if (hasProtectedControlFocus(viewer) || isFocusedInside(pause) || isFocusedInside(focusedReadMore)) {
            record.pauseAttempted = false;
            return;
          }
          activateControl(pause);
          scheduleStatusAccessibilitySync();
          return;
        }
        record.pauseChecks += 1;
        if (record.pauseChecks < MAX_PAUSE_CHECKS) {
          scheduleStatusAccessibilitySync();
          return;
        }
        record.pauseAttempted = true;
      }
    }
    if (record.expandAttempted && !record.expandControlFound && viewer.videoNode) {
      const lateBody = getCaption(viewer, record);
      if (!(record.captionLengthBeforeExpansion > 0 && lateBody.length > record.captionLengthBeforeExpansion) && findReadMoreButton(viewer)) {
        record.expandAttempted = false;
        record.expansionChecks = 0;
        record.waitingForExpansion = false;
      }
    }
    if (!record.expandAttempted) {
      const bodyBeforeExpansion = getCaption(viewer, record);
      if (record.captionLengthBeforeExpansion > 0 && bodyBeforeExpansion.length > record.captionLengthBeforeExpansion) {
        record.expandAttempted = true;
        commitLabel(viewer, record);
        return;
      }
      const readMore = findReadMoreButton(viewer);
      if (readMore) {
        record.expandControlFound = true;
        if (hasProtectedControlFocus(viewer) || isFocusedInside(readMore)) return;
        record.captionButton = readMore;
        record.captionHost = readMore.parentElement || viewer.contentButton;
        record.captionLengthBeforeExpansion = bodyBeforeExpansion.length;
        record.captionBaselineCaptured = true;
        record.expandAttempted = true;
        record.waitingForExpansion = true;
        activateControl(readMore);
        scheduleStatusAccessibilitySync();
        return;
      }
      if (viewer.videoNode && record.expansionChecks < MAX_EXPANSION_CHECKS) {
        record.expansionChecks += 1;
        scheduleStatusAccessibilitySync();
        return;
      }
      record.expandAttempted = true;
    }
    if (record.waitingForExpansion) {
      const body = getCaption(viewer, record);
      if (body.length <= record.captionLengthBeforeExpansion && record.expansionChecks < MAX_EXPANSION_CHECKS) {
        record.expansionChecks += 1;
        scheduleStatusAccessibilitySync();
        return;
      }
      record.waitingForExpansion = false;
      if (body.length <= record.captionLengthBeforeExpansion) {
        record.expansionFailed = true;
        commitLabel(viewer, record);
        return;
      }
    }
    if (record.expansionFailed) {
      const body = getCaption(viewer, record);
      if (body.length > record.captionLengthBeforeExpansion) record.expansionFailed = false;
    }
    commitLabel(viewer, record);
  }
  function scheduleStatusAccessibilitySync() {
    if (!isStatusReadingCleanupEnabled()) {
      releaseCurrent();
      return;
    }
    if (scheduled) return;
    scheduled = true;
    const token = ++scheduleToken;
    scheduleFrame(() => {
      if (token !== scheduleToken) return;
      scheduled = false;
      syncStatusAccessibility();
    });
  }
  function refreshStatusAccessibility(options = {}) {
    if (!isStatusReadingCleanupEnabled()) {
      releaseStatusAccessibility();
      return;
    }
    if (options.retryControls && current) {
      if (current.mediaKind !== "video" && !current.pauseControlFound) {
        current.pauseAttempted = false;
        current.pauseChecks = 0;
      }
      if (current.mediaKind === "video" && !current.expandControlFound) {
        current.expandAttempted = false;
        current.expansionChecks = 0;
        current.waitingForExpansion = false;
        current.expansionFailed = false;
        current.captionButton = null;
        current.captionHost = null;
      }
    }
    generation += 1;
    scheduleStatusAccessibilitySync();
  }
  function releaseStatusAccessibility(removedRoot = null) {
    if (removedRoot && current?.contentButton && removedRoot !== current.contentButton && !removedRoot.contains?.(current.contentButton)) return;
    scheduled = false;
    scheduleToken += 1;
    releaseCurrent();
  }

  // src/appearance.js
  var isCleanUiMode = readSetting(STORAGE_KEYS.cleanUi, "false") === "true";
  var isOriginalDarkMode = readSetting(STORAGE_KEYS.originalDark, "false") === "true";
  var cleanUiSyncPending = false;
  function findDesktopAppPromoCloseButton(promo) {
    if (!promo?.querySelectorAll) return null;
    const controls = Array.from(promo.querySelectorAll("svg title")).filter((title) => normalizeText(title.textContent || "") === "ic-close").map((title) => title.closest?.('button, [role="button"]')).filter((control, index, items) => control && items.indexOf(control) === index).filter((control) => {
      const label = control.getAttribute("aria-label") || control.querySelector?.("[aria-label]")?.getAttribute("aria-label");
      return normalizeText(label || "") && !control.disabled && control.getAttribute("aria-disabled") !== "true" && control.isConnected && !control.hidden && !control.inert && control.getAttribute("aria-hidden") !== "true";
    });
    return controls.length === 1 ? controls[0] : null;
  }
  function getSidebarDesktopAppPromo() {
    const candidates = Array.from(document.querySelectorAll?.('[data-testid="wa-square-icon"]') || []).map((icon) => icon.closest?.('[role="button"][tabindex="0"]')).filter((candidate, index, items) => candidate && items.indexOf(candidate) === index).filter((candidate) => {
      const hasTitle = Array.from(candidate.querySelectorAll?.("span") || []).some((span) => getDesktopPromoRegex().test(normalizeText(span.textContent || "")));
      return hasTitle && findDesktopAppPromoCloseButton(candidate);
    });
    return candidates.length === 1 ? candidates[0] : null;
  }
  function toggleStyleSheet(id, cssText, enable) {
    let style = document.getElementById(id);
    if (enable) {
      if (!style) {
        style = document.createElement("style");
        style.id = id;
        style.textContent = cssText;
        document.head.appendChild(style);
      }
    } else if (style) {
      style.remove();
    }
  }
  function getDesktopAppPromo() {
    const sidebarPromo = getSidebarDesktopAppPromo();
    if (sidebarPromo) return sidebarPromo;
    const panel = document.querySelector('section[data-testid="intro-panel"]');
    if (!panel || !panel.children) return null;
    const actionGroup = panel.querySelector(':scope > [data-testid="intro-panel-empty-state-action-tile-group"]');
    if (!actionGroup) return null;
    for (const candidate of Array.from(panel.children)) {
      if (!candidate.querySelector || !candidate.querySelectorAll) continue;
      if (candidate === actionGroup || candidate.nextElementSibling !== actionGroup) continue;
      if (candidate.closest?.(CLEAN_UI_PROTECTED_SELECTOR) || candidate.querySelector(CLEAN_UI_PROTECTED_SELECTOR)) continue;
      const texts = Array.from(candidate.querySelectorAll("span")).map((el) => normalizeText(el.textContent || ""));
      const customTitle = normalizeText(getCustomText("desktop-promo")).toLocaleLowerCase();
      const hasCustomTitle = !!customTitle && texts.some((text) => text.toLocaleLowerCase() === customTitle);
      const hasTitle = texts.some((text) => getDesktopPromoRegex().test(text));
      const hasCopy = hasCustomTitle || texts.some((text) => DESKTOP_APP_PROMO_COPY_RE.test(text));
      const downloadButton = candidate.querySelector('button[type="button"]');
      const isDownloadButton = downloadButton && !downloadButton.disabled && downloadButton.getAttribute("aria-disabled") !== "true";
      const focusableCount = candidate.querySelectorAll(FOCUSABLE_SELECTOR).length;
      if (hasTitle && hasCopy && isDownloadButton && focusableCount === 1) return candidate;
    }
    return null;
  }
  function getDesktopAppPromoCloseButton(promo = getDesktopAppPromo()) {
    return findDesktopAppPromoCloseButton(promo);
  }
  function getRecentSearchesTargets() {
    const side = document.querySelector(SELECTORS.side);
    if (!side) return [];
    const targets = [];
    const searchPattern = getRecentSearchesRegex();
    const clearPattern = getClearAllRegex();
    const testIdContainers = side.querySelectorAll(
      '[data-testid="search-history"], [data-testid="recent-searches"], [data-testid="recent-search-list"], [data-testid*="recent-search"]'
    );
    testIdContainers.forEach((el) => targets.push(el));
    const candidates = Array.from(side.querySelectorAll('button, [role="button"], [role="region"], [role="group"]'));
    candidates.forEach((el) => {
      const ariaLabel = normalizeText(el.getAttribute("aria-label") || "");
      const title = normalizeText(el.getAttribute("title") || "");
      const text = normalizeText(el.textContent || "");
      if (searchPattern.test(ariaLabel) || searchPattern.test(title) || searchPattern.test(text) || clearPattern.test(ariaLabel) || clearPattern.test(title) || clearPattern.test(text)) {
        const container = el.closest('button, [role="button"], [role="region"], [role="group"]');
        if (container && !targets.includes(container)) {
          targets.push(container);
        }
      }
    });
    return targets.filter((el, index, arr) => el && arr.indexOf(el) === index);
  }
  function getCleanUiHiddenTargets() {
    return [
      getDesktopAppPromo(),
      document.querySelector('section[data-testid="intro-panel"] > [data-testid="intro-panel-empty-state-action-tile-group"]'),
      document.querySelector('#side [data-testid="chatlist-e2e-message"]'),
      ...getRecentSearchesTargets()
    ].filter((el, index, targets) => el && targets.indexOf(el) === index);
  }
  function releaseCleanUiMarkers(keep = /* @__PURE__ */ new Set()) {
    for (const el of [...ownedElements]) {
      const state = ownedAttributes.get(el)?.get(CLEAN_UI_HIDDEN_ATTRIBUTE);
      if (!state || state.owner !== OWNERS.cleanUiHidden) continue;
      if (keep.has(el) && el.isConnected) continue;
      releaseOwnedAttribute(el, CLEAN_UI_HIDDEN_ATTRIBUTE, OWNERS.cleanUiHidden);
    }
  }
  function syncCleanUi() {
    const targets = isCleanUiMode ? getCleanUiHiddenTargets() : [];
    const keep = new Set(targets);
    releaseCleanUiMarkers(keep);
    if (!targets.length) return false;
    if (targets.some((target) => target.contains(document.activeElement))) {
      const fallbacks = [
        document.querySelector(SELECTORS.chatSearch),
        getNavButton("navChats"),
        document.querySelector(SELECTORS.chatList)
      ].filter((el) => el && !targets.some((target) => target.contains(el)));
      if (!fallbacks.some(focusItem)) {
        releaseCleanUiMarkers();
        return false;
      }
    }
    targets.forEach((target) => {
      applyOwnedAttribute(target, CLEAN_UI_HIDDEN_ATTRIBUTE, "true", OWNERS.cleanUiHidden);
    });
    return true;
  }
  function scheduleCleanUiSync() {
    if (!isCleanUiMode || cleanUiSyncPending) return;
    cleanUiSyncPending = true;
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    schedule(() => {
      cleanUiSyncPending = false;
      syncCleanUi();
    });
  }
  var CLEAN_UI_CSS = `
  [${CLEAN_UI_HIDDEN_ATTRIBUTE}="true"] {
    display: none !important;
  }

  /* Reveal chat menus on hover or keyboard focus. */
  [data-testid="chat-list"] [role="row"] [data-testid="context-btn"] {
    opacity: 0 !important;
  }
  [data-testid="chat-list"] [role="row"]:hover [data-testid="context-btn"],
  [data-testid="chat-list"] [role="row"]:focus-within [data-testid="context-btn"] {
    opacity: 1 !important;
  }
`;
  var ORIGINAL_DARK_CSS = `
  body.dark, body.dark * {
    --background-default: #111b21 !important;
    --search-container-background: #111b21 !important;
    --drawer-background-deep: #111b21 !important;
    --panel-background-deeper: #111b21 !important;
    --compose-input-background: #202c33 !important;
    --compose-input-border: #66767e !important;
    --conversation-header-border: #222e35 !important;
    --conversation-panel-border: #222e35 !important;
    --dropdown-background: #222e35 !important;
    --intro-background: #202c33 !important;
    --reactions-panel-background-color: #222e35 !important;
    --WDS-background-wash-inset: #202c33 !important;
    --WDS-background-wash-inset-RGB: 32, 44, 51 !important;
    --WDS-background-wash-plain: #111b21 !important;
    --WDS-background-elevated-wash-inset: #202c33 !important;
    --WDS-surface-default: #111b21 !important;
    --WDS-surface-emphasized: #202c33 !important;
    --WDS-surface-elevated-default: #202c33 !important;
    --WDS-surface-elevated-emphasized: #2a3942 !important;
    --WDS-content-deemphasized: #bac5cb !important;
    --WDS-content-action-default: #aebac1 !important;
    --WDS-content-disabled: #617079 !important;
    --WDS-systems-chat-background-wallpaper: #111b21 !important;
    --WDS-systems-chat-surface-composer: #202c33 !important;
    --WDS-systems-chat-surface-tray: #111b21 !important;
    --WDS-systems-bubble-surface-system: #202c33 !important;
    --WDS-systems-bubble-surface-incoming: #202c33 !important;
    --WDS-systems-bubble-surface-incoming-RGB: 32, 44, 51 !important;
    --WDS-systems-bubble-surface-outgoing-RGB: 0, 92, 75 !important;
    --WDS-systems-bubble-surface-outgoing: #005c4b !important;
  }
`;
  function updateStyleSheets() {
    syncCleanUi();
    toggleStyleSheet("wa-plus-clean-ui-styles", CLEAN_UI_CSS, isCleanUiMode);
    toggleStyleSheet("wa-plus-original-dark-styles", ORIGINAL_DARK_CSS, isOriginalDarkMode);
  }
  function isCleanUiEnabled() {
    return isCleanUiMode;
  }
  function isOriginalDarkEnabled() {
    return isOriginalDarkMode;
  }
  function toggleCleanUiMode(announceChange = true) {
    const nextValue = !isCleanUiMode;
    if (!writeSetting(STORAGE_KEYS.cleanUi, nextValue ? "true" : "false")) {
      if (announceChange) announce(t("saveError"));
      return false;
    }
    isCleanUiMode = nextValue;
    const controlsHidden = syncCleanUi();
    toggleStyleSheet("wa-plus-clean-ui-styles", CLEAN_UI_CSS, isCleanUiMode);
    if (announceChange) {
      announce(isCleanUiMode ? t(controlsHidden ? "cleanUiOnHidden" : "cleanUiOn") : t("cleanUiOff"));
    }
    return true;
  }
  function toggleOriginalDarkMode(announceChange = true) {
    const nextValue = !isOriginalDarkMode;
    if (!writeSetting(STORAGE_KEYS.originalDark, nextValue ? "true" : "false")) {
      if (announceChange) announce(t("saveError"));
      return false;
    }
    isOriginalDarkMode = nextValue;
    toggleStyleSheet("wa-plus-original-dark-styles", ORIGINAL_DARK_CSS, isOriginalDarkMode);
    if (announceChange) announce(isOriginalDarkMode ? t("darkOn") : t("darkOff"));
    return true;
  }

  // src/navigation.js
  var lastStatusFull = "";
  var lastTypingActivity = "";
  var lastTypingChatTitle = "";
  var statusInterval = null;
  var lastTPressTime = 0;
  var unreadTarget = null;
  var consumedUnreadChatTitle = "";
  var isStatusTracking = readSetting(STORAGE_KEYS.chatActivity, "false") === "true";
  var chatPulseChatTitle = "";
  var chatPulseTailId = "";
  var chatPulseSeenIds = /* @__PURE__ */ new Set();
  var chatPulseStatuses = /* @__PURE__ */ new Map();
  var chatPulsePendingIds = /* @__PURE__ */ new Set();
  var chatPulseSyncTimer = null;
  var passiveAnnouncementTimer = null;
  var passiveAnnouncements = [];
  var passiveAnnouncementGeneration = 0;
  var pendingFocusRequest = 0;
  var DELIVERY_STATUS_BY_KEY = Object.freeze({
    deliveryPending: "Pending",
    deliverySent: "Sent",
    deliveryDelivered: "Delivered",
    deliveryRead: "Read"
  });
  var SHORTCUT_REMAPS = Object.freeze({
    KeyM: ["voice-recording", "R", "KeyR"],
    ArrowUp: ["previous-chat", "{", "BracketLeft"],
    ArrowDown: ["next-chat", "}", "BracketRight"]
  });
  function cancelPendingFocusRequests() {
    pendingFocusRequest++;
  }
  function beginFocusRequest() {
    return ++pendingFocusRequest;
  }
  function isFocusRequestCurrent(request) {
    const settingsMenu = document.getElementById("wa-plus-settings-menu");
    return request === pendingFocusRequest && (!settingsMenu || settingsMenu.hidden);
  }
  function getCanonicalDeliveryStatus(value) {
    return DELIVERY_STATUS_BY_KEY[getDeliveryStatusKey(value)] || "";
  }
  function getChatPulseStatus(message) {
    if (!message || !message.querySelector) return "";
    const named = Array.from(message.querySelectorAll?.(
      '[data-testid="msg-meta"] [aria-label], [data-testid="msg-meta"] [title]'
    ) || []);
    for (const element of named) {
      const status = cleanString(
        element.getAttribute("aria-label") || element.getAttribute("title") || "",
        false
      );
      const canonical = getCanonicalDeliveryStatus(status);
      if (canonical) return canonical;
      if (getDeliveryStatusRegex().test(status)) return status;
    }
    const icon = message.querySelector(
      '[data-testid="msg-meta"] [data-icon="msg-dblcheck-ack"], [data-testid="msg-meta"] [data-icon="msg-dblcheck"], [data-testid="msg-meta"] [data-icon="msg-check"], [data-testid="msg-meta"] [data-icon="msg-time"]'
    );
    const iconStatus = {
      "msg-dblcheck-ack": "Read",
      "msg-dblcheck": "Delivered",
      "msg-check": "Sent",
      "msg-time": "Pending"
    }[icon?.getAttribute("data-icon")];
    if (iconStatus) return iconStatus;
    return "";
  }
  function prepareChatPulseSummary(summary, message, messageId) {
    const safeSummary = isPrivacyModeEnabled() ? maskPhoneNumbers(cleanString(summary, "message", message)) : cleanString(summary, false, message);
    return appendSenderDevice(translateDeliveryStatusInText(safeSummary), messageId);
  }
  function getChatPulseSummary(message, messageId = "") {
    if (!message || !message.querySelector) return "";
    const metaSender = getDirectMetaAISender(message);
    const isMetaMessage = !!metaSender;
    const body = isMetaMessage ? message.querySelector('[data-testid="msg-container"] .copyable-text.selectable-text') : message.querySelector(MESSAGE_TEXT_CONTENT_SELECTOR);
    const bodyText = cleanString(body?.textContent || "", false);
    const mediaContent = message.querySelector(MESSAGE_MEDIA_CONTENT_SELECTOR);
    const metadata = message.querySelector('[data-testid="msg-meta"]');
    if (isMetaMessage ? !bodyText || !metadata : !bodyText && !mediaContent) return "";
    const nativeLabel = cleanString(message.getAttribute("aria-label") || "", false);
    if (!isMetaMessage && nativeLabel) {
      return prepareChatPulseSummary(
        nativeLabel.replace(getMessageContextInstructionRegex(), "").trim(),
        message,
        messageId
      );
    }
    const parts = [];
    const sender = metaSender || message.querySelector('span[aria-label$=":"]');
    [sender?.getAttribute("aria-label"), bodyText, metadata?.textContent, getChatPulseStatus(message)].forEach((part) => {
      const value = cleanString(part || "", false);
      if (value && !parts.includes(value)) parts.push(value);
    });
    return prepareChatPulseSummary(parts.join(" "), message, messageId);
  }
  function getChatPulseEntries() {
    const main = document.querySelector(SELECTORS.main);
    if (!main) return [];
    const container = main.querySelector(SELECTORS.conversationMessages);
    if (!container) return [];
    const entries = /* @__PURE__ */ new Map();
    Array.from(container.querySelectorAll(
      '[data-testid^="conv-msg-"][data-id], .focusable-list-item[data-id], div[role="row"][data-id]'
    )).forEach((wrapper) => {
      const message = wrapper.matches?.(".focusable-list-item") ? wrapper : wrapper.querySelector(".focusable-list-item");
      const dataId = wrapper.getAttribute("data-id") || message?.getAttribute?.("data-id") || message?.closest?.("[data-id]")?.getAttribute("data-id");
      if (!message || !dataId || entries.has(dataId)) return;
      entries.set(dataId, {
        id: dataId,
        summary: getChatPulseSummary(message, dataId),
        status: getChatPulseStatus(message)
      });
    });
    return Array.from(entries.values());
  }
  function setChatPulseBaseline(chatTitle, entries) {
    chatPulseChatTitle = chatTitle;
    chatPulseTailId = entries.length ? entries[entries.length - 1].id : "";
    chatPulseSeenIds = new Set(entries.map((entry) => entry.id));
    chatPulseStatuses = new Map(entries.map((entry) => [entry.id, entry.status]));
    chatPulsePendingIds.clear();
  }
  function captureChatPulseBaseline() {
    setChatPulseBaseline(getCurrentChatTitle(), getChatPulseEntries());
  }
  function schedulePassiveAnnouncements() {
    if (passiveAnnouncementTimer !== null || !passiveAnnouncements.length) return;
    const generation2 = passiveAnnouncementGeneration;
    const delay = Math.max(25, getUserAnnouncementUntil() - Date.now() + 25);
    passiveAnnouncementTimer = setTimeout(() => {
      passiveAnnouncementTimer = null;
      if (generation2 !== passiveAnnouncementGeneration) return;
      if (Date.now() < getUserAnnouncementUntil()) {
        schedulePassiveAnnouncements();
        return;
      }
      const ready = passiveAnnouncements.filter((entry) => entry.generation === generation2 && (entry.source === "pulse" && isAutomaticReadingEnabled() || entry.source === "activity" && isStatusTracking));
      passiveAnnouncements = [];
      if (generation2 !== passiveAnnouncementGeneration) return;
      announcePassiveMessages(ready.map((entry) => entry.text), generation2);
    }, delay);
  }
  function queuePassiveAnnouncements(source, announcements) {
    if (!announcements.length) return;
    if (source === "activity") {
      passiveAnnouncements = passiveAnnouncements.filter((entry) => entry.source !== "activity");
    }
    passiveAnnouncements.push(...announcements.map((text) => ({
      source,
      text,
      generation: passiveAnnouncementGeneration
    })));
    if (passiveAnnouncements.length > 50) {
      passiveAnnouncements = passiveAnnouncements.slice(-50);
    }
    schedulePassiveAnnouncements();
  }
  function discardPassiveAnnouncements(source) {
    passiveAnnouncements = passiveAnnouncements.filter((entry) => entry.source !== source);
    if (passiveAnnouncementTimer !== null) clearTimeout(passiveAnnouncementTimer);
    passiveAnnouncementTimer = null;
    schedulePassiveAnnouncements();
  }
  function discardAllPassiveAnnouncements() {
    passiveAnnouncements = [];
    if (passiveAnnouncementTimer !== null) clearTimeout(passiveAnnouncementTimer);
    passiveAnnouncementTimer = null;
    passiveAnnouncementGeneration++;
    invalidatePassiveAnnouncements();
  }
  function reconcileChatPulseEntries(chatTitle, entries) {
    if (chatTitle !== chatPulseChatTitle) {
      passiveAnnouncementGeneration++;
      invalidatePassiveAnnouncements();
      discardPassiveAnnouncements("pulse");
      setChatPulseBaseline(chatTitle, entries);
      return [];
    }
    if (!chatTitle) return [];
    const tailIndex = chatPulseTailId ? entries.findIndex((entry) => entry.id === chatPulseTailId) : -1;
    const canDetectAppend = !chatPulseTailId && chatPulseSeenIds.size === 0 || tailIndex >= 0;
    const appendedCandidates = canDetectAppend ? entries.slice(tailIndex + 1).filter((entry) => !chatPulseSeenIds.has(entry.id)) : [];
    const pendingCandidates = entries.filter((entry) => chatPulsePendingIds.has(entry.id) && !chatPulseSeenIds.has(entry.id));
    const candidateIds = new Set(
      [...pendingCandidates, ...appendedCandidates].map((entry) => entry.id)
    );
    const candidates = entries.filter((entry) => candidateIds.has(entry.id));
    const newEntries = [];
    for (const entry of candidates) {
      if (!entry.summary) break;
      newEntries.push(entry);
    }
    candidates.forEach((entry) => {
      if (newEntries.includes(entry)) chatPulsePendingIds.delete(entry.id);
      else chatPulsePendingIds.add(entry.id);
    });
    const newIds = new Set(newEntries.map((entry) => entry.id));
    const announcements = newEntries.map((entry) => entry.summary).filter(Boolean);
    const receiptCounts = /* @__PURE__ */ new Map();
    entries.forEach((entry) => {
      if (chatPulsePendingIds.has(entry.id)) return;
      const hadStatus = chatPulseStatuses.has(entry.id);
      const previousStatus = chatPulseStatuses.get(entry.id) || "";
      const previousRank = getDeliveryStatusRank(previousStatus);
      const nextRank = getDeliveryStatusRank(entry.status);
      const customStatusChanged = nextRank < 0 && previousRank < 0 && entry.status && entry.status !== previousStatus;
      if (!newIds.has(entry.id) && hadStatus && (nextRank > previousRank || customStatusChanged)) {
        receiptCounts.set(entry.status, (receiptCounts.get(entry.status) || 0) + 1);
      }
      chatPulseSeenIds.add(entry.id);
      if (!hadStatus || nextRank >= previousRank) chatPulseStatuses.set(entry.id, entry.status);
    });
    if (newEntries.length) chatPulseTailId = newEntries[newEntries.length - 1].id;
    receiptCounts.forEach((count, status) => {
      const translatedStatus = translateDeliveryStatus(status);
      announcements.push(count === 1 ? t("messageStatusSingle", { status: translatedStatus }) : t("messageStatusPlural", { count, status: translatedStatus }));
    });
    return announcements;
  }
  function syncChatPulse() {
    if (!isAutomaticReadingEnabled()) return;
    queuePassiveAnnouncements("pulse", reconcileChatPulseEntries(
      getCurrentChatTitle(),
      getChatPulseEntries()
    ));
  }
  function scheduleChatPulseSync() {
    if (!isAutomaticReadingEnabled()) return;
    if (chatPulseSyncTimer !== null) clearTimeout(chatPulseSyncTimer);
    chatPulseSyncTimer = setTimeout(() => {
      chatPulseSyncTimer = null;
      syncChatPulse();
    }, 300);
  }
  function toggleChatPulse(announceChange = true) {
    const enabled = !isAutomaticReadingEnabled();
    if (!setAutomaticReading(enabled)) {
      if (announceChange) announce(t("saveError"));
      return false;
    }
    if (enabled) captureChatPulseBaseline();
    else {
      if (chatPulseSyncTimer !== null) clearTimeout(chatPulseSyncTimer);
      chatPulseSyncTimer = null;
      chatPulseChatTitle = "";
      chatPulseTailId = "";
      chatPulseSeenIds.clear();
      chatPulseStatuses.clear();
      chatPulsePendingIds.clear();
      discardPassiveAnnouncements("pulse");
    }
    if (announceChange) announce(t(enabled ? "automaticReadingOn" : "automaticReadingOff"));
    return true;
  }
  function refreshPassiveBaselines() {
    if (isAutomaticReadingEnabled()) captureChatPulseBaseline();
    lastTypingActivity = getSelectedChatTypingActivity();
    lastTypingChatTitle = getChatRowTitle(getSelectedChatRow(getChatListRows()));
    const infoBtn = getHeaderInfoButton();
    lastStatusFull = getHeaderText(infoBtn);
  }
  function resetPassiveAnnouncementContext() {
    discardAllPassiveAnnouncements();
    refreshPassiveBaselines();
  }
  function togglePrivacyWithQueueReset(announceChange = true) {
    if (!togglePrivacyMode(announce, false)) {
      if (announceChange) announce(t("saveError"));
      return false;
    }
    const enabled = isPrivacyModeEnabled();
    refreshStatusAccessibility();
    resetPassiveAnnouncementContext();
    clearMessageLog();
    clearStatusRegion();
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    schedule(() => {
      if (isPrivacyModeEnabled() === enabled) refreshPassiveBaselines();
    });
    if (announceChange) announce(t(enabled ? "privacyOn" : "privacyOff"));
    return true;
  }
  function captureNextRowId(dividerEl) {
    const messageContainer = dividerEl.closest(SELECTORS.conversationMessages);
    if (!messageContainer) return;
    const row = getNextMessageRow(dividerEl, messageContainer);
    const message = row && row.querySelector("[data-id]");
    const chatTitle = getCurrentChatTitle();
    if (!message || !chatTitle || chatTitle === consumedUnreadChatTitle) return;
    unreadTarget = {
      chatTitle,
      messageId: message.getAttribute("data-id"),
      scrollTop: messageContainer.scrollTop,
      dividerEl
    };
  }
  function isShortUnreadText(text) {
    const normalized = (text || "").replace(/\s+/g, " ").trim();
    return normalized.length > 0 && normalized.length < 60 && getUnreadDividerRegex().test(normalized);
  }
  function maybeCaptureUnreadDivider(node) {
    if (!node.closest || !node.closest(SELECTORS.conversationMessages)) return;
    if (getCurrentChatTitle() === consumedUnreadChatTitle) return;
    const candidates = node.matches && node.matches("div, span") ? [node] : [];
    if (node.querySelectorAll) candidates.push(...node.querySelectorAll("div, span"));
    for (let i = 0; i < candidates.length; i++) {
      const el = candidates[i];
      if (el.childElementCount > 0) continue;
      if (el.closest('.focusable-list-item, [aria-hidden="true"]')) continue;
      if (isShortUnreadText(el.textContent || "")) {
        captureNextRowId(el);
        return;
      }
    }
  }
  function reconcileUnreadTarget() {
    const currentChatTitle = getCurrentChatTitle();
    if (consumedUnreadChatTitle && consumedUnreadChatTitle !== currentChatTitle) {
      consumedUnreadChatTitle = "";
    }
    if (!unreadTarget) return;
    const dividerRemoved = unreadTarget.dividerEl && (!unreadTarget.dividerEl.isConnected || !isShortUnreadText(unreadTarget.dividerEl.textContent || ""));
    if (unreadTarget.chatTitle !== currentChatTitle || dividerRemoved) unreadTarget = null;
  }
  function consumeUnreadTarget() {
    const chatTitle = getCurrentChatTitle();
    unreadTarget = null;
    if (chatTitle) consumedUnreadChatTitle = chatTitle;
    if (!isAutomaticReadingEnabled()) return;
    discardPassiveAnnouncements("pulse");
    setChatPulseBaseline(chatTitle, getChatPulseEntries());
  }
  function findMessageById(container, messageId) {
    if (!container || !messageId) return null;
    return container.querySelector(`[data-id="${CSS.escape(messageId)}"]`);
  }
  function getAdjacentMessageRow(node, preferLast = false) {
    if (!node || node.nodeType !== 1) return null;
    const rows = [];
    if (node.matches?.('div[role="row"]')) rows.push(node);
    rows.push(...Array.from(node.querySelectorAll?.('div[role="row"]') || []));
    return preferLast ? rows.at(-1) || null : rows[0] || null;
  }
  function recoverFocusAfterRemoval(rootEl, nextSibling = null, previousSibling = null) {
    const remembered = getRememberedFocus();
    const lostChat = remembered.lastFocusedChatRowNode && (rootEl === remembered.lastFocusedChatRowNode || rootEl.contains?.(remembered.lastFocusedChatRowNode));
    const lostMessage = remembered.lastFocusedMessageNode && (rootEl === remembered.lastFocusedMessageNode || rootEl.contains?.(remembered.lastFocusedMessageNode));
    if (!lostChat && !lostMessage) return;
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    schedule(() => {
      if (getActiveModal() || document.activeElement !== document.body) return;
      if (lostChat) {
        clearRememberedChatRow();
        focusChatListShortcut(document.body);
      } else {
        clearRememberedMessageRow();
        const messageContainer = document.querySelector(SELECTORS.conversationMessages);
        const replacement = findMessageById(messageContainer, remembered.lastFocusedMessageId);
        const replacementRow = replacement && (replacement.closest('div[role="row"]') || replacement);
        const adjacentRows = [
          getAdjacentMessageRow(nextSibling),
          getAdjacentMessageRow(previousSibling, true)
        ];
        const row = replacementRow || adjacentRows.find(
          (candidate) => candidate?.isConnected && messageContainer?.contains(candidate)
        ) || getMessageRows().at(-1);
        if (!focusItem(getBestInnerFocusElement(row))) focusItem(messageContainer);
      }
    });
  }
  function activateNav(selectorKey, name, focusSelector = null) {
    const selector = getNavSelector(selectorKey);
    const btn = document.querySelector(selector);
    if (!btn) {
      announce(t("buttonNotFound", { name }));
      return;
    }
    const request = beginFocusRequest();
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 50));
    const isDestinationOpen = (destination) => {
      if (selectorKey !== "navMetaAI") return hasActiveState(destination);
      const input = document.querySelector(SELECTORS.messageInput);
      if (!input || input.getAttribute("contenteditable") !== "true" || input.getAttribute("role") !== "textbox") return false;
      const labelledBy = (input.getAttribute("aria-labelledby") || "").split(/\s+/).map((id) => document.getElementById(id)?.textContent || "").filter(Boolean).join(" ");
      const inputName = labelledBy || [
        input.getAttribute("aria-label"),
        input.getAttribute("title"),
        input.getAttribute("placeholder")
      ].filter(Boolean).join(" ");
      return getMetaAIRegex().test(inputName);
    };
    const confirmDestination = (attempt = 1) => {
      if (!isFocusRequestCurrent(request) || getActiveModal()) return;
      const destination = document.querySelector(selector);
      if (!destination || !isDestinationOpen(destination)) {
        if (attempt < 30) schedule(() => confirmDestination(attempt + 1));
        else announce(t("didNotOpen", { name }));
        return;
      }
      const focusTarget = focusSelector ? document.querySelector(focusSelector) : destination;
      if (!focusTarget) {
        if (attempt < 30) schedule(() => confirmDestination(attempt + 1));
        else announce(t("listEmpty", { name }));
        return;
      }
      if (!focusItem(focusTarget)) {
        announce(t("couldNotFocus", { name }));
        return;
      }
      scheduleRoleFix(getRoleFixRoot(focusTarget));
    };
    if (isDestinationOpen(btn) || hasActiveState(btn)) {
      schedule(() => confirmDestination());
      return;
    }
    btn.click();
    schedule(() => confirmDestination());
  }
  function isParticipantList(text) {
    return splitParticipantList(text).length >= 4;
  }
  function truncateList(text) {
    if (isParticipantList(text)) {
      const parts = splitParticipantList(text);
      if (parts.length > 3) {
        return t("andOthers", {
          names: parts.slice(0, 3).map(isolateBidiText).join(", "),
          count: parts.length - 3
        });
      }
    }
    return text;
  }
  function stopStatusTracking() {
    if (statusInterval) clearInterval(statusInterval);
    statusInterval = null;
    lastStatusFull = "";
    lastTypingActivity = "";
    lastTypingChatTitle = "";
  }
  function localizeSelectedChatActivity(text, title, regex, genericRegex, translate, messageKey) {
    const textAfterTitle = title && text.startsWith(title) ? text.slice(title.length).trim() : "";
    const isGenericActivity = genericRegex.test(text);
    const isNamedGenericActivity = !!textAfterTitle && genericRegex.test(textAfterTitle);
    if (!regex.test(text) && !isNamedGenericActivity) return "";
    if (!isGenericActivity && !isNamedGenericActivity) return translate(text);
    return title ? t(messageKey, {
      name: isolateBidiText(title),
      verb: "is",
      suffix: getTypingSuffix(text)
    }) : "";
  }
  function getSelectedChatTypingActivity(rows = getChatListRows()) {
    const row = getSelectedChatRow(rows);
    const secondary = row?.querySelector('[data-testid="cell-frame-secondary"]');
    const indicators = Array.from(secondary?.querySelectorAll?.("[title], [aria-label]") || []);
    if (!indicators.length) {
      const first = secondary?.querySelector("[title], [aria-label]");
      if (first) indicators.push(first);
    }
    const values = indicators.map(
      (indicator) => indicator.getAttribute("aria-label") || indicator.getAttribute("title") || indicator.textContent
    );
    if (!values.some(Boolean)) values.push(secondary?.textContent);
    const activities = [];
    const rawActivities = /* @__PURE__ */ new Set();
    const title = getChatRowTitle(row);
    for (const value of values) {
      const text = cleanString(value || "", false).replace(getUnknownContactRegex(), "").replace(/^~\s*/, "");
      let type = "typing";
      let activity = localizeSelectedChatActivity(
        text,
        title,
        getTypingRegex(),
        getGenericTypingRegex(),
        translateTypingActivity,
        "typingActivity"
      );
      if (!activity) {
        type = "recording";
        activity = localizeSelectedChatActivity(
          text,
          title,
          getRecordingAudioRegex(),
          getGenericRecordingAudioRegex(),
          translateRecordingAudioActivity,
          "recordingAudioActivity"
        );
      }
      const canonical = `${type}\0${activity}`;
      if (!activity || rawActivities.has(canonical)) continue;
      rawActivities.add(canonical);
      const safeActivity = cleanString(activity, isPrivacyModeEnabled() ? "identity" : false);
      if (!safeActivity) continue;
      const existing = activities.find((item) => item.type === type && item.text === safeActivity);
      if (existing) {
        existing.count++;
      } else {
        activities.push({ type, text: safeActivity, count: 1, suffix: getTypingSuffix(text) });
      }
    }
    return activities.map(
      (item) => item.count > 1 ? t(item.type === "recording" ? "recordingAudioActivityCount" : "typingActivityCount", {
        count: item.count,
        suffix: item.suffix
      }) : item.text
    ).join(", ");
  }
  function syncSelectedChatTypingActivity(rows = getChatListRows()) {
    const row = getSelectedChatRow(rows);
    const chatTitle = getChatRowTitle(row);
    if (chatTitle !== lastTypingChatTitle) {
      passiveAnnouncementGeneration++;
      invalidatePassiveAnnouncements();
      discardPassiveAnnouncements("activity");
      lastTypingActivity = "";
      lastTypingChatTitle = chatTitle;
    }
    const typingActivity = getSelectedChatTypingActivity(rows);
    const rowFocused = row && row.contains(document.activeElement);
    if (!typingActivity || rowFocused) {
      if (lastTypingActivity || rowFocused) discardPassiveAnnouncements("activity");
    } else if (typingActivity !== lastTypingActivity) {
      queuePassiveAnnouncements("activity", [typingActivity]);
    }
    lastTypingActivity = typingActivity;
    return typingActivity;
  }
  function startStatusTracking() {
    if (statusInterval) clearInterval(statusInterval);
    const infoBtn = getHeaderInfoButton();
    lastStatusFull = infoBtn ? getHeaderText(infoBtn) : "";
    const rows = getChatListRows();
    lastTypingChatTitle = getChatRowTitle(getSelectedChatRow(rows));
    lastTypingActivity = getSelectedChatTypingActivity(rows);
    statusInterval = setInterval(() => {
      if (!isStatusTracking) return;
      const currentInfoBtn = getHeaderInfoButton();
      const fullText = currentInfoBtn ? getHeaderText(currentInfoBtn) : "";
      const lines = fullText.split("\n").map((l) => l.trim()).filter(Boolean);
      const prevLines = lastStatusFull.split("\n").map((l) => l.trim()).filter(Boolean);
      if (prevLines.length > 0 && lines.length > 0 && lines[0] !== prevLines[0]) {
        passiveAnnouncementGeneration++;
        invalidatePassiveAnnouncements();
        discardPassiveAnnouncements("activity");
      }
      const typingActivity = syncSelectedChatTypingActivity();
      if (!currentInfoBtn || !fullText) return;
      if (fullText !== lastStatusFull) {
        if (prevLines.length > 0 && lines[0] === prevLines[0]) {
          const status = lines.slice(1).join(" ").trim();
          const prevStatus = prevLines.slice(1).join(" ").trim();
          if (!typingActivity && status && status !== prevStatus) {
            const focused = document.activeElement;
            const isHeaderFocused = focused === currentInfoBtn || currentInfoBtn.contains(focused);
            if (!isParticipantList(status) && !isHeaderFocused) {
              const activity = translateActivityStatus(status);
              queuePassiveAnnouncements("activity", [
                isPrivacyModeEnabled() ? maskPhoneNumbers(cleanString(activity, "identity")) : activity
              ]);
            }
          }
        }
        lastStatusFull = fullText;
      }
    }, 1500);
  }
  function toggleStatusTracking(announceChange = true) {
    const enabled = !isStatusTracking;
    if (!writeSetting(STORAGE_KEYS.chatActivity, String(enabled))) {
      if (announceChange) announce(t("saveError"));
      return false;
    }
    isStatusTracking = enabled;
    if (enabled) startStatusTracking();
    else {
      stopStatusTracking();
      discardPassiveAnnouncements("activity");
    }
    if (announceChange) announce(t(enabled ? "chatActivityOn" : "chatActivityOff"));
    return true;
  }
  function isChatActivityEnabled() {
    return isStatusTracking;
  }
  function focusChatListShortcut(origin = document.activeElement) {
    const request = beginFocusRequest();
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    const tryFocus = (attempt) => {
      if (!isFocusRequestCurrent(request) || getActiveModal()) return;
      const rows = getChatListRows();
      const mainActive = isChatMainActive();
      const fromChatSearch = !!(origin && origin.closest && origin.closest(SELECTORS.chatSearch));
      let target = fromChatSearch ? null : getPreferredChatRow(rows, origin);
      if (!target && (!mainActive || fromChatSearch)) {
        const scroller = document.querySelector(SELECTORS.chatListScroller);
        if (scroller && scroller.scrollTop > 0) {
          scroller.scrollTop = 0;
          if (attempt < SHORTCUT_RENDER_RETRIES) {
            schedule(() => tryFocus(attempt + 1));
            return;
          }
        }
        const firstRow = rows[0] || null;
        if (firstRow && !isNearChatListTop(firstRow) && attempt < SHORTCUT_RENDER_RETRIES) {
          schedule(() => tryFocus(attempt + 1));
          return;
        }
        target = firstRow && isNearChatListTop(firstRow) ? firstRow : null;
      }
      const retryOrAnnounce = () => {
        if (attempt < SHORTCUT_RENDER_RETRIES) {
          schedule(() => tryFocus(attempt + 1));
        } else {
          const chatList = document.querySelector(SELECTORS.chatListInSide);
          if (chatList) focusItem(chatList);
          announce(t(rows.length === 0 ? "chatListEmpty" : "chatNotReady"));
        }
      };
      if (target && applyChatRowNativeMask(target) && focusChatRow(target, retryOrAnnounce, () => isFocusRequestCurrent(request))) return;
      retryOrAnnounce();
    };
    tryFocus(1);
  }
  function focusLastMessageShortcut() {
    const request = beginFocusRequest();
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    let clickedScrollToBottom = false;
    const tryFocus = (attempt) => {
      if (!isFocusRequestCurrent(request) || getActiveModal()) return;
      const main = document.querySelector(SELECTORS.main);
      if (!isChatMainActive(main)) {
        announce(t("noMessages"));
        return;
      }
      const scrollToBottomButton = !clickedScrollToBottom && main.querySelector(getScrollToBottomSelector());
      if (isRenderedElement(scrollToBottomButton) && !scrollToBottomButton.disabled && scrollToBottomButton.getAttribute("aria-disabled") !== "true") {
        clickedScrollToBottom = true;
        scrollToBottomButton.click();
        if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryFocus(attempt + 1));
        else announce(t("messageNotReady"));
        return;
      }
      const messageContainer = main.querySelector(SELECTORS.conversationMessages) || main;
      const hasMoreBelow = messageContainer.scrollHeight > messageContainer.clientHeight && messageContainer.scrollTop + messageContainer.clientHeight < messageContainer.scrollHeight - 1;
      if (hasMoreBelow) {
        messageContainer.scrollTop = messageContainer.scrollHeight;
        if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryFocus(attempt + 1));
        else announce(t("messageNotReady"));
        return;
      }
      const rows = getMessageRows();
      const row = rows[rows.length - 1];
      if (!row || !focusItem(getBestInnerFocusElement(row))) {
        if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryFocus(attempt + 1));
        else announce(t(rows.length === 0 ? "noMessages" : "messageNotReady"));
        return;
      }
      row.scrollIntoView({ block: "end" });
    };
    tryFocus(1);
  }
  function findUnreadMessageTarget(messageContainer) {
    reconcileUnreadTarget();
    if (consumedUnreadChatTitle && consumedUnreadChatTitle === getCurrentChatTitle()) return null;
    if (unreadTarget) {
      if (!unreadTarget.chatTitle || unreadTarget.chatTitle !== getCurrentChatTitle()) {
        unreadTarget = null;
      } else {
        const msg = findMessageById(messageContainer, unreadTarget.messageId);
        return msg && msg.isConnected ? msg.closest('div[role="row"]') || msg : null;
      }
    }
    const rows = Array.from(messageContainer.querySelectorAll('div[role="row"]'));
    for (const row of rows) {
      if (row.closest('[aria-hidden="true"]') || row.querySelector(".focusable-list-item")) continue;
      if (!isShortUnreadText(row.textContent || "")) continue;
      const target = getNextMessageRow(row, messageContainer);
      if (target) return target;
    }
    const candidates = Array.from(messageContainer.querySelectorAll("div, span"));
    for (const el of candidates) {
      if (el.childElementCount > 0) continue;
      if (el.closest('.focusable-list-item, [aria-hidden="true"]')) continue;
      if (isShortUnreadText(el.textContent || "")) {
        const target = getNextMessageRow(el, messageContainer);
        if (target) return target;
      }
    }
    return null;
  }
  function jumpToUnreadShortcut() {
    const request = beginFocusRequest();
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    const tryJump = (attempt) => {
      if (!isFocusRequestCurrent(request) || getActiveModal()) return;
      const side = document.querySelector(SELECTORS.side);
      if (side && side.contains(document.activeElement)) {
        announce(t("unreadHistoryOnly"));
        return;
      }
      const main = document.querySelector(SELECTORS.main);
      if (!isChatMainActive(main)) {
        announce(t("noOpenChat"));
        return;
      }
      const messageContainer = main.querySelector(SELECTORS.conversationMessages) || main;
      const target = findUnreadMessageTarget(messageContainer);
      if (!target && unreadTarget && attempt < SHORTCUT_RENDER_RETRIES) {
        messageContainer.scrollTop = unreadTarget.scrollTop;
        schedule(() => tryJump(attempt + 1));
        return;
      }
      if (!target) {
        announce(t("unreadNotFound"));
        return;
      }
      if (!focusItem(getBestInnerFocusElement(target))) {
        if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryJump(attempt + 1));
        else announce(t("unreadNotReady"));
        return;
      }
      target.scrollIntoView({ block: "center" });
      consumeUnreadTarget();
    };
    tryJump(1);
  }
  function getMediaPlayerCloseButton() {
    return document.querySelector(SELECTORS.videoPlayerClose) || document.querySelector(SELECTORS.audioPlayerClose);
  }
  function activateMediaPlayerClose(closeButton) {
    if (!closeButton) {
      announce(t("mediaNotOpen"));
      return false;
    }
    closeButton.click();
    announce(t("mediaClosed"));
    return true;
  }
  function closeMediaPlayerShortcut(origin = document.activeElement) {
    const mediaCloseButton = getMediaPlayerCloseButton();
    if (mediaCloseButton && isRenderedElement(mediaCloseButton)) {
      return activateMediaPlayerClose(mediaCloseButton);
    }
    const promo = getDesktopAppPromo();
    const promoCloseButton = getDesktopAppPromoCloseButton(promo);
    if (!promoCloseButton || !isRenderedElement(promoCloseButton)) {
      return activateMediaPlayerClose(null);
    }
    const recoverFocus = promo.contains(origin) || promo.contains(document.activeElement);
    promoCloseButton.click();
    if (recoverFocus) {
      const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
      schedule(() => {
        const active = document.activeElement;
        if (active && active !== document.body && active.isConnected) return;
        [getNavButton("navChats"), document.querySelector(SELECTORS.chatList)].some(focusItem);
      });
    }
    announce(t("desktopPromoClosed"));
    return true;
  }
  function focusMessageInputShortcut() {
    const request = beginFocusRequest();
    const input = document.querySelector(SELECTORS.messageInput);
    if (input && (document.activeElement === input || input.contains(document.activeElement))) {
      const main = document.querySelector(SELECTORS.main);
      const messageContainer = main && (main.querySelector(SELECTORS.conversationMessages) || main);
      const rememberedState = getRememberedFocus();
      const remembered = rememberedState.lastFocusedMessageNode?.isConnected && main?.contains(rememberedState.lastFocusedMessageNode) ? rememberedState.lastFocusedMessageNode : findMessageById(messageContainer, rememberedState.lastFocusedMessageId);
      const row = remembered && (remembered.closest('div[role="row"]') || remembered);
      if (focusItem(getBestInnerFocusElement(row))) {
        row.scrollIntoView({ block: "nearest" });
      } else {
        focusLastMessageShortcut();
      }
      return;
    }
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 0));
    const tryFocus = (attempt) => {
      if (!isFocusRequestCurrent(request) || getActiveModal()) return;
      const currentInput = document.querySelector(SELECTORS.messageInput);
      if (currentInput && focusItem(currentInput)) return;
      if (attempt < SHORTCUT_RENDER_RETRIES && isChatMainActive()) {
        schedule(() => tryFocus(attempt + 1));
      } else {
        announce(t(currentInput ? "messageBoxNotReady" : "messageBoxNotOpen"));
      }
    };
    tryFocus(1);
  }
  function announceChatHeaderShortcut() {
    const main = document.querySelector(SELECTORS.main);
    if (!isChatMainActive(main)) {
      announce(t("noOpenChat"));
      return;
    }
    const headerBtn = getHeaderInfoButton();
    if (!headerBtn) {
      announce(t("titleNotFound"));
      return;
    }
    const headerLines = getHeaderText(headerBtn).split("\n").map((line) => line.trim()).filter(Boolean);
    const headerText = [
      headerLines[0],
      headerLines.length > 1 ? truncateList(headerLines.slice(1).join(" ")) : ""
    ].filter(Boolean).join(". ");
    const safeTitle = isPrivacyModeEnabled() ? maskPhoneNumbers(cleanString(headerText, "identity", headerBtn)) : headerText;
    announce(safeTitle || t("noTitle"));
  }
  function handleAltTShortcut() {
    const now = Date.now();
    if (lastTPressTime && now - lastTPressTime < ALT_T_DOUBLE_PRESS_MS) {
      lastTPressTime = 0;
      toggleStatusTracking();
      return;
    }
    lastTPressTime = now;
    announceChatHeaderShortcut();
  }
  function remapWhatsAppShortcut(e) {
    const remap = SHORTCUT_REMAPS[e.code];
    if (!remap || !isShortcutRemapEnabled(remap[0])) return false;
    const target = e.target?.dispatchEvent ? e.target : document.activeElement || document.body;
    if (!target?.dispatchEvent || typeof KeyboardEvent !== "function") return false;
    if (remap[0] === "voice-recording") armNextVoiceMessageCapture();
    e.preventDefault();
    target.dispatchEvent(new KeyboardEvent("keydown", {
      key: remap[1],
      code: remap[2],
      altKey: true,
      ctrlKey: true,
      shiftKey: true,
      bubbles: true,
      cancelable: true
    }));
    return true;
  }
  function handleNavShortcut(e) {
    if (!e.altKey || !e.shiftKey || e.ctrlKey || e.metaKey) return false;
    const navTargets = {
      Digit1: ["navChats", t("chats")],
      Digit2: ["navStatus", t("status"), SELECTORS.statusListFirstRow],
      Digit3: ["navCommunities", t("communities"), SELECTORS.communityListFirstRow],
      Digit4: ["navChannels", t("channels"), SELECTORS.channelListFirstRow],
      Digit5: ["navMetaAI", t("metaAi"), SELECTORS.messageInput]
    };
    if (navTargets[e.code]) {
      e.preventDefault();
      activateNav(...navTargets[e.code]);
      return true;
    }
    if (e.code === "KeyN") {
      e.preventDefault();
      togglePrivacyWithQueueReset();
      return true;
    }
    if (e.code === "KeyL") {
      e.preventDefault();
      lastTPressTime = 0;
      toggleChatPulse();
      return true;
    }
    if (e.code === "KeyD") {
      e.preventDefault();
      focusMessageInputShortcut();
      return true;
    }
    if (e.code === "Digit8") {
      e.preventDefault();
      toggleCleanUiMode();
      return true;
    }
    if (e.code === "Digit9") {
      e.preventDefault();
      toggleOriginalDarkMode();
      return true;
    }
    return false;
  }
  function handleAltShortcut(e) {
    if (!e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return false;
    if (remapWhatsAppShortcut(e)) return true;
    const shortcuts = {
      Digit1: focusChatListShortcut,
      Digit2: focusLastMessageShortcut,
      Digit3: jumpToUnreadShortcut,
      Digit0: closeMediaPlayerShortcut,
      KeyT: handleAltTShortcut
    };
    const handler = shortcuts[e.code];
    if (!handler) return false;
    e.preventDefault();
    handler(e.target);
    return true;
  }
  function scheduleFirstUnreadAfterChatOpen(target) {
    if (!shouldOpenChatsAtFirstUnread() || !target?.closest) return;
    const row = target.closest('div[role="row"]');
    if (!row || !row.closest(SELECTORS.chatListInSide)) return;
    const activator = getChatRowActivator(row);
    if (!activator || target !== activator) return;
    const request = beginFocusRequest();
    const expectedTitle = getChatRowTitle(row);
    const schedule = window.requestAnimationFrame || ((fn) => setTimeout(fn, 50));
    const tryFocus = (attempt) => {
      if (!isFocusRequestCurrent(request) || getActiveModal()) return;
      const main = document.querySelector(SELECTORS.main);
      if (!isChatMainActive(main)) {
        if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryFocus(attempt + 1));
        return;
      }
      if (expectedTitle) {
        const currentTitle = getCurrentChatTitle();
        if (currentTitle && currentTitle !== expectedTitle) {
          if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryFocus(attempt + 1));
          return;
        }
      }
      const messageContainer = main.querySelector(SELECTORS.conversationMessages);
      const unread = messageContainer && findUnreadMessageTarget(messageContainer);
      if (!unread) {
        if (attempt < SHORTCUT_RENDER_RETRIES) schedule(() => tryFocus(attempt + 1));
        return;
      }
      if (focusItem(getBestInnerFocusElement(unread))) {
        unread.scrollIntoView({ block: "center" });
        consumeUnreadTarget();
      }
    };
    schedule(() => tryFocus(1));
  }
  function isVisibleCallControl(control) {
    return isRenderedElement(control) && control.getAttribute("aria-disabled") !== "true" && !control.disabled;
  }
  function getIncomingCallAction(code) {
    if (typeof document.querySelectorAll !== "function") return null;
    const containers = Array.from(
      document.querySelectorAll('[data-testid="voip-container-audio-call"]')
    ).filter((container) => isVisibleCallControl(container));
    if (containers.length !== 1) return null;
    const callRoot = containers[0].closest('[data-testid="move_resize_component"]') || containers[0];
    const matches = Array.from(callRoot.querySelectorAll('[role="toolbar"]')).filter(isVisibleCallControl).map((toolbar) => {
      const buttons = Array.from(toolbar.querySelectorAll("button")).filter(isVisibleCallControl);
      const candidates = buttons.reduce((result, button) => {
        const icon = button.querySelector("svg title")?.textContent?.trim() || "";
        const renderedLabel = Array.from(button.querySelectorAll("span")).filter(isRenderedElement).filter((span) => !span.querySelector("svg")).map((span) => span.textContent || "").join(" ").trim();
        if (!renderedLabel) return result;
        if (icon === "ic-call-end-filled") result.declines.push(button);
        if (icon === "ic-call-filled" || icon === "ic-videocam-filled") result.accepts.push(button);
        return result;
      }, { accepts: [], declines: [] });
      return candidates.accepts.length === 1 && candidates.declines.length === 1 ? candidates : null;
    }).filter(Boolean);
    if (matches.length !== 1) return null;
    return code === "KeyA" ? matches[0].accepts[0] : matches[0].declines[0];
  }
  function isEditableShortcutTarget(target) {
    return !!target?.closest?.(
      'input, textarea, select, [contenteditable="true"], [role="textbox"]'
    );
  }
  function handleIncomingCallShortcut(e) {
    if (!e.ctrlKey || !e.altKey || e.shiftKey || e.metaKey || e.repeat || e.isComposing || e.defaultPrevented || e.getModifierState("AltGraph") || isEditableShortcutTarget(e.target) || e.code !== "KeyA" && e.code !== "KeyD") {
      return false;
    }
    const resolved = getIncomingCallAction(e.code);
    if (!resolved) return false;
    const activeModal = getActiveModal();
    if (activeModal && !activeModal.contains(resolved)) return false;
    e.preventDefault();
    e.stopImmediatePropagation();
    resolved.click();
    return true;
  }
  function handleModalMediaShortcut(e, activeModal) {
    if (!activeModal || !e.altKey || e.ctrlKey || e.shiftKey || e.metaKey || e.repeat || e.isComposing || e.defaultPrevented || e.getModifierState("AltGraph") || e.code !== "Digit0") {
      return false;
    }
    const closeButton = getMediaPlayerCloseButton();
    if (!closeButton || !activeModal.contains(closeButton) || !isRenderedElement(closeButton)) return false;
    e.preventDefault();
    e.stopImmediatePropagation();
    return activateMediaPlayerClose(closeButton);
  }
  function handleShortcuts(e) {
    if (e.isComposing || e.defaultPrevented) {
      lastTPressTime = 0;
      return;
    }
    const isAltT = e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey && e.code === "KeyT";
    const isModifierKey = /^(?:Alt|Control|Shift|Meta)(?:Left|Right)$/.test(e.code);
    const isAltKey = /^(?:Alt)(?:Left|Right)$/.test(e.code);
    if (!e.repeat && !isModifierKey) cancelPendingFocusRequests();
    if (!isAltT && !isAltKey || isAltT && e.repeat) lastTPressTime = 0;
    const settingsMenu = document.getElementById("wa-plus-settings-menu");
    if (settingsMenu && !settingsMenu.hidden) return;
    if (!e.repeat && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey && (e.key === "Enter" || e.code === "Enter") && !getActiveModal()) {
      scheduleFirstUnreadAfterChatOpen(e.target);
    }
    if (handleIncomingCallShortcut(e)) return;
    const activeModal = getActiveModal();
    if (handleModalMediaShortcut(e, activeModal)) return;
    if (e.repeat || e.metaKey || e.getModifierState("AltGraph") || activeModal) return;
    if (handleNavShortcut(e) || handleAltShortcut(e)) e.stopImmediatePropagation();
  }

  // src/settings-menu.js
  var MENU_ITEM_SELECTOR = '[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]';
  var UPDATE_DOWNLOAD_URL = "https://update.greasyfork.org/scripts/587557/WhatsApp%20Web%20Plus.user.js";
  var AUDIO_PROFILE_MENU_OPTIONS = [
    ["whatsapp", "audioProfileWhatsApp"],
    ["natural", "audioProfileNatural"],
    ["clear", "audioProfileClear"],
    ["clear-plus", "audioProfileClearPlus"],
    ["noise-filter", "audioProfileNoiseFilter"]
  ];
  var CALL_AUDIO_PROFILE_MENU_OPTIONS = [
    ["whatsapp", "callAudioProfileWhatsApp"],
    ["raw", "callAudioProfileRaw"],
    ["natural", "callAudioProfileNatural"],
    ["clear", "callAudioProfileClear"],
    ["noise-filter", "callAudioProfileNoiseFilter"]
  ];
  var STATUS_CUSTOM_KEYS = /* @__PURE__ */ new Set([
    "status-pause-labels",
    "status-read-more-labels",
    "status-media-fallback"
  ]);
  var rootMenu = null;
  var languageMenu = null;
  var languageItem = null;
  var privacyItem = null;
  var submenuMenus = /* @__PURE__ */ new Map();
  var submenuItems = /* @__PURE__ */ new Map();
  var activeSubmenuKey = "";
  var updateItem = null;
  var invoker = null;
  var alertTimer = null;
  var customDialog = null;
  var customDialogTitle = null;
  var customDialogLabel = null;
  var customDialogHelp = null;
  var customDialogError = null;
  var customDialogErrorTimer = null;
  var customDialogInput = null;
  var customDialogCancel = null;
  var customDialogSave = null;
  var customDialogInvoker = null;
  var customDialogKey = "";
  var customDialogName = "";
  function createMenuItem(role, action) {
    const item = document.createElement("button");
    item.type = "button";
    item.setAttribute("role", role);
    item.setAttribute("tabindex", "-1");
    item.dataset.action = action;
    const indicator = document.createElement("span");
    indicator.className = "wa-plus-menu-indicator";
    indicator.setAttribute("aria-hidden", "true");
    indicator.textContent = role === "menuitemcheckbox" ? "\u2713" : role === "menuitemradio" ? "\u25CF" : "";
    const label = document.createElement("span");
    label.className = "wa-plus-menu-label";
    const chevron = document.createElement("span");
    chevron.className = "wa-plus-menu-chevron";
    chevron.setAttribute("aria-hidden", "true");
    item.append(indicator, label, chevron);
    item.waPlusLabel = label;
    item.waPlusChevron = chevron;
    return item;
  }
  function setMenuItemLabel(item, text) {
    item.waPlusLabel.textContent = text;
  }
  function createSubmenu(key, labelKey, id) {
    const item = createMenuItem("menuitem", key);
    item.id = `${id}-item`;
    item.dataset.labelKey = labelKey;
    item.setAttribute("aria-haspopup", "menu");
    item.setAttribute("aria-expanded", "false");
    item.setAttribute("aria-controls", id);
    item.waPlusChevron.textContent = "\u203A";
    const menu = document.createElement("div");
    menu.id = id;
    menu.className = "wa-plus-settings-menu";
    menu.setAttribute("role", "menu");
    menu.setAttribute("aria-labelledby", item.id);
    menu.hidden = true;
    submenuItems.set(key, item);
    submenuMenus.set(key, menu);
    return { item, menu };
  }
  function createMenu() {
    const style = document.createElement("style");
    style.textContent = `
    .wa-plus-settings-menu {
      position: fixed;
      z-index: 2147483647;
      box-sizing: border-box;
      min-width: min(22rem, calc(100vw - 1rem));
      max-width: calc(100vw - 1rem);
      max-height: calc(100vh - 1rem);
      overflow: auto;
      padding: 0.25rem;
      border: 1px solid ButtonBorder;
      border-radius: 0.375rem;
      background: Canvas;
      color: CanvasText;
      box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 30%);
      font: 0.9375rem/1.4 system-ui, sans-serif;
    }
    .wa-plus-settings-menu[hidden] { display: none !important; }
    .wa-plus-settings-menu button {
      display: grid;
      grid-template-columns: 1.5rem minmax(0, 1fr) 1rem;
      width: 100%;
      box-sizing: border-box;
      border: 0;
      border-radius: 0.25rem;
      padding: 0.5rem 0.625rem;
      background: transparent;
      color: inherit;
      font: inherit;
      text-align: start;
      cursor: default;
    }
    .wa-plus-menu-indicator {
      grid-column: 1;
    }
    .wa-plus-menu-label { grid-column: 2; }
    .wa-plus-menu-chevron {
      grid-column: 3;
      justify-self: end;
    }
    .wa-plus-settings-menu [role="menuitemcheckbox"] > .wa-plus-menu-indicator,
    .wa-plus-settings-menu [role="menuitemradio"] > .wa-plus-menu-indicator {
      visibility: hidden;
    }
    .wa-plus-settings-menu [aria-checked="true"] > .wa-plus-menu-indicator { visibility: visible; }
    .wa-plus-settings-menu button:focus {
      outline: 2px solid Highlight;
      outline-offset: -2px;
      background: Highlight;
      color: HighlightText;
    }
    .wa-plus-settings-alert {
      position: fixed;
      z-index: 2147483647;
      inset-inline: 1rem;
      bottom: 1rem;
      max-width: 36rem;
      margin-inline: auto;
      box-sizing: border-box;
      padding: 0.75rem 1rem;
      border: 2px solid ButtonBorder;
      border-radius: 0.375rem;
      background: Canvas;
      color: CanvasText;
      box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 30%);
      font: 0.9375rem/1.4 system-ui, sans-serif;
    }
    .wa-plus-settings-alert:empty {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border: 0;
    }
    .wa-plus-custom-text-dialog {
      width: min(32rem, calc(100vw - 2rem));
      box-sizing: border-box;
      padding: 1rem;
      border: 2px solid ButtonBorder;
      border-radius: 0.5rem;
      background: Canvas;
      color: CanvasText;
      font: 0.9375rem/1.4 system-ui, sans-serif;
    }
    .wa-plus-custom-text-dialog::backdrop { background: rgb(0 0 0 / 55%); }
    .wa-plus-custom-text-dialog h2 { margin: 0 0 1rem; font-size: 1.125rem; }
    .wa-plus-custom-text-dialog label { display: block; margin-bottom: 0.375rem; }
    .wa-plus-custom-text-error { min-height: 1.4em; margin: 0.75rem 0 0; }
    .wa-plus-custom-text-dialog input {
      width: 100%;
      box-sizing: border-box;
      padding: 0.5rem;
      border: 1px solid ButtonBorder;
      background: Field;
      color: FieldText;
      font: inherit;
    }
    .wa-plus-custom-text-dialog input:focus,
    .wa-plus-custom-text-dialog button:focus {
      outline: 2px solid Highlight;
      outline-offset: 2px;
    }
    .wa-plus-custom-text-dialog-actions {
      display: flex;
      justify-content: flex-end;
      gap: 0.5rem;
      margin-top: 1rem;
    }
    .wa-plus-custom-text-dialog button {
      min-height: 2.75rem;
      padding: 0.5rem 1rem;
      border: 1px solid ButtonBorder;
      border-radius: 0.25rem;
      background: ButtonFace;
      color: ButtonText;
      font: inherit;
    }
    @media (forced-colors: active) {
      .wa-plus-settings-menu,
      .wa-plus-custom-text-dialog { forced-color-adjust: auto; }
      .wa-plus-settings-menu button:focus { outline: 2px solid Highlight; }
    }
  `;
    document.head.appendChild(style);
    rootMenu = document.createElement("div");
    rootMenu.id = "wa-plus-settings-menu";
    rootMenu.className = "wa-plus-settings-menu";
    rootMenu.setAttribute("role", "menu");
    rootMenu.hidden = true;
    const language2 = createSubmenu("language", "language", "wa-plus-language-menu");
    language2.item.id = "wa-plus-language-item";
    language2.menu.setAttribute("aria-labelledby", language2.item.id);
    languageItem = language2.item;
    languageMenu = language2.menu;
    rootMenu.appendChild(languageItem);
    privacyItem = createMenuItem("menuitemcheckbox", "privacy");
    privacyItem.dataset.labelKey = "privacyMode";
    rootMenu.appendChild(privacyItem);
    const accessibility = createSubmenu("accessibility", "accessibility", "wa-plus-accessibility-menu");
    const keyboardShortcuts = createSubmenu("keyboard-shortcuts", "keyboardShortcuts", "wa-plus-keyboard-shortcuts-menu");
    const appearance = createSubmenu("appearance", "appearance", "wa-plus-appearance-menu");
    const customLanguageStrings = createSubmenu("custom-language-strings", "customLanguageStrings", "wa-plus-custom-language-strings-menu");
    const audioExperimentsAvailable = installAudioExperimentHooks();
    const voiceRecording = audioExperimentsAvailable ? createSubmenu("voice-recording", "voiceRecording", "wa-plus-voice-recording-menu") : null;
    const voiceCalls = audioExperimentsAvailable ? createSubmenu("voice-calls", "voiceCalls", "wa-plus-voice-calls-menu") : null;
    rootMenu.append(
      accessibility.item,
      keyboardShortcuts.item,
      appearance.item,
      customLanguageStrings.item,
      ...voiceRecording ? [voiceRecording.item] : [],
      ...voiceCalls ? [voiceCalls.item] : []
    );
    if (voiceRecording) {
      const profileGroup = document.createElement("div");
      profileGroup.setAttribute("role", "group");
      profileGroup.dataset.labelKey = "audioProfiles";
      for (const [profile, labelKey] of AUDIO_PROFILE_MENU_OPTIONS) {
        const item = createMenuItem("menuitemradio", `audio-profile-${profile}`);
        item.dataset.audioProfile = profile;
        item.dataset.labelKey = labelKey;
        profileGroup.appendChild(item);
      }
      voiceRecording.menu.append(profileGroup);
      if (IS_DEBUG_BUILD) {
        const separator = document.createElement("div");
        separator.setAttribute("role", "separator");
        const copyDiagnosticsItem = createMenuItem("menuitem", "copy-voice-message-diagnostics");
        copyDiagnosticsItem.dataset.labelKey = "copyVoiceMessageDiagnostics";
        voiceRecording.menu.append(separator, copyDiagnosticsItem);
      }
    }
    if (voiceCalls) {
      const profileGroup = document.createElement("div");
      profileGroup.setAttribute("role", "group");
      profileGroup.dataset.labelKey = "callAudioProfiles";
      for (const [profile, labelKey] of CALL_AUDIO_PROFILE_MENU_OPTIONS) {
        const item = createMenuItem("menuitemradio", `call-audio-profile-${profile}`);
        item.dataset.callAudioProfile = profile;
        item.dataset.labelKey = labelKey;
        profileGroup.appendChild(item);
      }
      voiceCalls.menu.append(profileGroup);
      if (IS_DEBUG_BUILD) {
        const separator = document.createElement("div");
        separator.setAttribute("role", "separator");
        const copyDiagnosticsItem = createMenuItem("menuitem", "copy-call-diagnostics");
        copyDiagnosticsItem.dataset.labelKey = "copyCallDiagnostics";
        voiceCalls.menu.append(separator, copyDiagnosticsItem);
      }
    }
    [
      ["reduceAnnouncements", "reduce-announcements"],
      ["automaticReading", "automatic-reading"],
      ["chatActivity", "chat-activity"],
      ["senderDeviceAnnouncements", "sender-device-announcements"]
    ].forEach(([labelKey, action]) => {
      const item = createMenuItem("menuitemcheckbox", action);
      item.dataset.labelKey = labelKey;
      accessibility.menu.appendChild(item);
    });
    const openUnreadItem = createMenuItem("menuitemcheckbox", "open-chats-at-first-unread");
    openUnreadItem.dataset.labelKey = "openChatsAtFirstUnread";
    accessibility.menu.appendChild(openUnreadItem);
    const statusReadingItem = createMenuItem("menuitemcheckbox", "status-reading-cleanup");
    statusReadingItem.dataset.labelKey = "statusReadingCleanup";
    accessibility.menu.appendChild(statusReadingItem);
    [
      ["remapVoiceRecording", "remap-voice-recording"],
      ["remapPreviousChat", "remap-previous-chat"],
      ["remapNextChat", "remap-next-chat"]
    ].forEach(([labelKey, action]) => {
      const item = createMenuItem("menuitemcheckbox", action);
      item.dataset.labelKey = labelKey;
      keyboardShortcuts.menu.appendChild(item);
    });
    [
      ["cleanUi", "clean-ui"],
      ["originalDark", "original-dark"]
    ].forEach(([labelKey, action]) => {
      const item = createMenuItem("menuitemcheckbox", action);
      item.dataset.labelKey = labelKey;
      appearance.menu.appendChild(item);
    });
    [
      ["unreadDividerText", "custom-unread-divider", "unread-divider"],
      ["typingIndicatorText", "custom-typing-text", "typing"],
      ["recordingAudioIndicatorText", "custom-recording-audio-text", "recording-audio"],
      ["deliveryStatusText", "custom-delivery-status", "delivery-status"],
      ["deliveryPendingText", "custom-delivery-pending", "delivery-pending"],
      ["deliverySentText", "custom-delivery-sent", "delivery-sent"],
      ["deliveryDeliveredText", "custom-delivery-delivered", "delivery-delivered"],
      ["deliveryReadText", "custom-delivery-read", "delivery-read"],
      ["desktopAppPromoText", "custom-desktop-promo", "desktop-promo"],
      ["recentSearchesText", "custom-recent-searches", "recent-searches"],
      ["clearAllText", "custom-clear-all", "clear-all"],
      ["navChatsText", "custom-nav-chats", "nav-chats"],
      ["navStatusText", "custom-nav-status", "nav-status"],
      ["navCommunitiesText", "custom-nav-communities", "nav-communities"],
      ["navChannelsText", "custom-nav-channels", "nav-channels"],
      ["navMetaAIText", "custom-nav-meta-ai", "nav-meta-ai"],
      ["messageContextInstructionText", "custom-message-context-instruction", "message-context-instruction"],
      ["unknownContactPrefixText", "custom-unknown-contact-prefix", "unknown-contact-prefix"],
      ["participantPrefixText", "custom-participant-prefix", "participant-prefix"],
      ["quotePrefixText", "custom-quote-prefix", "quote-prefix"],
      ["onlineStatusText", "custom-online-status", "online-status"],
      ["lastSeenPrefixText", "custom-last-seen-prefix", "last-seen-prefix"],
      ["chatStatusLabelsText", "custom-chat-status-labels", "chat-status-labels"],
      ["viewStatusText", "custom-view-status", "view-status"],
      ["participantSeparatorText", "custom-participant-separator", "participant-separator"],
      ["statusPauseLabelsText", "custom-status-pause-labels", "status-pause-labels"],
      ["statusReadMoreLabelsText", "custom-status-read-more-labels", "status-read-more-labels"],
      ["statusMediaFallbackText", "custom-status-media-fallback", "status-media-fallback"],
      ["scrollToBottomText", "custom-scroll-to-bottom", "scroll-to-bottom"]
    ].forEach(([labelKey, action, customKey]) => {
      const item = createMenuItem("menuitem", action);
      item.dataset.labelKey = labelKey;
      item.dataset.customKey = customKey;
      item.setAttribute("aria-haspopup", "dialog");
      customLanguageStrings.menu.appendChild(item);
    });
    updateItem = createMenuItem("menuitem", "open-update");
    rootMenu.appendChild(updateItem);
    LANGUAGES.forEach(({ value, label }) => {
      const item = createMenuItem("menuitemradio", `language-${value}`);
      item.dataset.language = value;
      setMenuItemLabel(item, label);
      languageMenu.appendChild(item);
    });
    for (const [key, menu] of submenuMenus) {
      submenuItems.get(key)?.after(menu);
      menu.addEventListener("click", handleMenuClick);
    }
    const alert = document.createElement("div");
    alert.id = "wa-plus-settings-alert";
    alert.className = "wa-plus-settings-alert";
    alert.setAttribute("role", "alert");
    alert.setAttribute("aria-atomic", "true");
    customDialog = document.createElement("dialog");
    customDialog.id = "wa-plus-custom-text-dialog";
    customDialog.className = "wa-plus-custom-text-dialog";
    customDialog.setAttribute("aria-labelledby", "wa-plus-custom-text-title");
    const form = document.createElement("form");
    form.method = "dialog";
    customDialogTitle = document.createElement("h2");
    customDialogTitle.id = "wa-plus-custom-text-title";
    customDialogLabel = document.createElement("label");
    customDialogLabel.setAttribute("for", "wa-plus-custom-text-input");
    customDialogInput = document.createElement("input");
    customDialogInput.id = "wa-plus-custom-text-input";
    customDialogInput.type = "text";
    customDialogInput.dir = "auto";
    customDialogInput.setAttribute(
      "aria-describedby",
      "wa-plus-custom-text-help wa-plus-custom-text-error"
    );
    customDialogHelp = document.createElement("p");
    customDialogHelp.id = "wa-plus-custom-text-help";
    customDialogError = document.createElement("p");
    customDialogError.id = "wa-plus-custom-text-error";
    customDialogError.className = "wa-plus-custom-text-error";
    customDialogError.setAttribute("role", "alert");
    customDialogError.setAttribute("aria-atomic", "true");
    const actions = document.createElement("div");
    actions.className = "wa-plus-custom-text-dialog-actions";
    customDialogCancel = document.createElement("button");
    customDialogCancel.type = "button";
    customDialogSave = document.createElement("button");
    customDialogSave.type = "submit";
    actions.append(customDialogCancel, customDialogSave);
    form.append(
      customDialogTitle,
      customDialogLabel,
      customDialogInput,
      customDialogHelp,
      customDialogError,
      actions
    );
    customDialog.appendChild(form);
    document.body.append(rootMenu, alert, customDialog);
    rootMenu.addEventListener("click", handleMenuClick);
    customDialogCancel.addEventListener("click", () => customDialog.close());
    customDialog.addEventListener("close", () => {
      clearCustomDialogSaveError();
      restoreCustomDialogFocus();
    });
    form.addEventListener("submit", saveCustomText);
  }
  function reportSaveError() {
    const alert = document.getElementById("wa-plus-settings-alert");
    if (!alert) return;
    clearTimeout(alertTimer);
    alert.textContent = "";
    alert.lang = getLanguage();
    alert.dir = "ltr";
    alertTimer = setTimeout(() => {
      alert.textContent = t("saveError");
      alertTimer = null;
    }, 0);
  }
  function clearSaveError() {
    const alert = document.getElementById("wa-plus-settings-alert");
    clearTimeout(alertTimer);
    alertTimer = null;
    if (alert) alert.textContent = "";
  }
  function clearCustomDialogSaveError() {
    clearTimeout(customDialogErrorTimer);
    customDialogErrorTimer = null;
    if (customDialogError) customDialogError.textContent = "";
  }
  function reportCustomDialogSaveError() {
    clearCustomDialogSaveError();
    customDialogError.lang = getLanguage();
    customDialogError.dir = "ltr";
    customDialogErrorTimer = setTimeout(() => {
      customDialogError.textContent = t("saveError");
      customDialogErrorTimer = null;
    }, 0);
  }
  function getMenuItems(menu) {
    return Array.from(menu.querySelectorAll(MENU_ITEM_SELECTOR)).filter((item) => item.closest('[role="menu"]') === menu);
  }
  function focusMenuItem(menu, index) {
    const items = getMenuItems(menu);
    if (!items.length) return;
    const target = items[(index + items.length) % items.length];
    items.forEach((item) => item.setAttribute("tabindex", "-1"));
    target.focus({ preventScroll: true });
    target.scrollIntoView({ block: "nearest" });
  }
  function updateMenu() {
    const currentLanguage = LANGUAGES.find((item) => item.value === getLanguage()) || LANGUAGES[0];
    const currentAudioProfile = isAudioExperimentEnabled() ? getAudioExperimentProfile() : "whatsapp";
    const currentCallAudioProfile = isCallAudioExperimentEnabled() ? getCallAudioExperimentProfile() : "whatsapp";
    rootMenu.lang = getLanguage();
    rootMenu.dir = "ltr";
    rootMenu.setAttribute("aria-label", t("settings"));
    for (const [key, menu] of submenuMenus) {
      const item = submenuItems.get(key);
      menu.lang = getLanguage();
      menu.dir = "ltr";
      if (key === "language") setMenuItemLabel(item, `${t("language")}: ${currentLanguage.label}`);
      else setMenuItemLabel(item, t(item.dataset.labelKey));
      for (const group of menu.querySelectorAll('[role="group"]')) {
        if (group.dataset.labelKey) group.setAttribute("aria-label", t(group.dataset.labelKey));
      }
    }
    const states = {
      privacy: isPrivacyModeEnabled(),
      "reduce-announcements": isAnnouncementReductionEnabled(),
      "automatic-reading": isAutomaticReadingEnabled(),
      "chat-activity": isChatActivityEnabled(),
      "sender-device-announcements": isSenderDeviceAnnouncementEnabled(),
      "open-chats-at-first-unread": shouldOpenChatsAtFirstUnread(),
      "status-reading-cleanup": isStatusReadingCleanupEnabled(),
      "remap-voice-recording": isShortcutRemapEnabled("voice-recording"),
      "remap-previous-chat": isShortcutRemapEnabled("previous-chat"),
      "remap-next-chat": isShortcutRemapEnabled("next-chat"),
      "clean-ui": isCleanUiEnabled(),
      "original-dark": isOriginalDarkEnabled()
    };
    setMenuItemLabel(privacyItem, t(privacyItem.dataset.labelKey));
    privacyItem.setAttribute("aria-checked", String(states.privacy));
    for (const menu of submenuMenus.values()) {
      getMenuItems(menu).forEach((item) => {
        const labelKey = item.dataset.labelKey;
        const customKey = item.dataset.customKey;
        if (customKey) {
          const val = getCustomText(customKey);
          const displayVal = val ? t("customValueSet") : t("defaultLabel");
          setMenuItemLabel(item, t(labelKey, { value: displayVal }));
        } else if (labelKey) {
          setMenuItemLabel(item, t(labelKey));
        }
        if (item.getAttribute("role") === "menuitemcheckbox") {
          item.setAttribute("aria-checked", String(states[item.dataset.action]));
        } else if (item.dataset.audioProfile) {
          item.setAttribute("aria-checked", String(item.dataset.audioProfile === currentAudioProfile));
        } else if (item.dataset.callAudioProfile) {
          item.setAttribute("aria-checked", String(item.dataset.callAudioProfile === currentCallAudioProfile));
        }
      });
    }
    setMenuItemLabel(updateItem, t("openUpdate"));
    getMenuItems(languageMenu).forEach((item) => {
      item.lang = item.dataset.language;
      item.dir = "ltr";
      item.setAttribute("aria-checked", String(item.dataset.language === getLanguage()));
    });
  }
  function clamp(value, min, max) {
    return Math.max(min, Math.min(value, max));
  }
  function positionMenu(menu, x, y) {
    const margin = 8;
    menu.style.visibility = "hidden";
    menu.hidden = false;
    const rect = menu.getBoundingClientRect();
    menu.style.left = `${clamp(x, margin, Math.max(margin, innerWidth - rect.width - margin))}px`;
    menu.style.top = `${clamp(y, margin, Math.max(margin, innerHeight - rect.height - margin))}px`;
    menu.style.visibility = "";
  }
  function positionSubmenu(key) {
    const parentItem = submenuItems.get(key);
    const menu = submenuMenus.get(key);
    const parentRect = parentItem.getBoundingClientRect();
    menu.style.visibility = "hidden";
    menu.hidden = false;
    const rect = menu.getBoundingClientRect();
    const x = parentRect.right + rect.width <= innerWidth - 8 ? parentRect.right : parentRect.left - rect.width;
    const y = clamp(parentRect.top, 8, Math.max(8, innerHeight - rect.height - 8));
    menu.style.left = `${clamp(x, 8, Math.max(8, innerWidth - rect.width - 8))}px`;
    menu.style.top = `${y}px`;
    menu.style.visibility = "";
  }
  function closeSubmenu(returnFocus = false) {
    if (!activeSubmenuKey) return;
    const item = submenuItems.get(activeSubmenuKey);
    const menu = submenuMenus.get(activeSubmenuKey);
    menu.hidden = true;
    item.setAttribute("aria-expanded", "false");
    activeSubmenuKey = "";
    if (returnFocus) item.focus({ preventScroll: true });
  }
  function openSubmenu(key) {
    const item = submenuItems.get(key);
    const menu = submenuMenus.get(key);
    if (!item || !menu) return;
    if (activeSubmenuKey && activeSubmenuKey !== key) closeSubmenu(false);
    activeSubmenuKey = key;
    item.setAttribute("aria-expanded", "true");
    positionSubmenu(key);
    focusMenuItem(menu, 0);
  }
  function isSettingsMenuOpen() {
    return !!rootMenu && !rootMenu.hidden;
  }
  function restoreSettingsFocus(primary) {
    return [
      primary,
      getNavButton("navChats"),
      document.querySelector(SELECTORS.chatList),
      document.body
    ].some(focusItem);
  }
  function closeSettingsMenu(restoreFocus = true) {
    if (!rootMenu || rootMenu.hidden) return;
    closeSubmenu(false);
    rootMenu.hidden = true;
    getMenuItems(rootMenu).forEach((item) => item.setAttribute("tabindex", "-1"));
    for (const menu of submenuMenus.values()) {
      menu.hidden = true;
      getMenuItems(menu).forEach((item) => item.setAttribute("tabindex", "-1"));
    }
    if (restoreFocus) restoreSettingsFocus(invoker);
    invoker = null;
  }
  function openSettingsMenu(x, y, source) {
    if (!rootMenu) return;
    cancelPendingFocusRequests();
    if (isSettingsMenuOpen()) closeSettingsMenu(false);
    const activeElement = document.activeElement;
    invoker = activeElement?.isConnected && activeElement !== document.body ? activeElement : source?.isConnected ? source : null;
    updateMenu();
    positionMenu(rootMenu, x, y);
    focusMenuItem(rootMenu, 0);
  }
  function anchorForKeyboard() {
    const target = document.activeElement;
    const rect = target?.getBoundingClientRect?.();
    if (rect && (rect.width || rect.height)) {
      return { x: rect.left, y: rect.bottom, target };
    }
    return { x: 16, y: 16, target };
  }
  function openUpdatePage() {
    closeSettingsMenu(true);
    let opened = null;
    try {
      opened = window.open(UPDATE_DOWNLOAD_URL, "_blank");
      if (opened) opened.opener = null;
    } catch {
    }
    if (!opened) announce(t("updateOpenFailed"));
  }
  function copyTextFallback(text, labelKey) {
    if (!document.body || typeof document.execCommand !== "function") return false;
    const previousFocus = document.activeElement;
    const input = document.createElement("textarea");
    input.value = text;
    input.readOnly = true;
    input.setAttribute("tabindex", "-1");
    input.setAttribute("aria-label", t(labelKey));
    input.style.position = "fixed";
    input.style.inset = "0 auto auto 0";
    input.style.opacity = "0";
    document.body.appendChild(input);
    try {
      input.select();
      return document.execCommand("copy") === true;
    } catch {
      return false;
    } finally {
      input.remove();
      try {
        previousFocus?.focus?.({ preventScroll: true });
      } catch {
      }
    }
  }
  function writeDiagnosticText(text, labelKey, onResult) {
    const fallbackFocus = document.activeElement;
    const fallback = () => document.activeElement === fallbackFocus && copyTextFallback(text, labelKey);
    try {
      if (typeof navigator.clipboard?.writeText === "function") {
        Promise.resolve(navigator.clipboard.writeText(text)).then(
          () => onResult(true),
          () => onResult(fallback())
        );
        return;
      }
      onResult(copyTextFallback(text, labelKey));
    } catch {
      onResult(fallback());
    }
  }
  function copyCallDiagnostics() {
    if (!getCallAudioExperimentReports().length) {
      announce(t("callDiagnosticsUnavailable"));
      return;
    }
    const text = getCallAudioExperimentDiagnosticText();
    writeDiagnosticText(text, "copyCallDiagnostics", (copied) => {
      announce(t(copied ? "callDiagnosticsCopied" : "callDiagnosticsCopyFailed"));
    });
  }
  async function copyFocusedVoiceMessageDiagnostics(target) {
    announce(t("voiceMessageDiagnosticsAnalyzing"));
    const text = await getFocusedVoiceMessageDiagnosticText(target);
    if (!text) {
      announce(t("voiceMessageDiagnosticsUnavailable"));
      return;
    }
    writeDiagnosticText(text, "copyVoiceMessageDiagnostics", (copied) => {
      announce(t(copied ? "voiceMessageDiagnosticsCopied" : "voiceMessageDiagnosticsCopyFailed"));
    });
  }
  function restoreCustomDialogFocus() {
    const target = customDialogInvoker;
    customDialogInvoker = null;
    customDialogKey = "";
    customDialogName = "";
    restoreSettingsFocus(target);
  }
  function openCustomTextDialog(item) {
    customDialogKey = item.dataset.customKey;
    customDialogName = t(item.dataset.labelKey, { value: "" }).replace(/:\s*$/, "").trim();
    customDialogInvoker = invoker;
    closeSettingsMenu(true);
    customDialog.lang = getLanguage();
    customDialog.dir = "ltr";
    customDialogTitle.textContent = t("editCustomText", { name: customDialogName });
    customDialogLabel.textContent = customDialogName;
    customDialogHelp.textContent = t("customTextInstruction");
    customDialogCancel.textContent = t("cancel");
    customDialogSave.textContent = t("save");
    customDialogInput.value = getCustomText(customDialogKey);
    clearCustomDialogSaveError();
    customDialog.showModal();
    customDialogInput.focus({ preventScroll: true });
  }
  function saveCustomText(event) {
    event.preventDefault();
    const value = customDialogInput.value;
    const name = customDialogName;
    clearCustomDialogSaveError();
    const saved = setCustomText(customDialogKey, value);
    if (!saved) {
      reportCustomDialogSaveError();
      customDialogInput.focus({ preventScroll: true });
      return;
    }
    if (STATUS_CUSTOM_KEYS.has(customDialogKey)) refreshStatusAccessibility({ retryControls: true });
    customDialog.close();
    announce(value.trim() ? t("customTextSaved", { name }) : t("customTextReset", { name }));
  }
  function shouldKeepMenuOpen(item) {
    return item?.getAttribute("role") === "menuitemcheckbox";
  }
  function activateItem(item, keepOpen) {
    const action = item.dataset.action;
    let saved = true;
    if (action === "open-update") {
      openUpdatePage();
      return;
    }
    if (IS_DEBUG_BUILD && action === "copy-call-diagnostics") {
      closeSettingsMenu(true);
      void copyCallDiagnostics();
      return;
    }
    if (IS_DEBUG_BUILD && action === "copy-voice-message-diagnostics") {
      const target = invoker;
      closeSettingsMenu(true);
      void copyFocusedVoiceMessageDiagnostics(target);
      return;
    }
    if (submenuMenus.has(action)) {
      openSubmenu(action);
      return;
    }
    clearSaveError();
    if (action.startsWith("language-")) {
      saved = setLanguage(item.dataset.language);
      if (saved) {
        resetPassiveAnnouncementContext();
        if (isPrivacyModeEnabled()) refreshPrivacyAttributes();
        else refreshSenderDeviceLabels();
        refreshStatusAccessibility({ retryControls: true });
      }
    } else if (action === "privacy") {
      saved = togglePrivacyWithQueueReset(false);
    } else if (action === "reduce-announcements") {
      saved = setAnnouncementReduction(!isAnnouncementReductionEnabled());
      if (saved) refreshAnnouncementReduction();
    } else if (action === "automatic-reading") {
      saved = toggleChatPulse(false);
    } else if (action === "chat-activity") {
      saved = toggleStatusTracking(false);
    } else if (action === "sender-device-announcements") {
      saved = setSenderDeviceAnnouncement(!isSenderDeviceAnnouncementEnabled());
      if (saved) {
        refreshSenderDeviceLabels();
        discardPassiveAnnouncements("pulse");
      }
    } else if (action.startsWith("audio-profile-")) {
      saved = selectAudioExperimentProfile(item.dataset.audioProfile);
    } else if (action.startsWith("call-audio-profile-")) {
      saved = selectCallAudioExperimentProfile(item.dataset.callAudioProfile);
    } else if (action === "open-chats-at-first-unread") {
      saved = setOpenChatsAtFirstUnread(!shouldOpenChatsAtFirstUnread());
    } else if (action === "status-reading-cleanup") {
      saved = setStatusReadingCleanup(!isStatusReadingCleanupEnabled());
      if (saved) refreshStatusAccessibility();
    } else if (action.startsWith("remap-")) {
      const name = action.slice("remap-".length);
      saved = setShortcutRemap(name, !isShortcutRemapEnabled(name));
    } else if (action === "clean-ui") {
      saved = toggleCleanUiMode(false);
    } else if (action === "original-dark") {
      saved = toggleOriginalDarkMode(false);
    } else if (action.startsWith("custom-")) {
      openCustomTextDialog(item);
      return;
    }
    if (!saved) {
      reportSaveError();
      updateMenu();
      return;
    }
    updateMenu();
    if (!keepOpen || action.startsWith("language-")) closeSettingsMenu(true);
  }
  function handleMenuClick(event) {
    const item = event.target.closest(MENU_ITEM_SELECTOR);
    if (!item) return;
    event.preventDefault();
    event.stopPropagation();
    activateItem(item, shouldKeepMenuOpen(item));
  }
  function moveFocus(menu, amount) {
    const items = getMenuItems(menu);
    const index = Math.max(0, items.indexOf(document.activeElement));
    focusMenuItem(menu, index + amount);
  }
  function handleSettingsShortcut(event) {
    return event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey && event.code === "F8";
  }
  function handleKeydown(event) {
    if (!event.repeat && !event.isComposing && handleSettingsShortcut(event) && (isSettingsMenuOpen() || !getActiveModal())) {
      event.preventDefault();
      event.stopImmediatePropagation();
      if (isSettingsMenuOpen()) {
        closeSettingsMenu(!getActiveModal());
      } else {
        const anchor = anchorForKeyboard();
        openSettingsMenu(anchor.x, anchor.y, anchor.target);
      }
      return;
    }
    if (!isSettingsMenuOpen()) {
      return;
    }
    const focusedMenu = document.activeElement?.closest?.('[role="menu"]');
    if (event.key === "ContextMenu" || event.key === "F10" && event.shiftKey) {
      const focusIsOutsideOwnedMenus = focusedMenu !== rootMenu && ![...submenuMenus.values()].includes(focusedMenu);
      if (focusIsOutsideOwnedMenus) {
        closeSettingsMenu(false);
        return;
      }
      event.preventDefault();
      event.stopImmediatePropagation();
      closeSettingsMenu(true);
      return;
    }
    if (event.altKey || event.ctrlKey || event.metaKey) {
      return;
    }
    const menu = focusedMenu;
    if (menu !== rootMenu && ![...submenuMenus.values()].includes(menu)) return;
    const activeItem = document.activeElement?.closest?.(MENU_ITEM_SELECTOR);
    const item = activeItem?.closest?.('[role="menu"]') === menu ? activeItem : null;
    if (event.repeat && (event.key === "Enter" || event.key === " ")) {
      event.preventDefault();
      event.stopImmediatePropagation();
      return;
    }
    let handled = true;
    switch (event.key) {
      case "ArrowDown":
        moveFocus(menu, 1);
        break;
      case "ArrowUp":
        moveFocus(menu, -1);
        break;
      case "Home":
        focusMenuItem(menu, 0);
        break;
      case "End":
        focusMenuItem(menu, -1);
        break;
      case "ArrowRight":
        if (item && submenuMenus.has(item.dataset.action)) openSubmenu(item.dataset.action);
        break;
      case "ArrowLeft":
        if (menu !== rootMenu) closeSubmenu(true);
        break;
      case "Enter":
        if (item) activateItem(item, shouldKeepMenuOpen(item));
        break;
      case " ":
        if (item) activateItem(item, shouldKeepMenuOpen(item));
        break;
      case "Escape":
        if (menu !== rootMenu) closeSubmenu(true);
        else closeSettingsMenu(true);
        break;
      case "Tab":
        closeSettingsMenu(true);
        handled = false;
        break;
      default:
        if (event.key.length === 1) {
          const items = getMenuItems(menu);
          const start = Math.max(0, items.indexOf(document.activeElement));
          const needle = event.key.toLocaleLowerCase(getLanguage());
          const match = [...items.slice(start + 1), ...items.slice(0, start + 1)].find((candidate) => candidate.waPlusLabel.textContent.trim().toLocaleLowerCase(getLanguage()).startsWith(needle));
          if (match) focusMenuItem(menu, items.indexOf(match));
          else handled = false;
        } else {
          handled = false;
        }
    }
    if (handled) {
      event.preventDefault();
      event.stopImmediatePropagation();
    }
  }
  function handlePointerDown(event) {
    cancelPendingFocusRequests();
    if (isSettingsMenuOpen() && !event.target.closest?.(".wa-plus-settings-menu")) {
      closeSettingsMenu(!getActiveModal(event.target));
    }
  }
  function handleFocusIn(event) {
    const menu = event.target?.closest?.('[role="menu"]');
    if (isSettingsMenuOpen() && menu !== rootMenu && ![...submenuMenus.values()].includes(menu)) {
      closeSettingsMenu(false);
    }
  }
  function handleClick(event) {
    if (isSettingsMenuOpen() && !event.target.closest?.(".wa-plus-settings-menu")) {
      closeSettingsMenu(false);
    }
  }
  function startSettingsMenu() {
    if (rootMenu || !document.body || !document.head) return;
    createMenu();
    window.addEventListener("keydown", handleKeydown, true);
    window.addEventListener("pointerdown", handlePointerDown, true);
    window.addEventListener("click", handleClick, true);
    window.addEventListener("focusin", handleFocusIn, true);
    window.addEventListener("resize", () => closeSettingsMenu(!getActiveModal()));
  }

  // src/main.js
  function onDomReady(fn) {
    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", fn);
    } else {
      fn();
    }
  }
  function recleanMessageAncestor(node) {
    const message = node && (node.closest?.(`${SELECTORS.conversationMessages} .focusable-list-item`) || node.querySelector?.(".focusable-list-item"));
    if (message) cleanNamedAttribute(message, "aria-label");
  }
  function handleAttributeMutation(mutation) {
    const el = mutation.target;
    const attrName = mutation.attributeName;
    const previousOwner = ownedAttributes.get(el)?.get(attrName)?.owner;
    if (isOwnedMutation(el, attrName)) return null;
    if (attrName === "aria-label" || attrName === "title") {
      cleanNamedAttribute(el, attrName);
      return attrName === "aria-label" ? getRoleFixRoot(el) : null;
    }
    if (attrName === "aria-labelledby" || attrName === "id") {
      const message = el.matches?.(".focusable-list-item") ? el : el.closest?.(".focusable-list-item");
      return [OWNERS.metaAIMessageName, OWNERS.chatLabel, OWNERS.messageGrid].includes(previousOwner) || isMetaAIReply(message) ? getRoleFixRoot(el) : null;
    }
    if (attrName === "data-id" && el.closest?.(SELECTORS.conversationMessages)) {
      recleanMessageAncestor(el);
      return getRoleFixRoot(el);
    }
    if (attrName === "data-pre-plain-text") {
      recleanMessageAncestor(el);
      return null;
    }
    if (attrName === "role" && el.closest) {
      if (el.closest(SELECTORS.conversationMessages)) return el.closest(SELECTORS.conversationMessages);
      if (el.closest(SELECTORS.chatListInSide)) return getRoleFixRoot(el);
    }
    if (attrName === "tabindex" && el.closest?.(SELECTORS.conversationMessages)) {
      return el.closest(SELECTORS.conversationMessages);
    }
    if ((attrName === "aria-hidden" || attrName === "tabindex") && el.closest && el.closest(SELECTORS.chatListInSide)) {
      return getRoleFixRoot(el);
    }
    if (attrName === "class" || attrName === "aria-pressed" || attrName === "aria-selected" || attrName === "data-navbar-item-selected") {
      return getRoleFixRoot(el);
    }
    return null;
  }
  function handleAddedNode(node) {
    if (node.nodeType !== 1) return null;
    cleanElementAttributes(node);
    recleanMessageAncestor(node);
    maybeCaptureUnreadDivider(node);
    return getRoleFixRoot(node) || getRoleFixRoot(node.parentElement);
  }
  var cleanupObserver = null;
  function createCleanupObserver() {
    return new MutationObserver((mutations) => {
      let pulseRelevant = false;
      reconcileUnreadTarget();
      for (const mutation of mutations) {
        const target = mutation.target?.nodeType === 1 ? mutation.target : mutation.target?.parentElement;
        const targetInConversation = !!(target?.matches?.(SELECTORS.conversationMessages) || target?.closest?.(SELECTORS.conversationMessages));
        if (targetInConversation) pulseRelevant = true;
        if (mutation.type === "attributes") {
          scheduleRoleFix(handleAttributeMutation(mutation));
          continue;
        }
        if (mutation.type === "characterData") {
          const parent = mutation.target.parentElement;
          if (parent) {
            cleanNamedAttribute(parent, "aria-label");
            cleanNamedAttribute(parent, "title");
            if (parent.matches?.('span[data-testid="author"]')) {
              cleanElementAttributes(parent);
            }
            recleanMessageAncestor(parent);
            maybeCaptureUnreadDivider(parent);
          }
          scheduleCleanUiSync();
          continue;
        }
        if (mutation.type === "childList") {
          mutation.addedNodes.forEach((node) => {
            scheduleRoleFix(handleAddedNode(node));
            if (node.nodeType === 1 && (node.matches?.(SELECTORS.conversationMessages) || node.querySelector?.(SELECTORS.conversationMessages))) {
              pulseRelevant = true;
            }
          });
          mutation.removedNodes.forEach((node) => {
            if (node.nodeType !== 1) return;
            if (node.matches?.(SELECTORS.statusPlayerRoot) || node.querySelector?.(SELECTORS.statusPlayerRoot)) {
              releaseStatusAccessibility(node);
            }
            forgetPrivacyState(node);
            recoverFocusAfterRemoval(node, mutation.nextSibling, mutation.previousSibling);
          });
          if (targetInConversation) {
            scheduleRoleFix(target.closest?.(SELECTORS.conversationMessages) || target);
          }
          recleanMessageAncestor(mutation.target);
          scheduleCleanUiSync();
        }
      }
      scheduleStatusAccessibilitySync();
      pruneDetachedOwnedElements();
      if (pulseRelevant) scheduleChatPulseSync();
    });
  }
  function startCleanupObserver() {
    if (document.body) {
      if (!cleanupObserver) cleanupObserver = createCleanupObserver();
      cleanupObserver.observe(document.body, {
        childList: true,
        subtree: true,
        characterData: true,
        attributes: true,
        attributeFilter: ["aria-label", "aria-labelledby", "id", "data-id", "title", "role", "class", "tabindex", "hidden", "style", "disabled", "aria-disabled", "aria-hidden", "aria-pressed", "aria-selected", "aria-expanded", "src", "poster", "data-testid", "data-status-id", "data-media-id", "data-animate-status-viewer", "data-navbar-item-selected", "data-pre-plain-text"]
      });
      cleanElementAttributes(document.body);
      const chatList = fixAccessibilityRoles(document.body);
      if (chatList) normalizeChatListTabStops(chatList);
    } else {
      setTimeout(startCleanupObserver, 100);
    }
  }
  onDomReady(function() {
    ensureLiveRegion();
    startSettingsMenu();
    startCleanupObserver();
    startStatusAutoAdvanceGuard();
    updateStyleSheets();
    window.addEventListener("keydown", handleShortcuts, true);
    document.addEventListener("keydown", handleMessageGridKeydown, true);
    document.addEventListener("focusin", (event) => {
      rememberFocusedRow(event.target);
      scheduleStatusAccessibilitySync();
    });
    document.addEventListener("mousedown", (event) => rememberFocusedRow(event.target));
    scheduleStatusAccessibilitySync();
    if (isChatActivityEnabled()) startStatusTracking();
    if (isAutomaticReadingEnabled()) captureChatPulseBaseline();
    console.log(`WhatsApp Web Plus script loaded (v${SCRIPT_VERSION})`);
  });
})();