WhatsApp Web Plus

Making WhatsApp web more accessible for visually impaired users

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

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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})`);
  });
})();