(() => {
  'use strict';
  if (window.__PULSE_CUSTOM_EMOJI_PICKER__) return;
  window.__PULSE_CUSTOM_EMOJI_PICKER__ = true;

  const STORAGE_KEY = 'ahSet';
  const ROOT_ID = 'pulse-custom-emoji-picker';
  const STYLE_ID = 'pulse-custom-emoji-picker-style';
  const NATIVE_STYLE_ID = 'pulse-custom-emoji-hide-native-style';
  const RECENT_KEY = 'emoji-picker-recent';

  let enabled = false;
  let root = null;
  let activeCategory = 'pulse';
  let lastEditable = null;
  let lastAnchor = null;
  let lastOpenAt = 0;
  let cleanupTimer = null;

  const CATEGORIES = [
    {
      id: 'pulse',
      label: 'Pulse',
      icon: '🥵',
      items: '🥵 🥰 😍 😇 🥹 🤯 😳 🥶 🤗 🤔 🫣 🤫 🥱 🤤 😈 🤒 🤐 💦 🔥 🍌 🚀 💋 ❤️ 🍆 🍾 🌭 😏 👀 🫦 👌 👈'.split(' ')
    },
    {
      id: 'smileys',
      label: 'Смайлы',
      icon: '😀',
      items: '😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳 😏 😒 😞 😔 😟 😕 🙁 ☹️ 😣 😖 😫 😩 🥺 😢 😭 😤 😠 😡 🤬 🤯 😳 🥵 🥶 😱 😨 😰 😥 😓 🤗 🤔 🫣 🤭 🫢 🫡 🤫 🫠 🤥 😶 😐 😑 😬 🙄 😯 😦 😧 😮 😲 🥱 😴 🤤 😪 😮‍💨 😵 😵‍💫 🤐 🥴 🤢 🤮 🤧 😷 🤒 🤕 🤑 🤠 😈 👿 👹 👺 🤡 💩 👻 💀 ☠️ 👽 👾 🤖 🎃'.split(' ')
    },
    {
      id: 'hearts',
      label: 'Сердца',
      icon: '❤️',
      items: '❤️ 🧡 💛 💚 💙 💜 🖤 🤍 🤎 💔 ❤️‍🔥 ❤️‍🩹 ❣️ 💕 💞 💓 💗 💖 💘 💝 💟 💋 💌 💯 🔥 ✨ ⭐ 🌟 💫 ⚡ 🌈 ☀️ 🌙'.split(' ')
    },
    {
      id: 'gestures',
      label: 'Жесты',
      icon: '👍',
      items: '👋 🤚 🖐️ ✋ 🖖 🫱 🫲 🫳 🫴 👌 🤌 🤏 ✌️ 🤞 🫰 🤟 🤘 🤙 👈 👉 👆 🖕 👇 ☝️ 🫵 👍 👎 ✊ 👊 🤛 🤜 👏 🙌 🫶 👐 🤲 🤝 🙏 ✍️ 💅 🤳 💪 🦾 🦵 🦶 👂 👃 🧠 👀 👁️ 👅 👄 🫦'.split(' ')
    },
    {
      id: 'people',
      label: 'Люди',
      icon: '🙋',
      items: '👶 🧒 👦 👧 🧑 👨 👩 🧔 👱‍♂️ 👱‍♀️ 🧓 👴 👵 🙍 🙎 🙅 🙆 💁 🙋 🧏 🙇 🤦 🤷 👮 🕵️ 💂 🥷 👷 🧑‍⚕️ 🧑‍🎓 🧑‍🏫 🧑‍⚖️ 🧑‍🌾 🧑‍🍳 🧑‍🔧 🧑‍🏭 🧑‍💼 🧑‍🔬 🧑‍💻 🧑‍🎤 🧑‍🎨 🧑‍✈️ 🧑‍🚀 🧑‍🚒 👰 🤵 🧙 🧚 🧛 🧜 🧝 🧞 🧟'.split(' ')
    },
    {
      id: 'animals',
      label: 'Природа',
      icon: '🐱',
      items: '🐶 🐱 🐭 🐹 🐰 🦊 🐻 🐼 🐻‍❄️ 🐨 🐯 🦁 🐮 🐷 🐸 🐵 🙈 🙉 🙊 🐒 🐔 🐧 🐦 🐤 🐣 🐥 🦆 🦅 🦉 🦇 🐺 🐗 🐴 🦄 🐝 🪱 🐛 🦋 🐌 🐞 🐜 🪰 🪲 🪳 🦟 🦗 🕷️ 🦂 🐢 🐍 🦎 🦖 🐙 🦑 🦐 🦞 🦀 🐡 🐠 🐟 🐬 🐳 🦈 🐊 🐅 🐆 🦓 🦍 🦧 🐘 🦛 🦏 🐪 🦒 🦘 🦬 🐃 🐂 🐄 🐎 🐖 🐏 🐑 🦌 🐕 🐩 🐈 🐓 🦃 🦜 🦢 🦩 🕊️ 🐇 🦝 🦨 🦡 🦦 🦥 🐁 🐀 🐿️ 🦔 🌵 🎄 🌲 🌳 🌴 🪵 🌱 🌿 ☘️ 🍀 🎍 🪴 🎋 🍃 🍂 🍁 🍄 🐚 🪨 🌾 💐 🌷 🌹 🥀 🌺 🌸 🌼 🌻'.split(' ')
    },
    {
      id: 'food',
      label: 'Еда',
      icon: '🍕',
      items: '🍏 🍎 🍐 🍊 🍋 🍌 🍉 🍇 🍓 🫐 🍈 🍒 🍑 🥭 🍍 🥥 🥝 🍅 🫒 🥑 🍆 🥔 🥕 🌽 🌶️ 🫑 🥒 🥬 🥦 🧄 🧅 🍄 🥜 🫘 🌰 🍞 🥐 🥖 🫓 🥨 🥯 🥞 🧇 🧀 🍖 🍗 🥩 🥓 🍔 🍟 🍕 🌭 🥪 🌮 🌯 🫔 🥙 🧆 🥚 🍳 🥘 🍲 🫕 🥣 🥗 🍿 🧈 🧂 🥫 🍱 🍘 🍙 🍚 🍛 🍜 🍝 🍠 🍢 🍣 🍤 🍥 🥮 🍡 🥟 🥠 🥡 🦪 🍦 🍧 🍨 🍩 🍪 🎂 🍰 🧁 🥧 🍫 🍬 🍭 🍮 🍯 🍼 🥛 ☕ 🫖 🍵 🧃 🥤 🧋'.split(' ')
    },
    {
      id: 'activity',
      label: 'Активность',
      icon: '⚽',
      items: '⚽ 🏀 🏈 ⚾ 🥎 🎾 🏐 🏉 🥏 🎱 🪀 🏓 🏸 🏒 🏑 🥍 🏏 🪃 🥅 ⛳ 🪁 🏹 🎣 🤿 🥊 🥋 🎽 🛹 🛼 🛷 ⛸️ 🥌 🎿 ⛷️ 🏂 🪂 🏋️ 🤼 🤸 ⛹️ 🤺 🤾 🏌️ 🏇 🧘 🏄 🏊 🤽 🚣 🧗 🚴 🚵 🏆 🥇 🥈 🥉 🏅 🎖️ 🏵️ 🎗️ 🎫 🎟️ 🎪 🤹 🎭 🩰 🎨 🎬 🎤 🎧 🎼 🎹 🥁 🪘 🎷 🎺 🪗 🎸 🪕 🎻 🎲 ♟️ 🎯 🎳 🎮 🎰 🧩'.split(' ')
    },
    {
      id: 'travel',
      label: 'Места',
      icon: '🚗',
      items: '🚗 🚕 🚙 🚌 🚎 🏎️ 🚓 🚑 🚒 🚐 🛻 🚚 🚛 🚜 🏍️ 🛵 🚲 🛴 🛹 🛼 🚨 🚔 🚍 🚘 🚖 🚡 🚠 🚟 🚃 🚋 🚞 🚝 🚄 🚅 🚈 🚂 🚆 🚇 🚊 🚉 ✈️ 🛫 🛬 🛩️ 💺 🛰️ 🚀 🛸 🚁 🛶 ⛵ 🚤 🛥️ 🛳️ ⛴️ 🚢 ⚓ 🛟 🪝 ⛽ 🚧 🚦 🚥 🗺️ 🗿 🗽 🗼 🏰 🏯 🏟️ 🎡 🎢 🎠 ⛲ ⛱️ 🏖️ 🏝️ 🏜️ 🌋 ⛰️ 🏔️ 🗻 🏕️ ⛺ 🛖 🏠 🏡 🏢 🏣 🏥 🏦 🏨 🏩 🏪 🏫 🏬 🏭 🏯 🏰 💒 🗼'.split(' ')
    },
    {
      id: 'objects',
      label: 'Объекты',
      icon: '💡',
      items: '⌚ 📱 📲 💻 ⌨️ 🖥️ 🖨️ 🖱️ 🖲️ 🕹️ 🗜️ 💽 💾 💿 📀 📼 📷 📸 📹 🎥 📽️ 🎞️ 📞 ☎️ 📟 📠 📺 📻 🎙️ 🎚️ 🎛️ 🧭 ⏱️ ⏲️ ⏰ 🕰️ ⌛ ⏳ 📡 🔋 🪫 🔌 💡 🔦 🕯️ 🪔 🧯 🛢️ 💸 💵 💴 💶 💷 🪙 💰 💳 💎 ⚖️ 🪜 🧰 🪛 🔧 🔨 ⚒️ 🛠️ ⛏️ 🪚 🔩 ⚙️ 🪤 🧱 ⛓️ 🧲 🔫 💣 🧨 🪓 🔪 🗡️ 🛡️ 🚬 ⚰️ 🪦 ⚱️ 🏺 🔮 📿 🧿 🪬 💈 ⚗️ 🔭 🔬 🕳️ 🩹 🩺 💊 💉 🩸 🧬 🦠 🧫 🧪 🌡️'.split(' ')
    },
    {
      id: 'symbols',
      label: 'Символы',
      icon: '🔣',
      items: '✅ ☑️ ✔️ ❌ ❎ ➕ ➖ ➗ ✖️ ♾️ ‼️ ⁉️ ❓ ❔ ❕ ❗ 〰️ 💱 💲 ⚕️ ♻️ ⚜️ 🔱 📛 🔰 ⭕ 🟢 🔵 🟣 🔴 🟠 🟡 ⚫ ⚪ 🟤 🔶 🔷 🔸 🔹 🔺 🔻 💠 🔘 🔳 🔲 🏁 🚩 🎌 🏴 🏳️ 🏳️‍🌈 🏴‍☠️ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ⛎ 🔀 🔁 🔂 ▶️ ⏩ ⏭️ ⏯️ ◀️ ⏪ ⏮️ 🔼 ⏫ 🔽 ⏬ ⏸️ ⏹️ ⏺️ ⏏️ 🎦 🔅 🔆 📶 🛜 📳 📴 ♀️ ♂️ ⚧️ ✖️ ➕ ➖ ➗ 🟰'.split(' ')
    }
  ];

  function isVisible(el) {
    if (!el || !el.isConnected) return false;
    const r = el.getBoundingClientRect();
    const st = window.getComputedStyle(el);
    return r.width > 2 && r.height > 2 && st.visibility !== 'hidden' && st.display !== 'none' && Number(st.opacity || 1) !== 0;
  }

  function getEmojiButton(target) {
    const el = target && target.closest && target.closest('[data-testid="emoji-btn"],button[aria-label*="emoji" i],button[title*="emoji" i],button[aria-label*="смай" i],button[title*="смай" i]');
    if (!el) return null;
    if (root && root.contains(el)) return null;
    return el;
  }

  function setNativeValue(el, value) {
    const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
    const desc = Object.getOwnPropertyDescriptor(proto, 'value');
    if (desc && desc.set) desc.set.call(el, value);
    else el.value = value;
  }

  function rememberEditable(el) {
    if (!el || root?.contains(el)) return;
    if ((el.matches && el.matches('textarea,input[type="text"],input:not([type])')) || el.isContentEditable) {
      if (isVisible(el)) lastEditable = el;
    }
  }

  function findEditable() {
    const isGoodField = (el) => {
      if (!el || root?.contains(el)) return false;
      if (!isVisible(el) || el.disabled || el.readOnly) return false;
      return ((el.matches && el.matches('textarea,input[type="text"],input:not([type])')) || el.isContentEditable);
    };

    if (isGoodField(lastEditable)) return lastEditable;

    const active = document.activeElement;
    if (isGoodField(active)) return active;

    const fields = [...document.querySelectorAll('textarea,input[type="text"],input:not([type]),[contenteditable="true"]')]
      .filter(isGoodField);

    if (lastAnchor && fields.length) {
      const ar = lastAnchor.getBoundingClientRect();
      const ax = ar.left + ar.width / 2;
      const ay = ar.top + ar.height / 2;
      fields.sort((a, b) => {
        const ra = a.getBoundingClientRect();
        const rb = b.getBoundingClientRect();
        const da = Math.hypot((ra.left + ra.width / 2) - ax, (ra.top + ra.height / 2) - ay);
        const db = Math.hypot((rb.left + rb.width / 2) - ax, (rb.top + rb.height / 2) - ay);
        return da - db;
      });
      return fields[0] || null;
    }

    fields.sort((a, b) => {
      const ar = a.getBoundingClientRect();
      const br = b.getBoundingClientRect();
      return (br.bottom - ar.bottom) || (br.right - ar.right);
    });
    return fields[0] || null;
  }

  function insertEmoji(emoji) {
    const el = findEditable();
    if (!el) return;
    el.focus();
    if (el.isContentEditable) {
      try {
        document.execCommand('insertText', false, emoji);
      } catch {
        el.textContent = (el.textContent || '') + emoji;
      }
      try {
        el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: emoji }));
      } catch {
        el.dispatchEvent(new Event('input', { bubbles: true }));
      }
      rememberEditable(el);
      scheduleTextareaOverlaySync();
      scheduleEmojiRender();
      return;
    }
    const start = Number.isFinite(el.selectionStart) ? el.selectionStart : String(el.value || '').length;
    const end = Number.isFinite(el.selectionEnd) ? el.selectionEnd : start;
    const value = String(el.value || '');
    const next = value.slice(0, start) + emoji + value.slice(end);
    setNativeValue(el, next);
    const pos = start + emoji.length;
    try { el.setSelectionRange(pos, pos); } catch {}
    try {
      el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: emoji }));
    } catch {
      el.dispatchEvent(new Event('input', { bubbles: true }));
    }
    el.dispatchEvent(new Event('change', { bubbles: true }));
    rememberEditable(el);
    scheduleTextareaOverlaySync();
    scheduleEmojiRender();
  }

  function emojiCodepoint(emoji, keepVariationSelectors = false) {
    const cps = [];
    for (let i = 0; i < emoji.length;) {
      const cp = emoji.codePointAt(i);
      i += cp > 0xffff ? 2 : 1;
      if (!keepVariationSelectors && cp === 0xfe0f) continue;
      cps.push(cp.toString(16));
    }
    return cps.join('-');
  }

  function fluentEmojiUrls(emoji) {
    const base = 'https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode@main/assets/';
    const variants = [
      emojiCodepoint(emoji, false),
      emojiCodepoint(emoji, true)
    ].filter((v, i, arr) => v && arr.indexOf(v) === i);
    return variants.map((code) => `${base}${code}_3d.png`);
  }


  function escapeRegExp(value) {
    return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  }

  const EMOJI_RENDER_MAP = (() => {
    const map = new Map();
    const add = (emoji) => {
      if (!emoji) return;
      map.set(emoji, emoji);
      const noVs = emoji.replace(/\uFE0F/g, '');
      if (noVs && noVs !== emoji) map.set(noVs, emoji);
    };
    CATEGORIES.forEach((cat) => {
      add(cat.icon);
      cat.items.forEach(add);
    });
    return map;
  })();

  const EMOJI_PATTERN = new RegExp(
    [...EMOJI_RENDER_MAP.keys()].sort((a, b) => b.length - a.length).map(escapeRegExp).join('|'),
    'gu'
  );

  let renderTimer = null;
  let textareaTimer = null;
  const textareaOverlays = new Map();

  function textHasKnownEmoji(text) {
    if (!text) return false;
    EMOJI_PATTERN.lastIndex = 0;
    return EMOJI_PATTERN.test(text);
  }

  function escapeHtml(text) {
    return String(text || '')
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  function emojiImageHtml(emoji) {
    const urls = fluentEmojiUrls(emoji);
    const src = urls[0] || '';
    const fallback = escapeHtml(emoji);
    return `<span class="pulse-inline-emoji" data-emoji="${fallback}"><img class="pulse-inline-emoji-img" src="${escapeHtml(src)}" alt="${fallback}" draggable="false" loading="lazy" onerror="this.parentNode.classList.add('no-img')"><span class="pulse-inline-emoji-fallback">${fallback}</span></span>`;
  }

  function renderEmojiHtml(text) {
    const value = String(text || '');
    let out = '';
    let last = 0;
    EMOJI_PATTERN.lastIndex = 0;
    value.replace(EMOJI_PATTERN, (match, offset) => {
      const emoji = EMOJI_RENDER_MAP.get(match) || match;
      out += escapeHtml(value.slice(last, offset));
      out += emojiImageHtml(emoji);
      last = offset + match.length;
      return match;
    });
    out += escapeHtml(value.slice(last));
    return out;
  }

  function shouldSkipEmojiRender(el) {
    if (!el || el.nodeType !== 1) return true;
    if (root && root.contains(el)) return true;
    return !!el.closest('script,style,noscript,textarea,input,select,option,svg,canvas,[contenteditable="true"],#pulse-custom-emoji-picker,.pulse-emoji-textarea-overlay,.pulse-inline-emoji,[data-pulse-emoji-ignore]');
  }

  function renderTextNodeEmoji(node) {
    if (!enabled || !node || node.nodeType !== Node.TEXT_NODE || !node.nodeValue) return;
    const parent = node.parentElement;
    if (shouldSkipEmojiRender(parent)) return;
    if (!textHasKnownEmoji(node.nodeValue)) return;
    const frag = document.createDocumentFragment();
    const text = node.nodeValue;
    let last = 0;
    EMOJI_PATTERN.lastIndex = 0;
    text.replace(EMOJI_PATTERN, (match, offset) => {
      const emoji = EMOJI_RENDER_MAP.get(match) || match;
      if (offset > last) frag.appendChild(document.createTextNode(text.slice(last, offset)));
      const span = document.createElement('span');
      span.className = 'pulse-inline-emoji';
      span.dataset.emoji = emoji;
      span.setAttribute('aria-label', emoji);
      const img = document.createElement('img');
      img.className = 'pulse-inline-emoji-img';
      img.alt = emoji;
      img.draggable = false;
      img.loading = 'lazy';
      const urls = fluentEmojiUrls(emoji);
      img.src = urls.shift() || '';
      img.onerror = () => {
        const next = urls.shift();
        if (next) img.src = next;
        else span.classList.add('no-img');
      };
      const fallback = document.createElement('span');
      fallback.className = 'pulse-inline-emoji-fallback';
      fallback.textContent = emoji;
      span.append(img, fallback);
      frag.appendChild(span);
      last = offset + match.length;
      return match;
    });
    if (last < text.length) frag.appendChild(document.createTextNode(text.slice(last)));
    node.parentNode.replaceChild(frag, node);
  }

  function processEmojiScope(scope) {
    if (!enabled || !scope) return;
    if (scope.nodeType === Node.TEXT_NODE) {
      renderTextNodeEmoji(scope);
      return;
    }
    if (scope.nodeType !== Node.ELEMENT_NODE || shouldSkipEmojiRender(scope)) return;
    const walker = document.createTreeWalker(scope, NodeFilter.SHOW_TEXT, {
      acceptNode(node) {
        if (!node.nodeValue || !textHasKnownEmoji(node.nodeValue)) return NodeFilter.FILTER_REJECT;
        return shouldSkipEmojiRender(node.parentElement) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
      }
    });
    const nodes = [];
    while (walker.nextNode()) nodes.push(walker.currentNode);
    nodes.forEach(renderTextNodeEmoji);
  }

  function scheduleEmojiRender(scope = document.body) {
    if (!enabled) return;
    if (renderTimer) clearTimeout(renderTimer);
    renderTimer = setTimeout(() => {
      renderTimer = null;
      processEmojiScope(scope || document.body);
    }, 60);
  }

  function unrenderInlineEmoji() {
    document.querySelectorAll('.pulse-inline-emoji[data-emoji]').forEach((el) => {
      try { el.replaceWith(document.createTextNode(el.dataset.emoji || '')); } catch {}
    });
  }

  function isTextareaCandidate(el) {
    if (!el || !(el instanceof HTMLTextAreaElement)) return false;
    if (root && root.contains(el)) return false;
    if (!isVisible(el)) return false;
    return true;
  }

  function storeTextareaStyles(el) {
    if (el.dataset.pulseEmojiStored === '1') return;
    el.dataset.pulseEmojiStored = '1';
    el.dataset.pulseEmojiColor = el.style.color || '';
    el.dataset.pulseEmojiCaretColor = el.style.caretColor || '';
    el.dataset.pulseEmojiTextShadow = el.style.textShadow || '';
  }

  function restoreTextareaStyles(el) {
    if (!el || el.dataset.pulseEmojiStored !== '1') return;
    el.style.color = el.dataset.pulseEmojiColor || '';
    el.style.caretColor = el.dataset.pulseEmojiCaretColor || '';
    el.style.textShadow = el.dataset.pulseEmojiTextShadow || '';
    delete el.dataset.pulseEmojiStored;
    delete el.dataset.pulseEmojiColor;
    delete el.dataset.pulseEmojiCaretColor;
    delete el.dataset.pulseEmojiTextShadow;
  }

  function removeTextareaOverlays() {
    textareaOverlays.forEach((overlay, textarea) => {
      try { overlay.remove(); } catch {}
      restoreTextareaStyles(textarea);
    });
    textareaOverlays.clear();
  }

  function forceRestoreTextInputs() {
    try {
      document.querySelectorAll('.pulse-emoji-textarea-overlay').forEach((el) => el.remove());
      document.querySelectorAll('textarea,input[type="text"],input:not([type])').forEach((el) => {
        restoreTextareaStyles(el);
        const color = String(el.style.color || '').replace(/\s/g, '').toLowerCase();
        const fill = String(el.style.webkitTextFillColor || '').replace(/\s/g, '').toLowerCase();
        const caret = String(el.style.caretColor || '').replace(/\s/g, '').toLowerCase();
        if (color === 'transparent' || color === 'rgba(0,0,0,0)') el.style.color = '';
        if (fill === 'transparent' || fill === 'rgba(0,0,0,0)') el.style.webkitTextFillColor = '';
        if (caret === 'transparent' || caret === 'rgba(0,0,0,0)') el.style.caretColor = '';
        if (el.style.textShadow === 'none' && !el.dataset.pulseEmojiTextShadow) el.style.textShadow = '';
        delete el.dataset.pulseEmojiStored;
        delete el.dataset.pulseEmojiColor;
        delete el.dataset.pulseEmojiCaretColor;
        delete el.dataset.pulseEmojiTextShadow;
      });
    } catch {}
  }

  function syncOneTextareaOverlay(textarea) {
    if (!enabled || !isTextareaCandidate(textarea)) {
      const old = textareaOverlays.get(textarea);
      if (old) {
        try { old.remove(); } catch {}
        textareaOverlays.delete(textarea);
      }
      restoreTextareaStyles(textarea);
      return;
    }
    const cs = window.getComputedStyle(textarea);
    storeTextareaStyles(textarea);
    textarea.style.color = 'transparent';
    textarea.style.caretColor = cs.color || '#111';
    textarea.style.textShadow = 'none';
    let overlay = textareaOverlays.get(textarea);
    if (!overlay) {
      overlay = document.createElement('div');
      overlay.className = 'pulse-emoji-textarea-overlay notranslate';
      overlay.setAttribute('translate', 'no');
      overlay.setAttribute('aria-hidden', 'true');
      document.body.appendChild(overlay);
      textareaOverlays.set(textarea, overlay);
      textarea.addEventListener('input', scheduleTextareaOverlaySync, true);
      textarea.addEventListener('scroll', scheduleTextareaOverlaySync, true);
      textarea.addEventListener('focus', scheduleTextareaOverlaySync, true);
      textarea.addEventListener('blur', scheduleTextareaOverlaySync, true);
    }
    const r = textarea.getBoundingClientRect();
    overlay.style.left = `${Math.round(r.left)}px`;
    overlay.style.top = `${Math.round(r.top)}px`;
    overlay.style.width = `${Math.round(r.width)}px`;
    overlay.style.height = `${Math.round(r.height)}px`;
    overlay.style.font = cs.font;
    overlay.style.fontFamily = cs.fontFamily;
    overlay.style.fontSize = cs.fontSize;
    overlay.style.fontWeight = cs.fontWeight;
    overlay.style.lineHeight = cs.lineHeight;
    overlay.style.letterSpacing = cs.letterSpacing;
    overlay.style.textAlign = cs.textAlign;
    overlay.style.padding = cs.padding;
    overlay.style.borderStyle = 'solid';
    overlay.style.borderColor = 'transparent';
    overlay.style.borderTopWidth = cs.borderTopWidth;
    overlay.style.borderRightWidth = cs.borderRightWidth;
    overlay.style.borderBottomWidth = cs.borderBottomWidth;
    overlay.style.borderLeftWidth = cs.borderLeftWidth;
    overlay.style.borderRadius = cs.borderRadius;
    overlay.style.color = cs.color || '#111';
    overlay.style.background = 'transparent';
    overlay.style.whiteSpace = 'pre-wrap';
    overlay.style.overflowWrap = 'break-word';
    overlay.style.wordBreak = cs.wordBreak;
    overlay.style.direction = cs.direction;
    overlay.style.textTransform = cs.textTransform;
    overlay.innerHTML = renderEmojiHtml(textarea.value || '');
    overlay.scrollTop = textarea.scrollTop || 0;
    overlay.scrollLeft = textarea.scrollLeft || 0;
  }

  function syncTextareaOverlays() {
    if (!enabled) {
      removeTextareaOverlays();
      return;
    }
    const current = new Set([...document.querySelectorAll('textarea')].filter(isTextareaCandidate));
    textareaOverlays.forEach((overlay, textarea) => {
      if (!current.has(textarea)) {
        try { overlay.remove(); } catch {}
        textareaOverlays.delete(textarea);
        restoreTextareaStyles(textarea);
      }
    });
    current.forEach(syncOneTextareaOverlay);
  }

  function scheduleTextareaOverlaySync() {
    // Disabled permanently: the visual overlay over Alpha textareas made input text
    // transparent/invisible and broke selection. Textareas must stay native.
    if (textareaTimer) clearTimeout(textareaTimer);
    textareaTimer = setTimeout(() => {
      textareaTimer = null;
      removeTextareaOverlays();
      forceRestoreTextInputs();
    }, 30);
  }

  function ensureStyles() {
    if (!document.getElementById(STYLE_ID)) {
      const style = document.createElement('style');
      style.id = STYLE_ID;
      style.textContent = `
        #${ROOT_ID}{position:fixed;z-index:2147483647;width:365px;max-width:calc(100vw - 16px);height:405px;max-height:calc(100vh - 16px);background:#17212b;color:#dbe8f3;border:1px solid rgba(255,255,255,.08);box-shadow:0 18px 48px rgba(0,0,0,.45);border-radius:10px;overflow:hidden;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;display:flex;flex-direction:column;pointer-events:auto;}
        #${ROOT_ID}.pulse-emoji-hidden{display:none!important;}
        #${ROOT_ID} *{box-sizing:border-box;scrollbar-width:thin;scrollbar-color:#536979 #17212b;}
        #${ROOT_ID} .pulse-emoji-head{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid rgba(255,255,255,.08);background:#1e2b38;}
        #${ROOT_ID} .pulse-emoji-title{font-size:13px;font-weight:800;letter-spacing:.02em;color:#8fb7d7;margin-right:auto;}
        #${ROOT_ID} .pulse-emoji-close{width:26px;height:26px;border:0;border-radius:8px;background:rgba(255,255,255,.06);color:#dbe8f3;cursor:pointer;font-size:18px;line-height:24px;}
        #${ROOT_ID} .pulse-emoji-close:hover{background:rgba(255,255,255,.12);}
        #${ROOT_ID} .pulse-emoji-tabs{display:flex;gap:2px;padding:6px 8px;background:#17212b;border-bottom:1px solid rgba(255,255,255,.06);overflow-x:auto;}
        #${ROOT_ID} .pulse-emoji-tab{flex:0 0 auto;width:34px;height:30px;border:0;border-radius:8px;background:transparent;color:#8aa4b8;cursor:pointer;font-size:17px;display:flex;align-items:center;justify-content:center;}
        #${ROOT_ID} .pulse-emoji-tab:hover{background:rgba(255,255,255,.08);}
        #${ROOT_ID} .pulse-emoji-tab.active{background:#2b5278;color:#fff;}
        #${ROOT_ID} .pulse-emoji-body{flex:1;overflow:auto;padding:8px 8px 10px;background:#17212b;}
        #${ROOT_ID} .pulse-emoji-section-title{font-size:12px;font-weight:700;color:#6f8da2;margin:2px 3px 8px;text-transform:none;}
        #${ROOT_ID} .pulse-emoji-grid{display:grid;grid-template-columns:repeat(8, 1fr);gap:3px;}
        #${ROOT_ID} .pulse-emoji-item{height:38px;border:0;border-radius:8px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;position:relative;}
        #${ROOT_ID} .pulse-emoji-item:hover{background:#25384a;}
        #${ROOT_ID} .pulse-emoji-item:active{transform:scale(.94);background:#2b5278;}
        #${ROOT_ID} .pulse-emoji-img{width:30px;height:30px;display:block;object-fit:contain;}
        #${ROOT_ID} .pulse-emoji-fallback{font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;font-size:24px;line-height:1;display:none;}
        #${ROOT_ID} .pulse-emoji-item.no-img .pulse-emoji-img{display:none;}
        #${ROOT_ID} .pulse-emoji-item.no-img .pulse-emoji-fallback{display:block;}
        .pulse-inline-emoji{display:inline-flex;align-items:center;justify-content:center;width:1.24em;height:1.24em;vertical-align:-.26em;line-height:1;margin:0 .02em;white-space:nowrap;}
        .pulse-inline-emoji-img{width:1.24em;height:1.24em;display:block;object-fit:contain;}
        .pulse-inline-emoji-fallback{display:none;font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;font-size:1em;line-height:1;}
        .pulse-inline-emoji.no-img .pulse-inline-emoji-img{display:none;}
        .pulse-inline-emoji.no-img .pulse-inline-emoji-fallback{display:inline;}
      `;
      document.documentElement.appendChild(style);
    }
  }

  function setNativeHidden(on) {
    let style = document.getElementById(NATIVE_STYLE_ID);
    if (!on) {
      if (style) style.remove();
      return;
    }
    if (!style) {
      style = document.createElement('style');
      style.id = NATIVE_STYLE_ID;
      document.documentElement.appendChild(style);
    }
    style.textContent = '[data-testid="emoji-popover"],[data-testid="emoji-list"]{display:none!important;visibility:hidden!important;pointer-events:none!important;}';
  }

  function destroyRoot() {
    if (root) {
      try { root.remove(); } catch {}
      root = null;
    }
    lastAnchor = null;
  }

  function renderRoot() {
    ensureStyles();
    const keepAnchor = lastAnchor;
    destroyRoot();
    lastAnchor = keepAnchor;
    const category = CATEGORIES.find((c) => c.id === activeCategory) || CATEGORIES[0];
    root = document.createElement('div');
    root.id = ROOT_ID;
    root.className = 'notranslate';
    root.setAttribute('translate', 'no');
    root.setAttribute('lang', 'en');
    root.innerHTML = `
      <div class="pulse-emoji-head">
        <div class="pulse-emoji-title">Pulse emoji</div>
        <button type="button" class="pulse-emoji-close" title="Закрыть">×</button>
      </div>
      <div class="pulse-emoji-tabs"></div>
      <div class="pulse-emoji-body">
        <div class="pulse-emoji-section-title"></div>
        <div class="pulse-emoji-grid"></div>
      </div>
    `;
    const tabs = root.querySelector('.pulse-emoji-tabs');
    CATEGORIES.forEach((cat) => {
      const b = document.createElement('button');
      b.type = 'button';
      b.className = 'pulse-emoji-tab' + (cat.id === activeCategory ? ' active' : '');
      b.title = cat.label;
      b.textContent = cat.icon;
      b.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        activeCategory = cat.id;
        renderRoot();
        if (lastAnchor) positionRoot(lastAnchor);
      });
      tabs.appendChild(b);
    });
    root.querySelector('.pulse-emoji-section-title').textContent = category.label;
    const grid = root.querySelector('.pulse-emoji-grid');
    category.items.forEach((emoji) => {
      const b = document.createElement('button');
      b.type = 'button';
      b.className = 'pulse-emoji-item';
      b.setAttribute('aria-label', emoji);
      b.dataset.emoji = emoji;
      const img = document.createElement('img');
      img.className = 'pulse-emoji-img';
      img.alt = emoji;
      img.draggable = false;
      img.loading = 'lazy';
      const urls = fluentEmojiUrls(emoji);
      img.src = urls.shift() || '';
      img.onerror = () => {
        const next = urls.shift();
        if (next) img.src = next;
        else b.classList.add('no-img');
      };
      const fallback = document.createElement('span');
      fallback.className = 'pulse-emoji-fallback';
      fallback.textContent = emoji;
      b.append(img, fallback);
      b.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        insertEmoji(emoji);
      });
      grid.appendChild(b);
    });
    root.querySelector('.pulse-emoji-close')?.addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();
      destroyRoot();
    });
    // Do not use capture here: capture stopPropagation blocks category, close and emoji item clicks.
    root.addEventListener('pointerdown', (e) => e.stopPropagation(), false);
    root.addEventListener('mousedown', (e) => e.stopPropagation(), false);
    root.addEventListener('click', (e) => e.stopPropagation(), false);
    document.body.appendChild(root);
  }

  function positionRoot(anchor) {
    if (!root || !anchor) return;
    const r = anchor.getBoundingClientRect();
    const w = root.offsetWidth || 365;
    const h = root.offsetHeight || 405;
    const vw = document.documentElement.clientWidth || window.innerWidth;
    const vh = document.documentElement.clientHeight || window.innerHeight;
    let left = Math.round(r.left);
    let top = Math.round(r.top - h - 8);
    if (top < 8) top = Math.round(r.bottom + 8);
    if (left + w > vw - 8) left = vw - w - 8;
    if (left < 8) left = 8;
    if (top + h > vh - 8) top = Math.max(8, vh - h - 8);
    root.style.left = `${left}px`;
    root.style.top = `${top}px`;
  }

  function openPicker(anchor) {
    lastAnchor = anchor;
    renderRoot();
    positionRoot(anchor);
    lastOpenAt = Date.now();
    try { localStorage.removeItem(RECENT_KEY); } catch {}
  }

  function togglePicker(anchor) {
    if (root && lastAnchor === anchor) destroyRoot();
    else openPicker(anchor);
  }

  function removeNativePopovers() {
    if (!enabled) return;
    try {
      document.querySelectorAll('[data-testid="emoji-popover"],[data-testid="emoji-list"]').forEach((el) => {
        el.style.display = 'none';
        el.style.visibility = 'hidden';
        el.style.pointerEvents = 'none';
      });
    } catch {}
  }

  function handleEmojiButtonEvent(e) {
    if (!enabled) return;
    const button = getEmojiButton(e.target);
    if (!button) return;
    e.preventDefault();
    e.stopPropagation();
    try { e.stopImmediatePropagation(); } catch {}
    if (e.type === 'pointerdown' || e.type === 'mousedown') {
      const now = Date.now();
      if (now - lastOpenAt > 120 || lastAnchor !== button || !root) openPicker(button);
    }
    removeNativePopovers();
  }

  function handleOutside(e) {
    if (!enabled || !root) return;
    const button = getEmojiButton(e.target);
    if (button) return;
    if (root.contains(e.target)) return;
    destroyRoot();
  }

  function applyEnabled(next) {
    enabled = !!next;
    setNativeHidden(enabled);
    if (!enabled) {
      destroyRoot();
      removeTextareaOverlays();
      unrenderInlineEmoji();
      try { document.body && document.body.classList.remove('pulse-emoji-enabled'); } catch {}
      return;
    }
    ensureStyles();
    try { document.body && document.body.classList.add('pulse-emoji-enabled'); } catch {}
    removeNativePopovers();
    scheduleEmojiRender(document.body);
    scheduleTextareaOverlaySync();
    try { localStorage.removeItem(RECENT_KEY); } catch {}
  }

  function readEnabled() {
    try {
      chrome.storage.local.get([STORAGE_KEY], (res) => {
        const set = res && res[STORAGE_KEY] && typeof res[STORAGE_KEY] === 'object' ? res[STORAGE_KEY] : {};
        applyEnabled(set.customEmojiPicker === true);
      });
    } catch {
      applyEnabled(false);
    }
  }

  document.addEventListener('focusin', (e) => rememberEditable(e.target), true);
  document.addEventListener('input', (e) => rememberEditable(e.target), true);
  document.addEventListener('click', (e) => rememberEditable(e.target), true);
  document.addEventListener('pointerdown', handleEmojiButtonEvent, true);
  document.addEventListener('mousedown', handleEmojiButtonEvent, true);
  document.addEventListener('click', handleEmojiButtonEvent, true);
  document.addEventListener('pointerdown', handleOutside, false);
  document.addEventListener('keydown', (e) => {
    if (enabled && e.key === 'Escape') destroyRoot();
  }, true);
  window.addEventListener('resize', () => { lastAnchor && root && positionRoot(lastAnchor); scheduleTextareaOverlaySync(); }, true);
  window.addEventListener('scroll', () => { lastAnchor && root && positionRoot(lastAnchor); scheduleTextareaOverlaySync(); }, true);

  const mo = new MutationObserver(() => {
    if (!enabled) return;
    if (cleanupTimer) return;
    cleanupTimer = setTimeout(() => {
      cleanupTimer = null;
      removeNativePopovers();
      scheduleEmojiRender(document.body);
      scheduleTextareaOverlaySync();
    }, 40);
  });
  try { mo.observe(document.documentElement, { childList: true, subtree: true }); } catch {}

  try {
    chrome.storage.onChanged.addListener((changes, area) => {
      if (area !== 'local' || !changes[STORAGE_KEY]) return;
      const set = changes[STORAGE_KEY].newValue || {};
      applyEnabled(set.customEmojiPicker === true);
    });
  } catch {}

  forceRestoreTextInputs();
  setTimeout(forceRestoreTextInputs, 250);
  setTimeout(forceRestoreTextInputs, 1200);
  readEnabled();
})();
