/* global chrome, SlotSharkPanel */

if (window.__slotshark_axiom_loaded) {
} else {

window.__slotshark_axiom_loaded = true;

// Long-lived port keeps the MV3 service worker awake so the /ping interval
// in background.js keeps firing and the server's HTTPS keepalive stays warm.
(function startKeepalivePort() {
  let port = null;
  let reconnectTimer = null;
  function connect() {
    try {
      port = chrome.runtime.connect({ name: "slotshark-keepalive" });
      port.onDisconnect.addListener(() => {
        port = null;
        if (reconnectTimer) clearTimeout(reconnectTimer);
        reconnectTimer = setTimeout(connect, 1000);
      });
    } catch {
      if (reconnectTimer) clearTimeout(reconnectTimer);
      reconnectTimer = setTimeout(connect, 2000);
    }
  }
  connect();
})();

(async function SlotSharkAxiom() {
  "use strict";

  let prefs = null;
  try {
    const data = await chrome.storage.local.get("slotshark.sitePreferences");
    prefs = data["slotshark.sitePreferences"]?.axiom;
  } catch {
    return;
  }

  if (!prefs?.enabled) return;

  if (location.search.includes("chain=bnb")) return;

  await SlotSharkPanel.init();

  const features = prefs.features || {};
  const observers = {};
  const CLS = SlotSharkPanel._cls;

  const SOL_ADDR_RE = /[1-9A-HJ-NP-Za-km-z]{32,44}/g;

  const activeWaitIntervals = new Set();

  function waitFor(selector, opts = {}) {
    const { root = document, timeout = 5000, all = false } = opts;
    return new Promise((resolve) => {
      const check = () => (all ? root.querySelectorAll(selector) : root.querySelector(selector));
      const result = check();
      if (all ? result.length : result) return resolve(all ? Array.from(result) : result);

      let elapsed = 0;
      const interval = setInterval(() => {
        elapsed += 100;
        const found = check();
        if (all ? found.length : found) {
          clearInterval(interval);
          activeWaitIntervals.delete(interval);
          resolve(all ? Array.from(found) : found);
        } else if (elapsed >= timeout) {
          clearInterval(interval);
          activeWaitIntervals.delete(interval);
          resolve(all ? [] : null);
        }
      }, 100);
      activeWaitIntervals.add(interval);
    });
  }

  function getPoolId() {
    const parts = location.href.split("/meme/");
    return parts.length > 1 ? parts[1].split("?")[0].split("#")[0] : null;
  }

  function getPoolIdFromLink(el) {
    const href = el.getAttribute("href") || el.href || "";
    const match = href.match(/\/meme\/([^?#/]+)/);
    return match ? match[1] : null;
  }

  async function getTokenMint() {
    const mintContainer = document.querySelector(
      "div.ease-in-out.border-primaryStroke\\/70"
    );
    if (!mintContainer) return null;

    const copyTarget = mintContainer.querySelector("div.cursor-pointer");
    if (!copyTarget) return null;

    const addrSpan = copyTarget.querySelector("span.text-textSecondary");
    if (!addrSpan) return null;

    const [prefix, suffix] = (addrSpan.textContent || "").split("...");
    if (!prefix || !suffix) return null;

    copyTarget.click();
    await new Promise((r) => setTimeout(r, 50));

    try {
      const addr = await navigator.clipboard.readText();
      if (addr && addr.startsWith(prefix.trim()) && addr.endsWith(suffix.trim())) return addr;
    } catch { /* clipboard denied */ }
    return null;
  }

  function getMintFromPulseCache(prefix, suffix) {
    try {
      const raw = localStorage.getItem("axiom.pulse");
      if (!raw) return null;
      const data = JSON.parse(raw);
      if (!data?.content) return null;
      const token = data.content.find(
        (t) => t.tokenAddress?.startsWith(prefix) && t.tokenAddress?.endsWith(suffix)
      );
      return token ? token.pairAddress : null;
    } catch {
      return null;
    }
  }

  async function resolveAddressFromRow(rowEl) {
    const copyBtn = rowEl.querySelector("button.group\\/copy");
    if (copyBtn) {
      const [prefix, suffix] = (copyBtn.textContent || "").split("...");
      if (prefix && suffix) {
        const p = prefix.trim(), s = suffix.trim();
        const cached = getMintFromPulseCache(p, s);
        if (cached) return cached;
        copyBtn.click();
        await new Promise((r) => setTimeout(r, 50));
        try {
          const addr = await navigator.clipboard.readText();
          if (addr && addr.startsWith(p) && addr.endsWith(s)) return addr;
        } catch { /* clipboard denied */ }
      }
    }
    const link = rowEl.querySelector('a[href*="/meme/"]');
    return link ? getPoolIdFromLink(link) : null;
  }

  function hasButton(el, cls) {
    return !!el.querySelector(`[class*="${cls || CLS}"]`);
  }

  function insertBeforeSibling(refEl, newEl) {
    refEl.parentNode.insertBefore(newEl, refEl);
  }

  function insertAfterSibling(refEl, newEl) {
    refEl.nextSibling
      ? refEl.parentNode.insertBefore(newEl, refEl.nextSibling)
      : refEl.parentNode.appendChild(newEl);
  }

  async function injectInstantTradePresets() {
    if (!location.pathname.startsWith("/meme/")) return;

    const itCls = CLS + "-it";
    let debounceTimer = null;

    const reinject = () => {
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(() => {
        const panel = document.querySelector("div#instant-trade");
        if (!panel) return;
        if (!panel.querySelector(`.${itCls}`)) {
          setupPresetClones(panel);
        }
      }, 100);
    };

    const tradePanel = await waitFor("div#instant-trade", { timeout: 8000 });
    if (tradePanel) setupPresetClones(tradePanel);

    const obs = new MutationObserver(reinject);
    obs.observe(document.body, { childList: true, subtree: true });
    observers.token = observers.token || [];
    observers.token.push(obs);
  }

  async function setupPresetClones(tradePanel) {
    const itCls = CLS + "-it";
    tradePanel.querySelectorAll(`.${itCls}`).forEach((el) => el.remove());
    tradePanel.parentElement?.querySelectorAll(`.${itCls}`).forEach((el) => el.remove());

    tradePanel.style.minHeight = "358px";

    await SlotSharkPanel._refreshPreset();
    const buyAmounts = SlotSharkPanel._buyPresets;
    const sellPresets = SlotSharkPanel._sellPresets;

    const presetRows = tradePanel.querySelectorAll("div.flex-row.w-full");
    let buyDone = false, sellDone = false;
    presetRows.forEach((row) => {
      const presetBtns = row.querySelectorAll("div.rounded-full:not(.group\\/wallets)");
      if (!presetBtns.length) return;

      const firstText = presetBtns[0]?.textContent?.trim() || "";
      const isSellRow = firstText.includes("%");

      if (isSellRow && sellDone) return;
      if (!isSellRow && buyDone) return;
      if (isSellRow) sellDone = true; else buyDone = true;

      const amounts = isSellRow ? sellPresets : buyAmounts;

      const container = document.createElement("div");
      container.classList.add(itCls);
      Object.assign(container.style, { display: "flex", flexDirection: "column", width: "100%", gap: "4px", marginTop: "4px" });

      for (let i = 0; i < amounts.length; i += 4) {
        const ssRow = document.createElement("div");
        Object.assign(ssRow.style, { display: "flex", width: "100%", gap: row.style.gap || "4px" });

        amounts.slice(i, i + 4).forEach((amount) => {
          const clone = presetBtns[0].cloneNode(true);
          clone.classList.add(itCls);

          const label = isSellRow ? `${amount}%` : `${amount}`;
          const textEl = clone.querySelector("span, div");
          if (textEl) textEl.textContent = label;
          else clone.textContent = label;

          Object.assign(clone.style, {
            border: "1px solid " + SlotSharkPanel._color,
            color: SlotSharkPanel._color,
            zIndex: "200",
            flex: "1",
            userSelect: "none",
          });
          // Override Axiom's inherited `:active { pointer-events: none }` (swallows rapid re-clicks).
          clone.style.setProperty("pointer-events", "auto", "important");

          clone.onclick = async function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (!SlotSharkPanel._isAuthenticated) {
              SlotSharkPanel.showToast("Not logged in. Open SlotShark popup to authenticate.", "error");
              return;
            }
            const poolId = getPoolId();
            if (!poolId) { SlotSharkPanel.showToast("Token not found!", "error"); return; }
            if (isSellRow) SlotSharkPanel._executeSell(poolId, amount);
            else SlotSharkPanel._executeBuy(poolId, amount);
          };

          clone.onmouseover = function () {
            clone.style.backgroundColor = SlotSharkPanel._color;
            clone.style.color = "hsl(var(--twc-grey-900) / var(--twc-grey-900-opacity, var(--tw-text-opacity)))";
          };
          clone.onmouseout = function () {
            clone.style.backgroundColor = "";
            clone.style.color = SlotSharkPanel._color;
          };

          ssRow.appendChild(clone);
        });

        container.appendChild(ssRow);
      }

      row.insertAdjacentElement("afterend", container);
    });
  }

  async function injectInstantTradeButton() {
    if (!location.pathname.startsWith("/meme/")) return;

    const mainBtnCls = CLS + "-tb";

    if (document.querySelector(`.${mainBtnCls}`)) return;

    const allBtns = await waitFor(
      "button.bg-decrease.rounded-full.items-center, button.bg-increase.rounded-full.items-center",
      { all: true, timeout: 8000 }
    );
    if (!allBtns.length) return;
    const filtered = allBtns.filter((b) => b.textContent !== "Place Order");
    const mainBtn = filtered[filtered.length - 1];
    if (!mainBtn) return;

    const allInputs = await waitFor("input.w-full.h-full.bg-transparent", { all: true, timeout: 5000 });
    const inputEl = allInputs.length ? allInputs[allInputs.length - 1] : null;
    if (!inputEl) return;

    mainBtn.parentElement.style.flexDirection = "column";
    mainBtn.style.width = "100%";
    mainBtn.style.marginBottom = "6px";

    const getLabel = () => {
      const sell = mainBtn.textContent.includes("Sell");
      const val = inputEl.value || "0";
      return sell ? `Sell ${val}%` : `Buy ${val} SOL`;
    };

    const ssBtn = SlotSharkPanel.createInstantTradeButton(getLabel(), {
      onClick: async () => {
        const poolId = getPoolId();
        if (!poolId) { SlotSharkPanel.showToast("Token not found!", "error"); return; }
        const sell = mainBtn.textContent.includes("Sell");
        const val = parseFloat(inputEl.value || "0");
        if (isNaN(val) || !val) { SlotSharkPanel.showToast("Invalid amount!", "error"); return; }
        if (sell) SlotSharkPanel._executeSell(poolId, val);
        else SlotSharkPanel._executeBuy(poolId, val);
      },
    });
    ssBtn.classList.add(mainBtnCls);

    mainBtn.insertAdjacentElement("afterend", ssBtn);

    const updateLabel = () => {
      const isSellNoPercent = mainBtn.textContent.includes("Sell") &&
        !inputEl.parentElement?.parentElement?.lastElementChild?.querySelector("span")?.textContent?.trim()?.includes("%");
      ssBtn.style.display = isSellNoPercent ? "none" : "block";
      const span = ssBtn.querySelector("span");
      if (span) span.textContent = getLabel();
    };
    setTimeout(updateLabel, 1000);

    const inputObs = new MutationObserver(updateLabel);
    inputObs.observe(inputEl, { attributes: true, attributeFilter: ["value"] });

    const btnObs = new MutationObserver(updateLabel);
    if (mainBtn.firstChild) btnObs.observe(mainBtn.firstChild, { childList: true });
    btnObs.observe(mainBtn, { characterData: true, subtree: true });

    observers.token = observers.token || [];
    observers.token.push(inputObs, btnObs);
  }

  async function injectPulseQB() {
    const containers = await waitFor(
      ".h-full.flex-1.overflow-hidden.bg-backgroundSecondary",
      { all: true, timeout: 8000 }
    );
    if (!containers.length) return;

    const rowSelector = "div[style*='position: absolute'][style*='width: 100%']";

    containers.forEach((container) => {
      container.querySelectorAll(rowSelector).forEach((row) => injectPulseRow(row));

      let sweepPending = false;
      const sweepMissingRows = () => {
        sweepPending = false;
        container.querySelectorAll(rowSelector).forEach((row) => {
          if (row.querySelector(`[class*="${CLS}"]`)) return;
          // Wait for Axiom's native anchor before injecting; a later mutation retriggers the sweep.
          const hasAnchor =
            row.querySelector("button.group\\/quickBuyButton") ||
            row.querySelector(
              "img[src*='pump-grad.svg'], img[src*='virtual-curve-grad.svg'], img[src*='bonk-grad.svg'], img[src*='boop-grad.svg']"
            );
          if (hasAnchor) injectPulseRow(row);
        });
      };

      const obs = new MutationObserver((mutations) => {
        const pending = new Set();
        mutations.forEach((m) => {
          m.addedNodes.forEach((node) => {
            if (node.nodeType === Node.ELEMENT_NODE) pending.add(node);
          });
        });
        pending.forEach((node) => {
          if (node.nodeName === "DIV" && !node.classList.length) {
            injectPulseRow(node);
          } else if (
            node.nodeName === "DIV" &&
            node.classList.contains("hidden") &&
            node.innerHTML.includes("ri-crosshair-2-fill")
          ) {
            const parent = node.closest(rowSelector);
            if (parent) injectPulseRow(parent);
          }
        });
        // Debounced fallback sweep — virtualized rows can mutate in-place without hitting the branches above.
        if (!sweepPending) {
          sweepPending = true;
          requestAnimationFrame(sweepMissingRows);
        }
      });
      obs.observe(container, { childList: true, subtree: true });
      observers.pulse = observers.pulse || [];
      observers.pulse.push(obs);
    });
  }

  function injectPulseRow(rowEl) {
    const pumpImg = rowEl.querySelector('img[src="https://axiom.trade/images/pump.svg"]');
    const isGraduated = pumpImg && pumpImg.closest("div.bg-primaryBlue");

    rowEl.querySelectorAll(`[class*="${CLS}"]`).forEach((el) => el.remove());

    if (isGraduated) {
      const gradImgs = rowEl.querySelectorAll(
        "img[src*='pump-grad.svg'], img[src*='virtual-curve-grad.svg'], img[src*='bonk-grad.svg'], img[src*='boop-grad.svg']"
      );
      const anchors = Array.from(gradImgs).map((img) => img.closest("div.relative")).filter(Boolean);
      anchors.forEach((anchor) => {
        addPulseButton(rowEl, anchor);
      });
    } else {
      const qbButtons = rowEl.querySelectorAll("button.group\\/quickBuyButton");
      if (!qbButtons.length) return;

      qbButtons.forEach((qb) => {
        if (qb.parentElement) {
          Object.assign(qb.parentElement.style, { display: "flex", marginBottom: "-4px", gap: "2px" });
        }
        addPulseButton(rowEl, qb);
      });
    }
  }

  function addPulseButton(rowEl, anchorEl) {
    const resolveAddress = async () => {
      const copyBtn = rowEl.querySelector("button.group\\/copy");
      if (!copyBtn) { SlotSharkPanel.showToast("Token not found!", "error"); return null; }
      const [prefix, suffix] = (copyBtn.textContent || "").split("...");
      if (!prefix || !suffix) { SlotSharkPanel.showToast("Token not found!", "error"); return null; }
      const p = prefix.trim(), s = suffix.trim();

      const cached = getMintFromPulseCache(p, s);
      if (cached) return cached;
      copyBtn.click();
      await new Promise((r) => setTimeout(r, 50));
      try {
        const addr = await navigator.clipboard.readText();
        if (addr && addr.startsWith(p) && addr.endsWith(s)) return addr;
      } catch { /* clipboard denied */ }
      SlotSharkPanel.showToast("Token not found!", "error");
      return null;
    };

    if (features.pulseQB) {
      const qbBtn = SlotSharkPanel.createQuickBuyButton("", {
        type: "pulse-qb",
        resolveAddress,
        style: { marginLeft: "6px" },
      });
      insertAfterSibling(anchorEl, qbBtn);
    }

    if (features.pulsePanel) {
      const panelBtn = SlotSharkPanel.createPanelButton("", { resolveAddress });
      const afterEl = features.pulseQB
        ? anchorEl.nextSibling?.nextSibling || anchorEl.nextSibling
        : anchorEl;
      if (afterEl) insertAfterSibling(afterEl, panelBtn);
      else insertAfterSibling(anchorEl, panelBtn);
    }
  }

  async function injectWatchlist() {
    const getWatchlistLinks = () => {
      const links = document.querySelectorAll('a[href*="/meme/"]');
      return Array.from(links).filter(
        (l) =>
          l.classList.contains("group") &&
          !l.classList.contains("group/token") &&
          !l.closest(".w-full.pointer-events-none:not(.absolute)")
      );
    };

    const stCls = CLS + "-wl";

    const processLinks = (links) => {
      links.forEach((link) => {
        if (link.querySelector(`.${stCls}`)) return;
        const poolId = getPoolIdFromLink(link);
        if (!poolId) return;

        const btn = SlotSharkPanel.createQuickBuyButton(poolId, {
          type: "watchlist",
          style: { marginLeft: "6px" },
        });
        btn.classList.add(stCls);
        link.appendChild(btn);
      });
    };

    processLinks(getWatchlistLinks());

    const obs = new MutationObserver((mutations) => {
      const newLinks = [];
      mutations.forEach((m) => {
        m.addedNodes.forEach((node) => {
          if (node.nodeType !== Node.ELEMENT_NODE) return;
          if (
            node.nodeName === "A" &&
            node.href?.includes("/meme/") &&
            node.classList.contains("group") &&
            !node.classList.contains("group/token")
          ) {
            newLinks.push(node);
          }
          node.querySelectorAll?.('a[href*="/meme/"]')?.forEach((a) => {
            if (a.classList.contains("group") && !a.classList.contains("group/token")) {
              newLinks.push(a);
            }
          });
        });
      });
      if (newLinks.length) processLinks(newLinks);
    });
    obs.observe(document.body, { childList: true, subtree: true });
    observers.watchlist = observers.watchlist || [];
    observers.watchlist.push(obs);
  }

  const wtCls = CLS + "-wt";

  function processTrackerRow(rowEl, force = false) {
    const existing = rowEl.querySelectorAll(`.${wtCls}`);
    if (existing.length > 0 && (force || existing.length > 1)) {
      existing.forEach((el) => el.remove());
    } else if (existing.length === 1 && !force) return;

    const justifyEnd = rowEl.querySelector("div.justify-end");
    if (!justifyEnd) return;

    const link = rowEl.querySelector("a[href*='/meme/']");
    if (!link) return;

    const poolId = getPoolIdFromLink(link);
    if (!poolId) return;

    const prevId = rowEl.dataset.ssPoolId;
    const prevTime = parseInt(rowEl.dataset.ssLastProcessed || "0");
    if (prevId === poolId && Date.now() - prevTime < 500 && !force) return;
    rowEl.dataset.ssPoolId = poolId;
    rowEl.dataset.ssLastProcessed = String(Date.now());

    const btn = SlotSharkPanel.createQuickBuyButton(poolId, {
      type: "wallet-tracker",
      style: { marginRight: "6px" },
    });
    btn.classList.add(wtCls);

    insertBeforeSibling(justifyEnd, btn);
  }

  function isTrackerRow(el) {
    return el.querySelector("a[href*='/meme/']") && el.querySelector("div.justify-end");
  }

  function injectWalletTracker() {
    function scanRows() {
      document.querySelectorAll("div.flex-row.group, div.flex.group").forEach((row) => {
        if (row.querySelector(`.${wtCls}`)) return;
        if (isTrackerRow(row)) processTrackerRow(row);
      });
    }

    scanRows();

    const obs = new MutationObserver((mutations) => {
      for (const m of mutations) {
        for (const node of m.removedNodes) {
          if (node.nodeType === Node.ELEMENT_NODE && node.classList?.contains(wtCls)) {
            const parent = m.target.closest("div.flex.group, div.flex-row.group");
            if (parent) processTrackerRow(parent, true);
          }
        }
        for (const node of m.addedNodes) {
          if (node.nodeType !== Node.ELEMENT_NODE) continue;
          if (node.matches?.("div.flex-row.group, div.flex.group")) {
            if (!node.querySelector(`.${wtCls}`) && isTrackerRow(node)) {
              processTrackerRow(node);
            }
          }
          if (node.querySelectorAll) {
            node.querySelectorAll("div.flex-row.group, div.flex.group").forEach((row) => {
              if (!row.querySelector(`.${wtCls}`) && isTrackerRow(row)) {
                processTrackerRow(row);
              }
            });
          }
        }
      }
    });
    obs.observe(document.body, { childList: true, subtree: true });
    observers["wallet-tracker"] = observers["wallet-tracker"] || [];
    observers["wallet-tracker"].push(obs);

    let polls = 0;
    const pollId = setInterval(() => {
      scanRows();
      if (++polls >= 50) { // 5 seconds then stop
        clearInterval(pollId);
        activeWaitIntervals.delete(pollId);
      }
    }, 100);
    activeWaitIntervals.add(pollId);
  }

  function injectTweetFeed(force = false) {
    document.querySelectorAll("[data-index]").forEach((el) => {
      processTweetItem(el, force);
    });
    setupTweetFeedScrollObserver();
  }

  function processTweetItem(el, force = false) {
    const taCls = CLS + "-ta";
    const paragraphs = el.querySelectorAll("p.text-textSecondary");
    if (!paragraphs.length) return;

    const existing = el.querySelectorAll(`.${taCls}`);
    if (existing.length && !force) return;
    if (existing.length && force) existing.forEach((e) => e.remove());

    const addresses = new Set();
    paragraphs.forEach((p) => {
      const matches = (p.textContent || "").match(SOL_ADDR_RE) || [];
      matches.forEach((a) => addresses.add(a));
    });
    el.querySelectorAll("a[href]").forEach((a) => {
      const href = a.getAttribute("href") || "";
      const match = href.match(SOL_ADDR_RE);
      if (match) addresses.add(match[match.length - 1]);
    });

    if (!addresses.size) return;

    addresses.forEach((addr) => {
      let inserted = false;

      paragraphs.forEach((p) => {
        if (inserted) return;
        const walker = document.createTreeWalker(p, NodeFilter.SHOW_TEXT);
        let textNode;
        while ((textNode = walker.nextNode())) {
          const idx = textNode.textContent.indexOf(addr);
          if (idx === -1) continue;

          if (textNode.nextSibling?.classList?.contains(taCls) && textNode.nextSibling?.dataset?.address === addr) {
            inserted = true;
            break;
          }

          const before = textNode.textContent.slice(0, idx + addr.length);
          const after = textNode.textContent.slice(idx + addr.length);
          textNode.textContent = before;

          const btn = createTweetBuyButton(addr, taCls);
          if (textNode.nextSibling) {
            textNode.parentNode.insertBefore(btn, textNode.nextSibling);
          } else {
            textNode.parentNode.appendChild(btn);
          }

          if (after) {
            const afterNode = document.createTextNode(after);
            if (btn.nextSibling) {
              btn.parentNode.insertBefore(afterNode, btn.nextSibling);
            } else {
              btn.parentNode.appendChild(afterNode);
            }
          }

          inserted = true;
          break;
        }
      });

      if (!inserted) {
        el.querySelectorAll("a[href]").forEach((a) => {
          const href = a.getAttribute("href") || "";
          const match = href.match(SOL_ADDR_RE);
          if (match && match[match.length - 1] === addr) {
            if (a.nextSibling?.classList?.contains(taCls) && a.nextSibling?.dataset?.address === addr) return;
            const btn = createTweetBuyButton(addr, taCls);
            insertAfterSibling(a, btn);
          }
        });
      }
    });
  }

  function createTweetBuyButton(address, taCls) {
    const btn = document.createElement("button");
    btn.type = "button";
    btn.classList.add(taCls);
    btn.dataset.address = address;

    btn.innerHTML = `
      <div style="display:inline-flex;align-items:center;gap:2px;">
        ${SHARK_SVG_12}
        <span style="white-space:nowrap;font-size:12px;font-weight:500;">${SlotSharkPanel._quickBuyAmount}</span>
      </div>
    `;

    Object.assign(btn.style, {
      display: "inline-flex",
      alignItems: "center",
      verticalAlign: "middle",
      border: "1px solid",
      borderRadius: "4px",
      borderColor: SlotSharkPanel._bgColor,
      color: SlotSharkPanel._color,
      backgroundColor: SlotSharkPanel._bgColor,
      marginLeft: "4px",
      marginRight: "2px",
      zIndex: "200",
      cursor: "pointer",
      transition: "background-color 0.2s ease, opacity 0.15s ease-in",
      padding: "4px 5px",
      lineHeight: "1",
      opacity: "0",
    });

    requestAnimationFrame(() => {
      requestAnimationFrame(() => { btn.style.opacity = "1"; });
    });

    btn.onmouseover = function () { btn.style.backgroundColor = "rgba(26, 140, 255, 0.5)"; };
    btn.onmouseout = function () { btn.style.backgroundColor = SlotSharkPanel._bgColor; };

    btn.onclick = async function (e) {
      e.preventDefault();
      e.stopPropagation();
      if (!SlotSharkPanel._isAuthenticated) {
        SlotSharkPanel.showToast("Not logged in. Open SlotShark popup to authenticate.", "error");
        return;
      }
      SlotSharkPanel._executeBuy(address, SlotSharkPanel._quickBuyAmount);
    };

    return btn;
  }

  function setupTweetFeedScrollObserver() {
    if (observers["tweet-feed"]) {
      observers["tweet-feed"].forEach((o) => {
        if (o.disconnect) o.disconnect();
        if (o.cleanup) o.cleanup();
      });
    }
    observers["tweet-feed"] = [];

    const scrollContainers = document.querySelectorAll(
      ".overflow-y-auto, [style*='overflow-y: auto'], [style*='overflow: auto']"
    );

    scrollContainers.forEach((container) => {
      const getTextKey = (el) => {
        const paragraphs = el.querySelectorAll("p.text-textSecondary");
        let textKey = "";
        paragraphs.forEach((p) => {
          const walker = document.createTreeWalker(p, NodeFilter.SHOW_TEXT);
          let node;
          while ((node = walker.nextNode())) {
            if (!node.parentElement.closest(`[class*="${CLS}"]`)) {
              textKey += node.textContent;
            }
          }
        });
        return textKey;
      };

      const process = () => {
        container.querySelectorAll("[data-index]").forEach((el) => {
          const textKey = getTextKey(el);
          const key = `${el.getAttribute("data-index")}:${textKey.slice(0, 100)}`;
          if (el.dataset.ssProcessed !== key) {
            el.querySelectorAll(`[class*="${CLS}-ta"]`).forEach((b) => b.remove());
            el.dataset.ssProcessed = key;
            processTweetItem(el);
          }
        });
      };

      let debounceTimer = null;
      const onScroll = () => {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(process, 100);
      };
      container.addEventListener("scroll", onScroll, { passive: true });

      const mutObs = new MutationObserver((mutations) => {
        let hasChanges = false;
        for (const m of mutations) {
          if (m.addedNodes.length || m.type === "characterData" ||
            (m.type === "attributes" && m.attributeName === "data-index")) {
            hasChanges = true;
            break;
          }
        }
        if (hasChanges) {
          clearTimeout(debounceTimer);
          debounceTimer = setTimeout(process, 50);
        }
      });
      mutObs.observe(container, {
        childList: true, subtree: true, attributes: true,
        attributeFilter: ["data-index", "style"], characterData: true,
      });

      const cleanup = () => {
        container.removeEventListener("scroll", onScroll);
        clearTimeout(debounceTimer);
      };
      observers["tweet-feed"].push(mutObs);
      observers["tweet-feed"].push({ cleanup });
    });
  }

  let searchInterval = null;

  function injectSearch() {
    const srCls = CLS + "-sr";

    const processSearch = () => {
      const input = document.querySelector('input[placeholder*="Search"], input[placeholder*="search"]');
      if (!input) return;
      const fixedContainer = input.closest(".fixed");
      if (!fixedContainer) return;

      fixedContainer.querySelectorAll('a[href*="/meme/"]').forEach((link) => {
        if (link.classList.contains("absolute")) return;
        if (link.querySelector(`.${srCls}`)) return;
        const poolId = getPoolIdFromLink(link);
        if (!poolId) return;

        const btn = SlotSharkPanel.createQuickBuyButton(poolId, {
          type: "search",
          style: { marginLeft: "6px", zIndex: "200", padding: "0px 8px" },
        });
        btn.classList.add(srCls);
        link.appendChild(btn);
      });
    };

    document.addEventListener("focusin", searchFocusIn, true);
    document.addEventListener("input", searchInput, true);
    document.addEventListener("keydown", searchKeydown);
    document.addEventListener("click", searchClickOutside);

    function searchFocusIn(e) {
      if (e.target.tagName === "INPUT" && e.target.placeholder?.toLowerCase().includes("search")) {
        processSearch();
        if (!searchInterval) searchInterval = setInterval(processSearch, 150);
      }
    }
    function searchInput(e) {
      if (e.target.tagName === "INPUT" && e.target.placeholder?.toLowerCase().includes("search")) {
        setTimeout(processSearch, 100);
        setTimeout(processSearch, 300);
      }
    }
    function searchKeydown(e) {
      if (e.key === "Escape" && searchInterval) { clearInterval(searchInterval); searchInterval = null; }
    }
    function searchClickOutside(e) {
      const input = document.querySelector('input[placeholder*="Search"], input[placeholder*="search"]');
      if (input && !input.closest(".fixed")?.contains(e.target) && searchInterval) {
        clearInterval(searchInterval);
        searchInterval = null;
      }
    }

    observers.search = observers.search || [];
    observers.search.push({
      cleanup() {
        document.removeEventListener("focusin", searchFocusIn, true);
        document.removeEventListener("input", searchInput, true);
        document.removeEventListener("keydown", searchKeydown);
        document.removeEventListener("click", searchClickOutside);
        if (searchInterval) { clearInterval(searchInterval); searchInterval = null; }
      },
    });
  }

  async function injectTokenLinks() {
    const stCls = CLS + "-tl";

    const getLinks = () => {
      const links = document.querySelectorAll('a[href*="/meme/"]');
      return Array.from(links).filter(
        (l) =>
          !l.classList.contains("group/token") &&
          !l.classList.contains("group") &&
          !l.closest(".fixed")
      );
    };

    const processLinks = (links) => {
      links.forEach((link) => {
        const existing = link.querySelector(`.${stCls}`);
        if (existing) return;
        const poolId = getPoolIdFromLink(link);
        if (!poolId) return;

        const btn = SlotSharkPanel.createQuickBuyButton(poolId, {
          type: "token-link",
          style: { marginLeft: "6px", padding: "0px 8px", zIndex: "199" },
        });
        btn.classList.add(stCls);
        link.appendChild(btn);
      });
    };

    processLinks(getLinks());

    const obs = new MutationObserver((mutations) => {
      const newLinks = [];
      mutations.forEach((m) => {
        m.addedNodes.forEach((node) => {
          if (node.nodeType !== Node.ELEMENT_NODE) return;
          if (node.nodeName === "A" && node.href?.includes("/meme/") &&
              !node.classList.contains("group/token") && !node.classList.contains("group") &&
              !node.closest(".fixed")) {
            newLinks.push(node);
          }
          node.querySelectorAll?.('a[href*="/meme/"]')?.forEach((a) => {
            if (!a.classList.contains("group/token") && !a.classList.contains("group") &&
                !a.closest(".fixed")) {
              newLinks.push(a);
            }
          });
        });
      });
      if (newLinks.length) processLinks(newLinks);
    });
    obs.observe(document.body, { childList: true, subtree: true });
    observers["token-links"] = observers["token-links"] || [];
    observers["token-links"].push(obs);
  }

  function runInjectors() {
    if (features.instantTrade) injectInstantTradePresets();
    injectInstantTradeButton();
    if (features.pulseQB || features.pulsePanel) injectPulseQB();
    if (features.watchlist) injectWatchlist();
    if (features.walletTracker) injectWalletTracker();

    injectTokenLinks();
    injectTweetFeed(true);
    injectSearch();
  }

  function cleanupAll() {
    SlotSharkPanel.removeAll();

    Object.values(observers).forEach((list) => {
      if (Array.isArray(list)) {
        list.forEach((o) => {
          if (o.disconnect) o.disconnect();
          if (o.cleanup) o.cleanup();
        });
      }
    });
    Object.keys(observers).forEach((k) => delete observers[k]);

    activeWaitIntervals.forEach((id) => clearInterval(id));
    activeWaitIntervals.clear();

    if (searchInterval) { clearInterval(searchInterval); searchInterval = null; }
  }

  let lastUrl = location.href;

  function onNavigate() {
    cleanupAll();
    runInjectors();
    if (window.__ssUpdateFloating) setTimeout(window.__ssUpdateFloating, 50);
  }

  let messageListener = null;
  try {
    messageListener = (msg) => {
      if (msg?.type === "SPA_NAVIGATE" && msg.url !== lastUrl) {
        lastUrl = msg.url;
        onNavigate();
      }
    };
    chrome.runtime.onMessage.addListener(messageListener);
  } catch { /* orphaned script */ }

  const urlPollId = setInterval(() => {
    if (!chrome.runtime?.id) { clearInterval(urlPollId); return; }
    if (location.href !== lastUrl) {
      lastUrl = location.href;
      onNavigate();
    }
  }, 300);

  function onPopstate() {
    if (location.href !== lastUrl) {
      lastUrl = location.href;
      onNavigate();
    }
  }
  window.addEventListener("popstate", onPopstate);

  let storageListener = null;
  try {
    storageListener = (changes) => {
      if (changes["slotshark.sitePreferences"]) {
        const newPrefs = changes["slotshark.sitePreferences"].newValue?.axiom;
        if (newPrefs && !newPrefs.enabled) cleanupAll();
      }
      if (changes["slotshark.presets"] || changes["slotshark.activePreset"]) {
        const panel = document.querySelector("div#instant-trade");
        if (panel) setupPresetClones(panel);
      }
    };
    chrome.storage.onChanged.addListener(storageListener);
  } catch { /* orphaned content script */ }

  function onVisibilityChange() {
    if (document.hidden) cleanupAll();
    else runInjectors();
  }

  function onPointerOver(e) {
    const btn = e.target.closest(`[class*="${CLS}"]`);
    if (btn) btn.style.backgroundColor = "rgba(26, 140, 255, 0.5)";
  }
  function onPointerOut(e) {
    const btn = e.target.closest(`[class*="${CLS}"]`);
    if (btn) btn.style.backgroundColor = SlotSharkPanel._bgColor;
  }

  function onUnload() {
    cleanupAll();
    clearInterval(urlPollId);

    SlotSharkPanel.destroy();
    if (storageListener) {
      try { chrome.storage.onChanged.removeListener(storageListener); } catch {}
    }
    if (messageListener) {
      try { chrome.runtime.onMessage.removeListener(messageListener); } catch {}
    }
    document.removeEventListener("visibilitychange", onVisibilityChange);
    window.removeEventListener("popstate", onPopstate);
    window.removeEventListener("beforeunload", onUnload);
    window.removeEventListener("pagehide", onUnload);
    document.removeEventListener("pointerover", onPointerOver);
    document.removeEventListener("pointerout", onPointerOut);

    window.__slotshark_axiom_loaded = false;
  }

  document.addEventListener("visibilitychange", onVisibilityChange, { passive: true });
  window.addEventListener("beforeunload", onUnload, { passive: true });
  window.addEventListener("pagehide", onUnload, { passive: true });

  document.addEventListener("pointerover", onPointerOver, { passive: true });
  document.addEventListener("pointerout", onPointerOut, { passive: true });

  (function initFloatingPanel() {
    const STORAGE_POS_KEY = "slotshark.panelPos";
    const STORAGE_SIZE_KEY = "slotshark.panelSize";
    const STORAGE_HIDDEN_KEY = "slotshark.panelHidden";

    let panelEl = null;
    let btnEl = null;
    let contentHeight = 195;
    let isDragging = false;
    let dragOffsetX = 0;
    let dragOffsetY = 0;
    let overlay = null;

    function createMinimizeButton() {
      if (document.getElementById("ss-float-btn")) return;
      btnEl = document.createElement("button");
      btnEl.id = "ss-float-btn";
      Object.assign(btnEl.style, {
        position: "fixed", bottom: "20px", right: "20px",
        width: "44px", height: "44px", borderRadius: "50%",
        border: "1px solid rgba(255,255,255,0.15)", background: "#0b0b0f",
        color: "#fff", cursor: "pointer", zIndex: "9999999",
        display: "flex", alignItems: "center", justifyContent: "center",
        transition: "transform 0.15s, background 0.15s", padding: "0",
        boxShadow: "0 4px 16px rgba(0,0,0,0.4)",
      });
      const iconUrl = chrome.runtime.getURL("icons/icon48.png");
      btnEl.innerHTML = `<img src="${iconUrl}" width="28" height="28" style="border-radius:50%;" alt="">`;
      btnEl.onmouseover = () => { btnEl.style.transform = "scale(1.1)"; btnEl.style.background = "#1e2030"; };
      btnEl.onmouseout = () => { btnEl.style.transform = "scale(1)"; btnEl.style.background = "#0b0b0f"; };
      btnEl.onclick = () => restorePanel();
      document.body.appendChild(btnEl);
    }

    function createPanel() {
      if (document.getElementById("ss-float-panel")) return;
      panelEl = document.createElement("div");
      panelEl.id = "ss-float-panel";
      Object.assign(panelEl.style, {
        position: "fixed", top: "50%", left: "50%",
        transform: "translate(-50%, -50%)",
        width: "340px",
        background: "#0b0b0f", borderRadius: "12px",
        border: "1px solid #1e2030",
        boxShadow: "0 8px 32px rgba(0,0,0,0.6)",
        zIndex: "199", overflow: "hidden",
        display: "flex", flexDirection: "column",
      });

      const iframe = document.createElement("iframe");
      iframe.src = chrome.runtime.getURL("floating-panel.html");
      Object.assign(iframe.style, {
        width: "100%", border: "0",
        height: "0", display: "block",
      });
      iframe.allow = "clipboard-write";
      iframe.addEventListener("load", () => {
        setTimeout(() => {
          try {
            const h = iframe.contentDocument?.body?.scrollHeight;
            if (h && h > 100) {
              contentHeight = h;
              iframe.style.height = h + "px";
            }
          } catch {}
          const mint = getPoolId();
          if (mint && iframe.contentWindow) {
            iframe.contentWindow.postMessage({ type: "slotshark-set-mint", mint }, "*");
          }
        }, 100);
      });
      panelEl.appendChild(iframe);

      const edges = ["left", "right"];
      edges.forEach((edge) => {
        const handle = document.createElement("div");
        const isH = edge === "left" || edge === "right";
        Object.assign(handle.style, {
          position: "absolute", zIndex: "10",
          [edge]: "-3px",
          top: isH ? "0" : "",
          left: edge === "bottom" ? "0" : "",
          width: isH ? "6px" : "100%",
          height: isH ? "100%" : "6px",
          cursor: isH ? "ew-resize" : "ns-resize",
        });
        handle.addEventListener("mousedown", (ev) => {
          ev.preventDefault();
          const startX = ev.clientX;
          const startY = ev.clientY;
          const startW = panelEl.offsetWidth;
          const startH = iframe.offsetHeight;
          const startLeft = panelEl.getBoundingClientRect().left;
          const ov = document.createElement("div");
          Object.assign(ov.style, {
            position: "fixed", top: "0", left: "0", width: "100%", height: "100%",
            zIndex: "9999999", cursor: handle.style.cursor,
          });
          document.body.appendChild(ov);
          const onMove = (me) => {
            const dx = me.clientX - startX;
            const dy = me.clientY - startY;
            if (edge === "right") panelEl.style.width = Math.max(280, startW + dx) + "px";
            if (edge === "left") {
              const newW = Math.max(280, startW - dx);
              panelEl.style.width = newW + "px";
              panelEl.style.left = (startLeft + (startW - newW)) + "px";
              panelEl.style.transform = "none";
            }
          };
          const onUp = () => {
            ov.remove();
            document.removeEventListener("mousemove", onMove);
            document.removeEventListener("mouseup", onUp);
            try {
              chrome.storage.local.set({ [STORAGE_SIZE_KEY]: {
                width: panelEl.style.width,
              }});
            } catch {}
          };
          document.addEventListener("mousemove", onMove);
          document.addEventListener("mouseup", onUp);
        });
        panelEl.appendChild(handle);
      });

      document.body.appendChild(panelEl);

      chrome.storage.local.get([STORAGE_POS_KEY, STORAGE_SIZE_KEY]).then((data) => {
        const pos = data[STORAGE_POS_KEY];
        if (pos) {
          panelEl.style.top = pos.top;
          panelEl.style.left = pos.left;
          panelEl.style.transform = "none";
        }
        const size = data[STORAGE_SIZE_KEY];
        if (size) {
          if (size.width) panelEl.style.width = size.width;
        }
      });
    }

    function minimizePanel() {
      if (panelEl) panelEl.style.display = "none";
      if (btnEl) btnEl.style.display = "flex";
      chrome.storage.local.set({ [STORAGE_HIDDEN_KEY]: true });
      notifyIframePause(true);
    }

    function restorePanel() {
      if (!panelEl) createPanel();
      panelEl.style.display = "flex";
      if (btnEl) btnEl.style.display = "none";
      chrome.storage.local.set({ [STORAGE_HIDDEN_KEY]: false });

      const mint = getPoolId();
      if (mint) {
        const iframe = panelEl.querySelector("iframe");
        if (iframe?.contentWindow) {
          iframe.contentWindow.postMessage({ type: "slotshark-set-mint", mint }, "*");
        }
      }
    }

    function createOverlay(cursor) {
      overlay = document.createElement("div");
      Object.assign(overlay.style, {
        position: "fixed", top: "0", left: "0", width: "100%", height: "100%",
        zIndex: "9999999", cursor,
      });
      document.body.appendChild(overlay);
    }

    function removeOverlay() {
      if (overlay) { overlay.remove(); overlay = null; }
    }

    let mouseX = 0, mouseY = 0;
    let rafId = null;

    function startDrag(iframeClientX, iframeClientY) {
      if (!panelEl) return;
      isDragging = true;
      const iframe = panelEl.querySelector("iframe");
      const iframeRect = iframe.getBoundingClientRect();
      const panelRect = panelEl.getBoundingClientRect();
      const screenX = iframeRect.left + iframeClientX;
      const screenY = iframeRect.top + iframeClientY;
      panelEl.style.transform = "none";
      panelEl.style.left = panelRect.left + "px";
      panelEl.style.top = panelRect.top + "px";
      dragOffsetX = screenX - panelRect.left;
      dragOffsetY = screenY - panelRect.top;
      mouseX = screenX;
      mouseY = screenY;
      panelEl.style.cursor = "grabbing";
      createOverlay("grabbing");
      overlay.addEventListener("mousemove", (ev) => { mouseX = ev.clientX; mouseY = ev.clientY; });
      overlay.addEventListener("mouseup", endDrag);
      startRaf();
    }

    function endDrag() {
      if (!isDragging) return;
      isDragging = false;
      stopRaf();
      removeOverlay();
      if (panelEl) {
        panelEl.style.cursor = "";
        try {
          chrome.storage.local.set({ [STORAGE_POS_KEY]: {
            top: panelEl.style.top, left: panelEl.style.left,
          }});
        } catch {}
      }
    }


    function startRaf() {
      stopRaf();
      const tick = () => {
        if (isDragging && panelEl) {
          let x = mouseX - dragOffsetX;
          let y = mouseY - dragOffsetY;
          x = Math.max(0, Math.min(x, window.innerWidth - panelEl.offsetWidth));
          y = Math.max(0, Math.min(y, window.innerHeight - panelEl.offsetHeight));
          panelEl.style.left = x + "px";
          panelEl.style.top = y + "px";
        }
        rafId = requestAnimationFrame(tick);
      };
      rafId = requestAnimationFrame(tick);
    }

    function stopRaf() {
      if (rafId) { cancelAnimationFrame(rafId); rafId = null; }
    }

    let walletPanelEl = null;

    function notifyWalletPanelState(open) {
      const iframe = panelEl?.querySelector("iframe");
      if (iframe?.contentWindow) iframe.contentWindow.postMessage({ type: "slotshark-wallet-panel-state", open }, "*");
    }

    function toggleWalletPanel() {
      if (walletPanelEl) { walletPanelEl.remove(); walletPanelEl = null; notifyWalletPanelState(false); return; }
      if (!panelEl) return;

      walletPanelEl = document.createElement("div");
      walletPanelEl.id = "ss-wallet-panel";
      Object.assign(walletPanelEl.style, {
        position: "fixed", width: "300px",
        background: "#0b0b0f", borderRadius: "12px",
        border: "1px solid #1e2030", boxShadow: "0 8px 32px rgba(0,0,0,0.6)",
        zIndex: "199", display: "flex", flexDirection: "column",
        maxHeight: "400px", overflow: "hidden",
        fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
        fontSize: "13px", color: "#e0e0e0",
      });

      const header = document.createElement("div");
      Object.assign(header.style, {
        display: "flex", justifyContent: "space-between", alignItems: "center",
        padding: "10px 14px", borderBottom: "1px solid #1e2030", flexShrink: "0",
      });
      header.innerHTML = `<span style="font-weight:600;color:#fff;">Wallets</span>`;
      const closeBtn = document.createElement("button");
      Object.assign(closeBtn.style, {
        background: "none", border: "none", color: "#555", cursor: "pointer",
        fontSize: "18px", padding: "0", lineHeight: "1",
      });
      closeBtn.textContent = "\u00D7";
      closeBtn.onclick = () => { walletPanelEl.remove(); walletPanelEl = null; notifyWalletPanelState(false); };
      header.appendChild(closeBtn);
      walletPanelEl.appendChild(header);

      const actions = document.createElement("div");
      Object.assign(actions.style, {
        display: "flex", gap: "0", borderBottom: "1px solid #1e2030", flexShrink: "0",
      });
      const selectAllBtn = document.createElement("button");
      const selectNoneBtn = document.createElement("button");
      [selectAllBtn, selectNoneBtn].forEach((btn) => {
        Object.assign(btn.style, {
          flex: "1", background: "none", border: "none", color: "#1a8cff",
          cursor: "pointer", fontSize: "11px", padding: "8px", fontWeight: "500",
          transition: "background 0.1s",
        });
        btn.onmouseover = () => { btn.style.background = "rgba(26,140,255,0.08)"; };
        btn.onmouseout = () => { btn.style.background = "none"; };
      });
      selectAllBtn.textContent = "Select All";
      selectNoneBtn.textContent = "Deselect All";
      selectAllBtn.onclick = () => {
        activeList = walletList.map((w) => w.pubkey);
        chrome.storage.local.set({ "slotshark.activeWallets": activeList });
        renderList();
      };
      selectNoneBtn.onclick = () => {
        activeList = [];
        chrome.storage.local.set({ "slotshark.activeWallets": activeList });
        renderList();
      };
      actions.appendChild(selectAllBtn);
      actions.appendChild(selectNoneBtn);
      walletPanelEl.appendChild(actions);

      const listEl = document.createElement("div");
      Object.assign(listEl.style, { overflowY: "auto", flex: "1" });
      walletPanelEl.appendChild(listEl);

      let walletList = SlotSharkPanel._wallets.length > 0
        ? [...SlotSharkPanel._wallets]
        : [];
      let activeList = [...SlotSharkPanel._activeWallets];
      const balances = {};

      chrome.storage.local.get(["slotshark.walletOrder"]).then((data) => {
        const order = data["slotshark.walletOrder"] || [];
        if (order.length > 0) {
          const orderMap = {};
          order.forEach((pk, i) => { orderMap[pk] = i; });
          walletList.sort((a, b) => (orderMap[a.pubkey] ?? 9999) - (orderMap[b.pubkey] ?? 9999));
          renderList();
        }
      });

      SlotSharkPanel._apiCall("GET", "/auth/me").then((resp) => {
        if (resp?.data?.success) {
          walletList = (resp.data.wallets || []).filter((w) => w.active);
          chrome.storage.local.get(["slotshark.walletOrder"]).then((data) => {
            const order = data["slotshark.walletOrder"] || [];
            if (order.length > 0) {
              const orderMap = {};
              order.forEach((pk, i) => { orderMap[pk] = i; });
              walletList.sort((a, b) => (orderMap[a.pubkey] ?? 9999) - (orderMap[b.pubkey] ?? 9999));
            }
            renderList();
          });
        }
      });

      function renderList() {
        listEl.innerHTML = walletList.map((w) => {
          const isActive = activeList.includes(w.pubkey);
          const label = w.label || w.pubkey.slice(0, 8) + "...";
          const addr = w.pubkey.slice(0, 4) + "..." + w.pubkey.slice(-3);
          const bal = balances[w.pubkey];
          const solSvgUrl = chrome.runtime.getURL("icons/solana.svg");
          const balText = bal != null ? `<img src="${solSvgUrl}" width="12" height="12" style="vertical-align:middle;margin-right:2px;"> ${bal.toFixed(3)}` : "";
          return `<div class="ss-wp-item" data-pk="${w.pubkey}" style="
            display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;
            border-bottom:1px solid #1e2030;border-left:3px solid ${isActive ? "#1a8cff" : "transparent"};
            transition:background 0.1s;
          ">
            <div style="width:16px;height:16px;border-radius:4px;border:1px solid ${isActive ? "#1a8cff" : "#333"};
              background:${isActive ? "#1a8cff" : "#0b0b0f"};display:flex;align-items:center;justify-content:center;flex-shrink:0;">
              ${isActive ? '<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3"><path d="M5 13l4 4L19 7"/></svg>' : ""}
            </div>
            <div style="flex:1;min-width:0;">
              <div style="font-weight:600;font-size:13px;color:#fff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${label} <span style="font-weight:400;color:#555;font-size:11px;">${addr}</span></div>
            </div>
            <div style="font-size:12px;color:#4ade80;white-space:nowrap;font-weight:500;">${balText}</div>
          </div>`;
        }).join("");

        listEl.querySelectorAll(".ss-wp-item").forEach((item) => {
          item.onmouseover = () => { item.style.background = "rgba(26,140,255,0.06)"; };
          item.onmouseout = () => { item.style.background = ""; };
          item.onclick = () => {
            const pk = item.dataset.pk;
            if (activeList.includes(pk)) activeList = activeList.filter((p) => p !== pk);
            else activeList.push(pk);
            chrome.storage.local.set({ "slotshark.activeWallets": activeList });
            renderList();
          };
        });
      }

      renderList();
      document.body.appendChild(walletPanelEl);
      positionWalletPanel();
      notifyWalletPanelState(true);

      Promise.all(walletList.map(async (w) => {
        const r = await SlotSharkPanel._apiCall("GET", `/wallet/${w.pubkey}/balance`);
        if (r?.data?.success) balances[w.pubkey] = r.data.balanceSol;
      })).then(() => renderList());
    }

    function positionWalletPanel() {
      if (!walletPanelEl || !panelEl) return;
      const rect = panelEl.getBoundingClientRect();
      walletPanelEl.style.top = rect.top + "px";
      walletPanelEl.style.left = (rect.left - 308) + "px";
      if (parseInt(walletPanelEl.style.left) < 8) {
        walletPanelEl.style.left = (rect.right + 8) + "px";
      }
    }

    window.addEventListener("message", (e) => {
      if (e.data?.type === "slotshark-content-height" && panelEl) {
        const h = e.data.height;
        contentHeight = h;
        const iframe = panelEl.querySelector("iframe");
        if (iframe) iframe.style.height = h + "px";
      }
      if (e.data?.type === "slotshark-minimize") { if (walletPanelEl) { walletPanelEl.remove(); walletPanelEl = null; } minimizePanel(); }
      if (e.data?.type === "slotshark-toggle-wallets") toggleWalletPanel();
      if (e.data?.type === "slotshark-drag-start") { if (walletPanelEl) { walletPanelEl.remove(); walletPanelEl = null; } startDrag(e.data.clientX, e.data.clientY); }
      if (e.data?.type === "slotshark-drag-end") endDrag();
      if (e.data?.type === "slotshark-get-mint") {
        const mint = getPoolId();
        if (mint && panelEl) {
          const iframe = panelEl.querySelector("iframe");
          if (iframe?.contentWindow) {
            iframe.contentWindow.postMessage({ type: "slotshark-set-mint", mint }, "*");
          }
        }
      }
      if (e.data?.type === "slotshark-toast" && typeof e.data.message === "string") {
        const duration = typeof e.data.durationMs === "number" ? e.data.durationMs : null;
        SlotSharkPanel.showToast(e.data.message, e.data.toastType === "error" ? "error" : "success", duration);
      }
    });

    document.addEventListener("keydown", (e) => {
      if ((e.ctrlKey || e.metaKey) && e.key === "b") {
        e.preventDefault();
        if (panelEl?.style.display !== "none") minimizePanel();
        else restorePanel();
      }
    });

    window.__ssUpdateFloating = updateFloatingVisibility;
    function notifyIframePause(pause) {
      if (!panelEl) return;
      const iframe = panelEl.querySelector("iframe");
      if (iframe?.contentWindow) iframe.contentWindow.postMessage({ type: pause ? "slotshark-pause" : "slotshark-resume" }, "*");
    }

    function updateFloatingVisibility() {
      if (!chrome.runtime?.id) return;
      const onToken = location.pathname.startsWith("/meme/");
      if (onToken) {
        if (btnEl) btnEl.style.display = panelEl?.style.display !== "none" ? "none" : "flex";
        chrome.storage.local.get(STORAGE_HIDDEN_KEY).then((data) => {
          if (data[STORAGE_HIDDEN_KEY] !== true) {
            restorePanel();
            notifyIframePause(false);
          } else {
            if (btnEl) btnEl.style.display = "flex";
            notifyIframePause(true);
          }
        }).catch(() => {});
      } else {
        if (panelEl) panelEl.style.display = "none";
        if (btnEl) btnEl.style.display = "none";
        if (walletPanelEl) { walletPanelEl.remove(); walletPanelEl = null; notifyWalletPanelState(false); }
        notifyIframePause(true);
      }
    }

    function destroyFloatingPanel() {
      if (panelEl) { panelEl.remove(); panelEl = null; }
      if (btnEl) { btnEl.remove(); btnEl = null; }
      if (walletPanelEl) { walletPanelEl.remove(); walletPanelEl = null; }
    }

    window.addEventListener("beforeunload", destroyFloatingPanel);

    createMinimizeButton();
    updateFloatingVisibility();

  })();

  runInjectors();
})();

} // end duplicate injection guard
