Smart Panic

Navbar panic button — deposit all cash into your vault target stock. Works with Smart Stock Vault or standalone.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         Smart Panic
// @namespace    Noobler.torn.panicNavbar
// @version      2.1.2
// @description  Navbar panic button — deposit all cash into your vault target stock. Works with Smart Stock Vault or standalone.
// @author       Noobler
// @match        https://www.torn.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @connect      api.torn.com
// @license      MIT
// ==/UserScript==


(() => {
  // src/shared/theme.js
  var tokens = {
    accent: "#caa14a",
    accentMuted: "rgba(202, 161, 74, 0.35)",
    accentSubtle: "rgba(202, 161, 74, 0.12)",
    accentText: "#f0e3c0",
    panelBg: "linear-gradient(180deg, #23252b, #1b1d22)",
    panelHeaderBg: "linear-gradient(180deg, #2c2f37, #23252b)",
    panelBorder: "#34373f",
    surface: "#15161a",
    text: "#d7d9de",
    textMuted: "#8a8d96",
    textDim: "#71747d",
    success: "#6fcf86",
    successBg: "#16341f",
    successBorder: "#2c6b3c",
    warning: "#ffd966",
    warningBg: "#332b13",
    warningBorder: "#6b5a1f",
    danger: "#ff6b6b",
    dangerBg: "#341818",
    dangerBorder: "#6b2c2c",
    info: "#8dbdf0",
    infoBg: "#15263d",
    infoBorder: "#2c4f7b",
    hover: "#d8b25c",
    font: "'Trebuchet MS', Verdana, sans-serif",
    radius: "8px",
    shadow: "0 2px 10px rgba(0, 0, 0, 0.35)",
    statDex: "#8a7ff0",
    statDef: "#e07a4f",
    statStr: "#3fae84",
    statSpd: "#4a97e6"
  };
  var STYLE_ID = "hf-torn-theme";
  function injectStyles(scopeClass = "hf-torn") {
    if (document.getElementById(STYLE_ID)) {
      return;
    }
    const css = `
    .${scopeClass} {
      --hf-accent: ${tokens.accent};
      --hf-accent-muted: ${tokens.accentMuted};
      --hf-accent-subtle: ${tokens.accentSubtle};
      --hf-accent-text: ${tokens.accentText};
      --hf-panel-bg: ${tokens.panelBg};
      --hf-panel-header-bg: ${tokens.panelHeaderBg};
      --hf-panel-border: ${tokens.panelBorder};
      --hf-surface: ${tokens.surface};
      --hf-text: ${tokens.text};
      --hf-text-muted: ${tokens.textMuted};
      --hf-text-dim: ${tokens.textDim};
      --hf-success: ${tokens.success};
      --hf-success-bg: ${tokens.successBg};
      --hf-success-border: ${tokens.successBorder};
      --hf-warning: ${tokens.warning};
      --hf-warning-bg: ${tokens.warningBg};
      --hf-warning-border: ${tokens.warningBorder};
      --hf-danger: ${tokens.danger};
      --hf-danger-bg: ${tokens.dangerBg};
      --hf-danger-border: ${tokens.dangerBorder};
      --hf-info: ${tokens.info};
      --hf-info-bg: ${tokens.infoBg};
      --hf-info-border: ${tokens.infoBorder};
      --hf-hover: ${tokens.hover};
      --hf-radius: ${tokens.radius};
      --hf-shadow: ${tokens.shadow};
      --hf-font: ${tokens.font};
      --hf-stat-dex: ${tokens.statDex};
      --hf-stat-def: ${tokens.statDef};
      --hf-stat-str: ${tokens.statStr};
      --hf-stat-spd: ${tokens.statSpd};
      color: var(--hf-text);
      font-family: var(--hf-font);
      font-size: 12px;
      line-height: 1.4;
      box-sizing: border-box;
    }

    .${scopeClass} *, .${scopeClass} *::before, .${scopeClass} *::after {
      box-sizing: border-box;
    }

    .${scopeClass} .hf-btn {
      appearance: none;
      border: 1px solid var(--hf-panel-border);
      border-radius: 5px;
      background: var(--hf-surface);
      color: var(--hf-accent-text);
      cursor: pointer;
      padding: 6px 10px;
      font: inherit;
      transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
    }

    .${scopeClass} .hf-btn:hover {
      background: var(--hf-accent-subtle);
      border-color: var(--hf-accent);
      color: #fff;
    }

    .${scopeClass} .hf-btn.is-active,
    .${scopeClass} .hf-btn--primary {
      background: var(--hf-accent);
      border-color: var(--hf-accent);
      color: #1b1d22;
      font-weight: 700;
    }

    .${scopeClass} .hf-btn.is-active:hover,
    .${scopeClass} .hf-btn--primary:hover {
      background: var(--hf-hover);
      border-color: var(--hf-hover);
    }

    .${scopeClass} .hf-muted {
      color: var(--hf-text-muted);
    }

    .${scopeClass} .hf-dim {
      color: var(--hf-text-dim);
    }

    .${scopeClass} .hf-badge {
      display: inline-block;
      padding: 2px 8px;
      border-radius: 4px;
      background: var(--hf-accent);
      color: #1b1d22;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .${scopeClass} .hf-input,
    .${scopeClass} .hf-select {
      width: 100%;
      box-sizing: border-box;
      padding: 6px 8px;
      background: var(--hf-surface);
      border: 1px solid var(--hf-panel-border);
      color: var(--hf-accent-text);
      border-radius: 5px;
      font: inherit;
      font-size: 12px;
    }

    .${scopeClass} .hf-label {
      display: block;
      font-size: 11px;
      color: var(--hf-text-muted);
      margin: 12px 0 4px;
    }

    .${scopeClass} .hf-table {
      width: 100%;
      border-collapse: collapse;
    }

    .${scopeClass} .hf-table th,
    .${scopeClass} .hf-table td {
      padding: 4px 6px;
      text-align: left;
      border-bottom: 1px solid var(--hf-panel-border);
    }

    .${scopeClass} .hf-table th {
      font-weight: bold;
      color: var(--hf-accent-text);
    }

    .${scopeClass}.hf-panel {
      margin: 0 0 12px;
      border-radius: var(--hf-radius);
      background: var(--hf-panel-bg);
      border: 1px solid var(--hf-panel-border);
      box-shadow: var(--hf-shadow);
      overflow: hidden;
    }

    .${scopeClass}.hf-panel--page {
      width: 100%;
    }

    .${scopeClass}.hf-panel--fixed {
      position: fixed;
      z-index: 9999;
    }

    .${scopeClass} .hf-panel-header {
      background: var(--hf-panel-header-bg);
      border-bottom: 1px solid var(--hf-panel-border);
      border-radius: var(--hf-radius) var(--hf-radius) 0 0;
    }

    .${scopeClass} .hf-panel-tabs {
      border-bottom: 1px solid var(--hf-panel-border);
    }

    .${scopeClass} .hf-panel-body {
      padding: 12px 13px;
    }

    .${scopeClass}.hf-panel--page .hf-panel-body {
      max-height: min(70vh, 640px);
      overflow-y: auto;
    }

    .${scopeClass}.hf-panel--page.hf-panel--grow .hf-panel-body {
      max-height: none;
      overflow: visible;
    }

    .${scopeClass}.hf-overlay,
    .${scopeClass} .hf-overlay {
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.6);
      z-index: 99999;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .${scopeClass}.hf-modal,
    .${scopeClass} .hf-modal {
      background: #1f2127;
      border: 1px solid var(--hf-panel-border);
      border-radius: var(--hf-radius);
      width: min(440px, 92vw);
      max-height: 84vh;
      overflow-y: auto;
      padding: 18px;
      color: var(--hf-text);
    }

    .${scopeClass}.hf-modal h2,
    .${scopeClass} .hf-modal h2 {
      margin: 0 0 14px;
      font-size: 15px;
      color: var(--hf-accent-text);
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .${scopeClass} .hf-mini {
      font-size: 10px;
      color: var(--hf-text-dim);
      margin-top: 3px;
      line-height: 1.4;
    }
  `;
    const style = document.createElement("style");
    style.id = STYLE_ID;
    style.textContent = css;
    document.head.appendChild(style);
  }
  var theme = {
    tokens,
    injectStyles
  };

  // src/shared/storage.js
  var PREFIX = "hf.torn";
  function namespaced(key) {
    return `${PREFIX}.${key}`;
  }
  function getLocal(key, fallback = null) {
    try {
      const raw = localStorage.getItem(namespaced(key));
      if (raw === null) {
        return fallback;
      }
      return JSON.parse(raw);
    } catch {
      return fallback;
    }
  }
  function setLocal(key, value) {
    localStorage.setItem(namespaced(key), JSON.stringify(value));
  }
  function removeLocal(key) {
    localStorage.removeItem(namespaced(key));
  }
  var DB_NAME = "heartflower-torn";
  var DB_VERSION = 1;
  var dbPromise = null;
  function openDb() {
    if (dbPromise) {
      return dbPromise;
    }
    dbPromise = new Promise((resolve, reject) => {
      const request = indexedDB.open(DB_NAME, DB_VERSION);
      request.onupgradeneeded = () => {
        const db = request.result;
        if (!db.objectStoreNames.contains("races")) {
          const store = db.createObjectStore("races", { keyPath: "id" });
          store.createIndex("timestamp", "timestamp", { unique: false });
          store.createIndex("track", "track", { unique: false });
          store.createIndex("carKey", "carKey", { unique: false });
        }
      };
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error ?? new Error("IndexedDB open failed"));
    });
    return dbPromise;
  }
  async function withStore(storeName, mode, run) {
    const db = await openDb();
    return new Promise((resolve, reject) => {
      const tx = db.transaction(storeName, mode);
      const store = tx.objectStore(storeName);
      const request = run(store);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
    });
  }
  async function putRecord(storeName, record) {
    await withStore(storeName, "readwrite", (store) => store.put(record));
  }
  async function deleteRecord(storeName, key) {
    await withStore(storeName, "readwrite", (store) => store.delete(key));
  }
  async function getRecord(storeName, key) {
    return withStore(storeName, "readonly", (store) => store.get(key));
  }
  async function getAllRecords(storeName, query, limit) {
    const db = await openDb();
    return new Promise((resolve, reject) => {
      const tx = db.transaction(storeName, "readonly");
      const store = tx.objectStore(storeName);
      const request = store.getAll(query, limit);
      request.onsuccess = () => resolve(
        /** @type {Record<string, unknown>[]} */
        request.result ?? []
      );
      request.onerror = () => reject(request.error ?? new Error("IndexedDB getAll failed"));
    });
  }
  async function getByIndex(storeName, indexName, key) {
    return withStore(storeName, "readonly", (store) => store.index(indexName).getAll(key));
  }
  var storage = {
    PREFIX,
    getLocal,
    setLocal,
    removeLocal,
    putRecord,
    deleteRecord,
    getRecord,
    getAllRecords,
    getByIndex
  };

  // src/shared/dom.js
  function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
  async function waitFor(selector, options = {}) {
    const { timeout = 1e4, interval = 100, root = document } = options;
    const start = Date.now();
    while (Date.now() - start < timeout) {
      const el = root.querySelector(selector);
      if (el) {
        return el;
      }
      await sleep(interval);
    }
    throw new Error(`waitFor timeout: ${selector}`);
  }
  async function waitForOptional(selector, options = {}) {
    try {
      return await waitFor(selector, options);
    } catch {
      return null;
    }
  }
  function observeMutations(root, callback, options = {}) {
    const { debounce = 50 } = options;
    let timer = null;
    const observer = new MutationObserver(() => {
      if (timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(callback, debounce);
    });
    observer.observe(root, { childList: true, subtree: true });
    callback();
    return () => {
      if (timer) {
        clearTimeout(timer);
      }
      observer.disconnect();
    };
  }
  function onAnchorClick(callback) {
    const handler = (event) => {
      const target = (
        /** @type {Element} */
        event.target
      );
      if (target.tagName === "A" || target.closest("a")) {
        setTimeout(callback, 150);
      }
    };
    document.body.addEventListener("click", handler);
    return () => document.body.removeEventListener("click", handler);
  }
  function normalizeText(text) {
    return text.replace(/\s+/g, " ").trim();
  }
  var dom = {
    sleep,
    waitFor,
    waitForOptional,
    observeMutations,
    onAnchorClick,
    normalizeText
  };

  // src/shared/mount.js
  var MOUNT_PRESETS = {
    racing: {
      waitFor: ["#racingMainContainer"],
      target: "#racingMainContainer",
      position: "before"
    },
    gym: {
      waitFor: ["#gymroot"],
      target: "#gymroot",
      position: "prepend"
    },
    gymBar: {
      waitFor: ["#gymroot"],
      target: "#gymroot",
      position: "before"
    },
    stocksBar: {
      waitFor: ["#stockmarketroot"],
      target: "#stockmarketroot",
      position: "before"
    },
    disposalBar: {
      waitFor: ['[class*="disposal-root"]'],
      target: '[class*="disposal-root"]',
      position: "before"
    },
    contentTitle: {
      waitFor: [".content-title", ".body > .content-title", "div.content-title"],
      target: ".content-title",
      position: "after"
    }
  };
  function resolveMountConfig(mount2) {
    if (!mount2) {
      return MOUNT_PRESETS.contentTitle;
    }
    if (typeof mount2 === "string") {
      if (mount2 === "page") {
        return MOUNT_PRESETS.contentTitle;
      }
      return MOUNT_PRESETS[mount2] ?? MOUNT_PRESETS.contentTitle;
    }
    return mount2;
  }
  function findMountTarget(config) {
    const pageReady = config.waitFor.some((selector) => document.querySelector(selector));
    if (!pageReady) {
      return null;
    }
    return document.querySelector(config.target);
  }
  function insertAt(target, element, position) {
    switch (position) {
      case "before":
        target.insertAdjacentElement("beforebegin", element);
        break;
      case "after":
        target.insertAdjacentElement("afterend", element);
        break;
      case "prepend":
        target.prepend(element);
        break;
      case "append":
        target.append(element);
        break;
    }
  }
  function isMountedAt(element, target, position) {
    if (!element.isConnected) {
      return false;
    }
    switch (position) {
      case "before":
        return element.nextElementSibling === target;
      case "after":
        return element.previousElementSibling === target;
      case "prepend":
        return target.firstElementChild === element;
      case "append":
        return target.lastElementChild === element;
      default:
        return false;
    }
  }
  function mountElement(config, element) {
    const target = findMountTarget(config);
    if (!target) {
      return false;
    }
    if (isMountedAt(element, target, config.position)) {
      return true;
    }
    insertAt(target, element, config.position);
    return true;
  }
  function watchMount(config, getElement) {
    let stopped = false;
    const start = Date.now();
    const timeoutMs = 15e3;
    const tryMount = () => {
      if (stopped) {
        return;
      }
      const element = getElement();
      mountElement(config, element);
    };
    const poll = window.setInterval(() => {
      tryMount();
      if (findMountTarget(config) || Date.now() - start > timeoutMs) {
        window.clearInterval(poll);
      }
    }, 250);
    const observer = new MutationObserver((mutations) => {
      const onlyOwnChanges = mutations.every((mutation) => {
        const node = mutation.target;
        return node instanceof HTMLElement && node.closest(".hf-torn");
      });
      if (!onlyOwnChanges) {
        tryMount();
      }
    });
    observer.observe(document.body, { childList: true, subtree: true });
    tryMount();
    return () => {
      stopped = true;
      window.clearInterval(poll);
      observer.disconnect();
    };
  }
  var mount = {
    MOUNT_PRESETS,
    resolveMountConfig,
    findMountTarget,
    insertAt,
    isMountedAt,
    mountElement,
    watchMount
  };

  // src/shared/api.js
  var API_BASE = "https://api.torn.com/v2";
  var SETTINGS_KEY = "hf.torn.settings";
  function loadSettings() {
    try {
      const raw = GM_getValue(SETTINGS_KEY, "{}");
      const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
      return {
        apiKey: String(parsed?.apiKey ?? "").trim()
      };
    } catch {
      return { apiKey: "" };
    }
  }
  function saveSettings(patch) {
    const current = loadSettings();
    GM_setValue(SETTINGS_KEY, JSON.stringify({ ...current, ...patch }));
  }
  function parseTornError(json) {
    if (!json || typeof json !== "object" || !("error" in json)) {
      return null;
    }
    const err = (
      /** @type {{ error?: unknown }} */
      json.error
    );
    if (typeof err === "string") {
      return new Error(err);
    }
    if (err && typeof err === "object") {
      const detail = (
        /** @type {{ error?: string, message?: string, code?: number }} */
        err
      );
      return new Error(detail.error || detail.message || `Torn API error (${detail.code ?? "unknown"})`);
    }
    return new Error("Torn API error");
  }
  function tornGet(path, params, apiKey) {
    const url = new URL(`${API_BASE}/${path.replace(/^\//, "")}`);
    url.searchParams.set("key", apiKey);
    for (const [key, value] of Object.entries(params ?? {})) {
      if (value !== void 0 && value !== "") {
        url.searchParams.set(key, String(value));
      }
    }
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: "GET",
        url: url.toString(),
        timeout: 2e4,
        onload: (response) => {
          try {
            const json = JSON.parse(response.responseText || "{}");
            const apiError = parseTornError(json);
            if (apiError) {
              reject(apiError);
              return;
            }
            resolve(json);
          } catch (error) {
            reject(error instanceof Error ? error : new Error("Invalid API response"));
          }
        },
        onerror: () => reject(new Error("Network error")),
        ontimeout: () => reject(new Error("API request timed out"))
      });
    });
  }
  var api = {
    loadSettings,
    saveSettings,
    parseTornError,
    tornGet,
    SETTINGS_KEY
  };

  // src/shared/ui.js
  function panelCollapsedKey(panelId) {
    return `panel.${panelId}.collapsed`;
  }
  function readPanelCollapsed(panelId, legacyKeys = []) {
    const stored = getLocal(panelCollapsedKey(panelId), void 0);
    if (stored === true || stored === "true") {
      return true;
    }
    if (stored === false || stored === "false") {
      return false;
    }
    for (const key of legacyKeys) {
      const raw = localStorage.getItem(key);
      if (raw === "true") {
        setLocal(panelCollapsedKey(panelId), true);
        return true;
      }
      if (raw === "false") {
        setLocal(panelCollapsedKey(panelId), false);
        return false;
      }
    }
    return false;
  }
  var PANELS = /* @__PURE__ */ new Map();
  function createPanel(options) {
    const existing = PANELS.get(options.id);
    if (existing?.element.isConnected) {
      return existing;
    }
    if (existing) {
      PANELS.delete(options.id);
    }
    injectStyles();
    const mountOption = options.mount ?? "racing";
    const isFixed = mountOption === "fixed";
    const mountConfig = isFixed ? null : resolveMountConfig(mountOption);
    const pageBody = options.pageBody ?? "cap";
    const growPageBody = !isFixed && pageBody === "grow";
    const root = document.createElement("section");
    root.id = options.id;
    root.className = isFixed ? "hf-torn hf-panel hf-panel--fixed" : `hf-torn hf-panel hf-panel--page${growPageBody ? " hf-panel--grow" : ""}`;
    applyPanelLayout(root, isFixed, options.position ?? "bottom-right");
    const header = document.createElement("div");
    header.className = "hf-panel-header";
    header.style.cssText = `
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 13px;
    cursor: pointer;
    user-select: none;
  `;
    const titleWrap = document.createElement("div");
    titleWrap.style.display = "flex";
    titleWrap.style.alignItems = "center";
    titleWrap.style.gap = "10px";
    titleWrap.style.flex = "1";
    titleWrap.style.minWidth = "0";
    if (options.badge) {
      const badge = document.createElement("span");
      badge.className = "hf-badge";
      badge.textContent = options.badge;
      titleWrap.appendChild(badge);
    } else if (options.title) {
      const title = document.createElement("div");
      title.textContent = options.title;
      title.style.fontWeight = "700";
      title.style.fontSize = "13px";
      title.style.color = "var(--hf-accent-text)";
      titleWrap.appendChild(title);
    }
    const right = document.createElement("div");
    right.className = "hf-panel-right";
    right.style.cssText = `
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    flex-shrink: 0;
  `;
    const subtitle = document.createElement("div");
    subtitle.className = "hf-muted hf-panel-subtitle";
    subtitle.style.cssText = `
    font-size: 11px;
    max-width: min(280px, 40vw);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
  `;
    const gear = document.createElement("button");
    gear.type = "button";
    gear.className = "hf-panel-gear";
    gear.title = "Settings";
    gear.innerHTML = "&#9881;";
    gear.style.cssText = `
    font-size: 15px;
    color: var(--hf-text-muted);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0 4px;
    line-height: 1;
    flex-shrink: 0;
    position: relative;
    z-index: 2;
  `;
    const openSettings2 = (event) => {
      event.preventDefault();
      event.stopPropagation();
      options.onSettings?.();
    };
    gear.addEventListener("mousedown", openSettings2);
    gear.addEventListener("click", openSettings2);
    const toggle = document.createElement("span");
    toggle.className = "hf-panel-chev";
    toggle.textContent = "\u25BC";
    toggle.style.cssText = "font-size:12px;color:var(--hf-text-muted);transition:transform .2s;flex-shrink:0;";
    right.appendChild(subtitle);
    if (options.onSettings) {
      right.appendChild(gear);
    }
    right.appendChild(toggle);
    header.appendChild(titleWrap);
    header.appendChild(right);
    const tabBar = document.createElement("div");
    tabBar.className = "hf-panel-tabs";
    tabBar.style.cssText = `
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px 8px;
  `;
    const body = document.createElement("div");
    body.className = "hf-panel-body";
    if (growPageBody) {
      body.style.maxHeight = "none";
      body.style.overflow = "visible";
    }
    root.appendChild(header);
    if (options.tabs.length > 1) {
      root.appendChild(tabBar);
    }
    root.appendChild(body);
    let collapsed = readPanelCollapsed(options.id, options.collapsedLegacyKeys);
    let activeTabId = options.tabs[0]?.id ?? "";
    const tabButtons = /* @__PURE__ */ new Map();
    const setCollapsed = (value) => {
      collapsed = value;
      const hideBody = collapsed;
      if (options.tabs.length > 1) {
        tabBar.style.display = collapsed ? "none" : "flex";
      }
      body.style.display = hideBody ? "none" : "block";
      toggle.style.transform = collapsed ? "rotate(-90deg)" : "";
      root.classList.toggle("is-collapsed", collapsed);
      setLocal(panelCollapsedKey(options.id), value);
    };
    const renderActiveTab = async () => {
      const tab = options.tabs.find((item) => item.id === activeTabId);
      body.replaceChildren();
      if (!tab) {
        body.textContent = "No tab selected.";
        return;
      }
      const content = await tab.render();
      body.appendChild(content);
    };
    const setTab = (id) => {
      activeTabId = id;
      tabButtons.forEach((btn, tabId) => {
        btn.classList.toggle("is-active", tabId === id);
      });
      renderActiveTab();
    };
    if (options.tabs.length > 1) {
      for (const tab of options.tabs) {
        const btn = document.createElement("button");
        btn.type = "button";
        btn.className = "hf-btn";
        btn.textContent = tab.label;
        btn.addEventListener("click", (event) => {
          event.stopPropagation();
          setTab(tab.id);
        });
        tabButtons.set(tab.id, btn);
        tabBar.appendChild(btn);
      }
    }
    header.addEventListener("click", (event) => {
      if (
        /** @type {Element} */
        event.target.closest(".hf-panel-gear")
      ) {
        return;
      }
      if (
        /** @type {Element} */
        event.target.closest("button")
      ) {
        return;
      }
      setCollapsed(!collapsed);
    });
    gear.addEventListener("mouseenter", () => {
      gear.style.color = "#fff";
    });
    gear.addEventListener("mouseleave", () => {
      gear.style.color = "var(--hf-text-muted)";
    });
    setTab(activeTabId);
    setCollapsed(collapsed);
    let stopWatching = null;
    const ensureMounted = () => {
      if (isFixed) {
        if (root.parentElement !== document.body) {
          document.body.appendChild(root);
        }
        return;
      }
      if (mountConfig) {
        mountElement(mountConfig, root);
      }
    };
    if (isFixed) {
      ensureMounted();
    } else if (mountConfig) {
      stopWatching = watchMount(mountConfig, () => root);
    }
    const panel = {
      element: root,
      setTab,
      refresh: () => {
        if (options.getSubtitle) {
          subtitle.textContent = options.getSubtitle() ?? "";
        }
        renderActiveTab();
      },
      setSubtitle: (text) => {
        subtitle.textContent = text;
      },
      ensureMounted,
      destroy: () => {
        stopWatching?.();
        root.remove();
        PANELS.delete(options.id);
      }
    };
    if (options.getSubtitle) {
      subtitle.textContent = options.getSubtitle() ?? "";
    }
    PANELS.set(options.id, panel);
    return panel;
  }
  function applyPanelLayout(el, isFixed, position) {
    if (!isFixed) {
      el.style.cssText = `
      position: static;
      width: 100%;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    `;
      return;
    }
    el.style.cssText = `
    position: fixed;
    z-index: 9999;
    width: min(420px, calc(100vw - 24px));
    max-height: min(70vh, 560px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
  `;
    applyFixedPosition(el, position);
  }
  function applyFixedPosition(el, position) {
    el.style.top = "";
    el.style.right = "";
    el.style.bottom = "";
    el.style.left = "";
    switch (position) {
      case "top-right":
        el.style.top = "12px";
        el.style.right = "12px";
        break;
      case "bottom-left":
        el.style.bottom = "12px";
        el.style.left = "12px";
        break;
      case "bottom-right":
      default:
        el.style.bottom = "12px";
        el.style.right = "12px";
        break;
    }
  }
  function emptyState(message) {
    const div = document.createElement("div");
    div.className = "hf-muted";
    div.textContent = message;
    return div;
  }
  var ui = {
    createPanel,
    emptyState
  };

  // src/shared/percent.js
  function parsePercent(raw, fallback = 0) {
    if (raw === null || raw === void 0 || raw === "") {
      return fallback;
    }
    if (typeof raw === "number") {
      return Number.isFinite(raw) ? raw : fallback;
    }
    const cleaned = String(raw).trim().replace("%", "").replace(",", ".");
    const value = parseFloat(cleaned);
    return Number.isFinite(value) ? value : fallback;
  }
  function weightToPercent(weight) {
    return Math.round(weight * 1e3) / 10;
  }
  function weightSharePercent(weight, weights) {
    const sum = Object.values(weights).reduce((total, w) => total + (w > 0 ? w : 0), 0);
    if (sum <= 0 || weight <= 0) {
      return 0;
    }
    return weight / sum * 100;
  }
  function percentToWeight(raw, fallback = 0) {
    const pct = parsePercent(raw, fallback * 100);
    return pct / 100;
  }
  function weightsToShares(weights) {
    const sum = Object.values(weights).reduce((total, w) => total + (w > 0 ? w : 0), 0);
    if (sum <= 0) {
      return {};
    }
    const out = {};
    for (const [stat, w] of Object.entries(weights)) {
      out[stat] = w > 0 ? w / sum * 100 : 0;
    }
    return out;
  }
  function normalizeWeightsToShares(weights) {
    const sum = Object.values(weights).reduce((total, w) => total + (w > 0 ? w : 0), 0);
    if (sum <= 0) {
      return weights;
    }
    const out = {};
    for (const [stat, w] of Object.entries(weights)) {
      out[stat] = w > 0 ? w / sum * 100 : 0;
    }
    return out;
  }
  function parseShareInputs(inputsByStat) {
    const raw = {};
    let sum = 0;
    for (const [stat, value] of Object.entries(inputsByStat)) {
      const pct = Math.max(0, parsePercent(value, 0));
      raw[stat] = pct;
      sum += pct;
    }
    if (sum <= 0) {
      return raw;
    }
    const out = {};
    for (const [stat, pct] of Object.entries(raw)) {
      out[stat] = pct > 0 ? pct / sum * 100 : 0;
    }
    return out;
  }
  function bonusesToMultiplier(bonuses) {
    const f = parsePercent(bonuses?.faction, 0);
    const e = parsePercent(bonuses?.education, 0);
    const p = parsePercent(bonuses?.property, 0);
    return (1 + f / 100) * (1 + e / 100) * (1 + p / 100);
  }
  function multiplierToTotalPercent(multiplier) {
    if (!Number.isFinite(multiplier) || multiplier <= 1) {
      return 0;
    }
    return Math.round((multiplier - 1) * 1e3) / 10;
  }
  function formatPercent(pct, digits = 1) {
    const rounded = Math.round(pct * Math.pow(10, digits)) / Math.pow(10, digits);
    const text = Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(digits);
    return `${text}%`;
  }
  function formatWeightSummary(weights, shortLabels) {
    const parts = Object.entries(weights).filter(([, w]) => w > 0).sort((a, b) => b[1] - a[1]).map(([stat, w]) => `${shortLabels[stat] ?? stat} ${formatPercent(weightSharePercent(w, weights), 0)}`);
    return parts.join(" \xB7 ");
  }
  var percent = {
    parsePercent,
    weightToPercent,
    weightSharePercent,
    percentToWeight,
    weightsToShares,
    normalizeWeightsToShares,
    parseShareInputs,
    bonusesToMultiplier,
    multiplierToTotalPercent,
    formatPercent,
    formatWeightSummary
  };

  // src/shared/index.js
  var HF = {
    version: "0.4.0",
    theme,
    storage,
    dom,
    mount,
    api,
    ui,
    percent
  };

  // src/panic/config.js
  var LS_PANIC = "alfa_panic_navbar_config";
  var SS_PENDING = "alfa_panic_nav_pending";
  var STOCKS_PATH = "/page.php?sid=stocks";
  var DEFAULT_CONFIG = {
    preferSmartStockVault: true,
    targetStock: "",
    vaultStocks: [],
    lockedStocks: []
  };
  var DEFAULT_VAULT_FALLBACK = { stocks: [], lockedStocks: [] };
  function loadJson(key, fallback) {
    try {
      const raw = localStorage.getItem(key);
      if (!raw) return { ...fallback };
      const o = JSON.parse(raw);
      return { ...fallback, ...o };
    } catch {
      return { ...fallback };
    }
  }
  function savePanicConfig(cfg) {
    try {
      localStorage.setItem(LS_PANIC, JSON.stringify(cfg));
    } catch (e) {
      console.error("[Smart Panic] save config failed", e);
    }
  }
  function getPanicConfig() {
    return loadJson(LS_PANIC, DEFAULT_CONFIG);
  }
  function getSsvVault() {
    return loadJson("alfa_vault_config", DEFAULT_VAULT_FALLBACK);
  }
  function getSsvGamble() {
    return loadJson("alfa_gamble_config", { targetStock: "" });
  }
  function resolveTargetSymbol(gambleTarget, vaultStocks) {
    const list = (Array.isArray(vaultStocks) ? vaultStocks : []).map((s) => String(s).toUpperCase());
    const gt = String(gambleTarget || "").toUpperCase();
    if (gt && list.includes(gt)) return gt;
    return String(list[0] || "").toUpperCase();
  }
  function getEffectiveVaultAndTarget() {
    const panic = getPanicConfig();
    if (panic.preferSmartStockVault) {
      const v = getSsvVault();
      const g = getSsvGamble();
      const stocks2 = (Array.isArray(v.stocks) ? v.stocks : []).map((s) => String(s).toUpperCase());
      const lockedStocks2 = (Array.isArray(v.lockedStocks) ? v.lockedStocks : []).map((s) => String(s).toUpperCase());
      const target2 = resolveTargetSymbol(g.targetStock || "", stocks2);
      return { vaultStocks: stocks2, lockedStocks: lockedStocks2, targetStock: target2, source: "ssv" };
    }
    const stocks = (Array.isArray(panic.vaultStocks) ? panic.vaultStocks : []).map((s) => String(s).toUpperCase());
    const lockedStocks = (Array.isArray(panic.lockedStocks) ? panic.lockedStocks : []).map((s) => String(s).toUpperCase());
    const target = resolveTargetSymbol(panic.targetStock || "", stocks);
    return { vaultStocks: stocks, lockedStocks, targetStock: target, source: "local" };
  }
  function isStocksPage() {
    return /[?&]sid=stocks\b/.test(location.search || "");
  }
  function stocksUrl() {
    return `https://www.torn.com${STOCKS_PATH}`;
  }
  function parseSymbolsInput(str) {
    if (!str || typeof str !== "string") return [];
    return str.split(/[\s,]+/).map((s) => s.trim().toUpperCase()).filter(Boolean);
  }

  // src/panic/money.js
  function parseTornNumber(val) {
    if (typeof val !== "string") return 0;
    val = val.trim().toLowerCase();
    if (!val) return 0;
    if (val.endsWith("k")) return parseFloat(val.replace("k", "")) * 1e3;
    if (val.endsWith("m")) return parseFloat(val.replace("m", "")) * 1e6;
    if (val.endsWith("b")) return parseFloat(val.replace("b", "")) * 1e9;
    return parseFloat(val.replace(/,/g, "")) || 0;
  }
  function getMoneyFromNavbar() {
    const el = document.getElementById("user-money");
    if (!el) return null;
    const dm = el.getAttribute("data-money");
    if (dm !== null && dm !== "") {
      const n = parseFloat(dm);
      if (!Number.isNaN(n)) return n;
    }
    const t = el.textContent || "";
    if (t) {
      const n = parseTornNumber(t.replace(/^\$/, ""));
      if (!Number.isNaN(n) && n >= 0) return n;
    }
    return null;
  }
  async function getMoneyApiFallback() {
    const key = localStorage.getItem("alfa_vault_apikey");
    if (!key) return null;
    try {
      const res = await fetch(`https://api.torn.com/v2/user/money?key=${encodeURIComponent(key)}&ts=${Date.now()}`);
      const data = await res.json();
      if (data.error) return null;
      if (data.money && typeof data.money.wallet === "number") return data.money.wallet;
    } catch (e) {
      console.warn("[Smart Panic] API money fallback failed", e);
    }
    return null;
  }
  async function getCashForPanic() {
    const dom2 = getMoneyFromNavbar();
    if (dom2 !== null && dom2 !== void 0 && !Number.isNaN(dom2)) return dom2;
    const api2 = await getMoneyApiFallback();
    return api2 !== null && api2 !== void 0 ? api2 : 0;
  }
  function formatMoneyWhole(amount) {
    return `$${Math.round(Number(amount) || 0).toLocaleString("en-US", {
      maximumFractionDigits: 0,
      minimumFractionDigits: 0
    })}`;
  }
  function tryUpdateGambleCashFromNavbar() {
    const el = document.getElementById("gamble-cash-value");
    if (!el || !document.getElementById("user-money")) return false;
    const domCash = getMoneyFromNavbar();
    if (domCash === null || domCash === void 0 || Number.isNaN(domCash)) return false;
    el.textContent = formatMoneyWhole(domCash);
    return true;
  }
  async function tryUpdateGambleCashWithApiFallback() {
    const el = document.getElementById("gamble-cash-value");
    if (!el) return;
    const w = await getMoneyApiFallback();
    if (w !== null && w !== void 0 && !Number.isNaN(w)) el.textContent = formatMoneyWhole(w);
  }
  function refreshGambleCashAfterPanicTrade() {
    tryUpdateGambleCashFromNavbar();
    setTimeout(() => tryUpdateGambleCashFromNavbar(), 400);
    setTimeout(() => tryUpdateGambleCashFromNavbar(), 800);
    setTimeout(() => {
      if (!tryUpdateGambleCashFromNavbar()) void tryUpdateGambleCashWithApiFallback();
    }, 1400);
  }

  // src/panic/stocks-page.js
  function scanStocksFromDom() {
    const map = /* @__PURE__ */ new Map();
    document.querySelectorAll('ul[class^="stock_"]').forEach((ul) => {
      const img = ul.querySelector('img[src*="logos/"]');
      if (!img) return;
      const src = img.getAttribute("src") || "";
      const m = src.match(/logos\/([^/.]+)\.svg/i);
      if (!m) return;
      const sym = m[1].toUpperCase();
      const stockId = ul.getAttribute("id");
      const priceEl = ul.querySelector('div[class^="price_"]');
      const priceTxt = priceEl ? priceEl.textContent : "";
      const price = parseFloat(String(priceTxt).replace(/,/g, "")) || 0;
      if (stockId && sym) map.set(sym, { stockId, price });
    });
    return map;
  }
  function waitForStockRow(symbol, maxMs = 12e3) {
    const sym = String(symbol || "").toUpperCase();
    return new Promise((resolve, reject) => {
      const t0 = Date.now();
      const tick = () => {
        const row = scanStocksFromDom().get(sym);
        if (row && row.price > 0 && row.stockId) {
          resolve(row);
          return;
        }
        if (Date.now() - t0 > maxMs) {
          reject(new Error("Stock list not ready or symbol not found"));
          return;
        }
        setTimeout(tick, 200);
      };
      tick();
    });
  }

  // src/panic/trade.js
  function getRFC() {
    const c = document.cookie.match(/rfc_v=([^;]+)/);
    return c ? c[1] : "";
  }
  async function postBuyShares(stockId, amount) {
    const rfc = getRFC();
    const url = `https://www.torn.com/page.php?sid=StockMarket&step=buyShares&rfcv=${encodeURIComponent(rfc)}`;
    const body = new URLSearchParams();
    body.set("stockId", stockId);
    body.set("amount", String(amount));
    const res = await fetch(url, {
      method: "POST",
      credentials: "include",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "X-Requested-With": "XMLHttpRequest"
      },
      body: body.toString()
    });
    const text = await res.text();
    let data;
    try {
      data = JSON.parse(text);
    } catch {
      throw new Error("Invalid response from Torn");
    }
    if (!data.success) throw new Error(data.message || "Trade failed");
    return data;
  }
  async function runPanic(btn, setStatus, openSettings2) {
    const { vaultStocks, lockedStocks, targetStock: sym } = getEffectiveVaultAndTarget();
    if (!sym || !vaultStocks.includes(sym)) {
      setStatus("Configure target stock (Settings)", true);
      openSettings2();
      return;
    }
    if (lockedStocks.includes(sym)) {
      setStatus("Target stock is locked", true);
      return;
    }
    if (!isStocksPage()) {
      try {
        sessionStorage.setItem(SS_PENDING, "1");
      } catch {
      }
      setStatus("Opening stocks\u2026 tap Panic again", false);
      window.location.href = stocksUrl();
      return;
    }
    if (btn) {
      btn.disabled = true;
      btn.classList.add("is-busy");
    }
    setStatus("Working\u2026", false);
    try {
      const cash = await getCashForPanic();
      const row = await waitForStockRow(sym);
      const shares = Math.floor(cash / row.price);
      if (shares <= 0) {
        setStatus("No cash to deposit", true);
        return;
      }
      await postBuyShares(row.stockId, shares);
      setStatus(`Deposited ${shares.toLocaleString()} shares`, false);
      refreshGambleCashAfterPanicTrade();
      try {
        sessionStorage.removeItem(SS_PENDING);
      } catch {
      }
    } catch (e) {
      console.error("[Smart Panic]", e);
      setStatus(e instanceof Error ? e.message : "Failed", true);
    } finally {
      if (btn) {
        btn.disabled = false;
        btn.classList.remove("is-busy");
      }
    }
  }

  // src/panic/settings.js
  function openSettings(setStatus) {
    const existing = document.querySelector(".hf-panic-settings-overlay");
    if (existing?.isConnected) return;
    existing?.remove();
    HF.theme.injectStyles();
    const panic = getPanicConfig();
    const overlay = document.createElement("div");
    overlay.className = "hf-torn hf-overlay hf-panic-settings-overlay";
    overlay.style.cssText = `
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(0, 0, 0, 0.62);
    backdrop-filter: blur(2px);
  `;
    const modal = document.createElement("div");
    modal.className = "hf-modal hf-torn hf-panic-settings-modal";
    modal.style.cssText = "width: min(420px, 94vw); max-height: 90vh; overflow-y: auto; padding: 18px;";
    modal.innerHTML = `
    <h2>
      Smart Panic settings
      <button type="button" class="hf-btn hf-panic-close" title="Close">\xD7</button>
    </h2>
    <div class="hf-panic-field hf-panic-check">
      <input type="checkbox" id="hf-panic-prefer-ssv" ${panic.preferSmartStockVault ? "checked" : ""}>
      <label for="hf-panic-prefer-ssv">
        Use Smart Stock Vault settings when available (vault list, locks, gamble target)
      </label>
    </div>
    <div class="hf-panic-field" id="hf-panic-standalone-fields">
      <label class="hf-label" for="hf-panic-vault-symbols">Vault symbols (standalone)</label>
      <input class="hf-input" type="text" id="hf-panic-vault-symbols" placeholder="e.g. MUN, SYM, TCI" autocomplete="off">
      <label class="hf-label" for="hf-panic-target" style="margin-top:12px">Target stock</label>
      <select class="hf-select" id="hf-panic-target"></select>
    </div>
    <div class="hf-panic-field hf-panic-hint" id="hf-panic-ssv-hint" hidden>
      Target and vault come from Smart Stock Vault. Configure there, or turn off the checkbox above.
    </div>
    <div class="hf-panic-actions">
      <button type="button" class="hf-btn hf-btn--save" id="hf-panic-save">Save</button>
      <button type="button" class="hf-btn" id="hf-panic-cancel">Cancel</button>
    </div>
  `;
    overlay.appendChild(modal);
    document.body.appendChild(overlay);
    overlay.addEventListener("click", (e) => {
      if (e.target === overlay) overlay.remove();
    });
    modal.addEventListener("click", (e) => e.stopPropagation());
    const preferEl = modal.querySelector("#hf-panic-prefer-ssv");
    const standaloneFields = modal.querySelector("#hf-panic-standalone-fields");
    const ssvHint = modal.querySelector("#hf-panic-ssv-hint");
    const vaultInput = modal.querySelector("#hf-panic-vault-symbols");
    const targetSel = modal.querySelector("#hf-panic-target");
    vaultInput.value = (panic.vaultStocks || []).join(", ");
    function refreshStandaloneVisibility() {
      const useSsv = preferEl.checked;
      standaloneFields.hidden = useSsv;
      ssvHint.hidden = !useSsv;
    }
    function fillTargetOptions() {
      const useSsv = preferEl.checked;
      const stocks = useSsv ? (getSsvVault().stocks || []).map((s) => String(s).toUpperCase()) : parseSymbolsInput(vaultInput.value);
      targetSel.innerHTML = "";
      const cur = useSsv ? resolveTargetSymbol(getSsvGamble().targetStock || "", stocks) : String(panic.targetStock || "").toUpperCase();
      stocks.forEach((sym) => {
        const opt = document.createElement("option");
        opt.value = sym;
        opt.textContent = sym;
        if (sym === cur) opt.selected = true;
        targetSel.appendChild(opt);
      });
      if (stocks.length === 0) {
        const opt = document.createElement("option");
        opt.value = "";
        opt.textContent = "Add symbols first";
        targetSel.appendChild(opt);
      }
    }
    preferEl.addEventListener("change", () => {
      refreshStandaloneVisibility();
      fillTargetOptions();
    });
    vaultInput.addEventListener("input", () => {
      if (!preferEl.checked) fillTargetOptions();
    });
    refreshStandaloneVisibility();
    fillTargetOptions();
    modal.querySelector(".hf-panic-close")?.addEventListener("click", () => overlay.remove());
    modal.querySelector("#hf-panic-cancel")?.addEventListener("click", () => overlay.remove());
    modal.querySelector("#hf-panic-save")?.addEventListener("click", () => {
      const vaultParsed = parseSymbolsInput(vaultInput.value);
      const next = {
        preferSmartStockVault: preferEl.checked,
        vaultStocks: preferEl.checked ? panic.vaultStocks || [] : vaultParsed,
        lockedStocks: panic.lockedStocks || []
      };
      if (preferEl.checked) {
        next.targetStock = panic.targetStock || "";
      } else {
        if (!vaultParsed.length) {
          alert("Add at least one vault symbol for standalone mode.");
          return;
        }
        const t = targetSel.value || "";
        next.targetStock = t && vaultParsed.includes(t) ? t : resolveTargetSymbol("", vaultParsed);
        next.vaultStocks = vaultParsed;
      }
      savePanicConfig({ ...DEFAULT_CONFIG, ...panic, ...next });
      overlay.remove();
      setStatus("Settings saved", false);
    });
  }

  // src/panic/navbar.js
  var ROOT_ID = "hf-panic-root";
  function isMobileLayout() {
    return window.matchMedia("(max-width: 784px)").matches;
  }
  function findEnergyBarLink() {
    const selectors = [
      'a.bar-link[class*="energy"]',
      'a[class*="bar-link"][class*="energy"]',
      'a[href*="sid=energy"]',
      'a[href*="/energy"]'
    ];
    for (const sel of selectors) {
      const el = document.querySelector(sel);
      if (el?.parentNode) return el;
    }
    return null;
  }
  function findInsertBeforeEnergy() {
    const energy = findEnergyBarLink();
    if (energy?.parentNode) return { parent: energy.parentNode, before: energy };
    const money = document.getElementById("user-money");
    if (money) {
      let p = money.parentElement;
      for (let i = 0; i < 6 && p; i++) {
        const g = p.querySelector('a.bar-link[class*="energy"], a[class*="energy"][class*="bar-link"]');
        if (g?.parentNode) return { parent: g.parentNode, before: g };
        p = p.parentElement;
      }
      if (money.parentNode) return { parent: money.parentNode, before: money.nextElementSibling };
    }
    return null;
  }
  function findMobileHeaderRow() {
    const money = document.getElementById("user-money");
    if (!money?.parentNode) return null;
    let p = money;
    for (let i = 0; i < 8 && p; i++) {
      const rect = p.getBoundingClientRect();
      if (p.tagName === "UL" || p.tagName === "DIV" || p.tagName === "NAV") {
        if (rect.width > 200) return p;
      }
      p = p.parentElement;
    }
    return money.parentElement;
  }
  function mountNavbar(setStatus, openSettingsFn) {
    if (document.getElementById(ROOT_ID)) return true;
    const root = document.createElement("div");
    root.id = ROOT_ID;
    root.className = "hf-torn hf-panic-root";
    root.dataset.hfPanic = "1";
    const stack = document.createElement("div");
    stack.className = "hf-panic-stack";
    const wrap = document.createElement("div");
    wrap.className = "hf-panic-btn-wrap";
    const btn = document.createElement("button");
    btn.type = "button";
    btn.className = "hf-panic-btn";
    btn.textContent = "Panic";
    const gear = document.createElement("button");
    gear.type = "button";
    gear.className = "hf-panic-gear";
    gear.setAttribute("aria-label", "Smart Panic settings");
    gear.innerHTML = "&#9881;";
    const status = document.createElement("div");
    status.className = "hf-panic-status";
    status.id = "hf-panic-status";
    btn.addEventListener("click", () => runPanic(btn, setStatus, openSettingsFn));
    gear.addEventListener("click", (e) => {
      e.preventDefault();
      e.stopPropagation();
      openSettingsFn();
    });
    wrap.appendChild(btn);
    wrap.appendChild(gear);
    stack.appendChild(wrap);
    stack.appendChild(status);
    root.appendChild(stack);
    if (isMobileLayout()) root.classList.add("hf-panic-root--mobile");
    const anchor = findInsertBeforeEnergy();
    if (anchor) {
      anchor.parent.insertBefore(root, anchor.before);
      return true;
    }
    if (isMobileLayout()) {
      const rowHost = findMobileHeaderRow();
      if (rowHost) {
        if (getComputedStyle(rowHost).display === "flex" || rowHost.querySelector(".bar-link")) {
          rowHost.appendChild(root);
        } else {
          const outer = document.createElement("div");
          outer.style.cssText = "display:flex;width:100%;justify-content:center;padding:4px 0;";
          outer.appendChild(root);
          rowHost.parentNode?.insertBefore(outer, rowHost.nextSibling);
        }
        return true;
      }
    }
    return false;
  }
  function createStatusSetter() {
    let timer = null;
    return function setStatus(msg, isError = false) {
      const el = document.getElementById("hf-panic-status");
      if (!el) return;
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      el.textContent = msg || "";
      el.classList.toggle("is-error", !!isError);
      el.classList.toggle("is-ok", !!msg && !isError);
      if (msg && !isError) {
        timer = window.setTimeout(() => {
          el.textContent = "";
          el.classList.remove("is-error", "is-ok");
          timer = null;
        }, 4e3);
      }
    };
  }

  // src/panic/styles.js
  var STYLE_ID2 = "hf-panic-styles";
  function injectPanicStyles() {
    if (document.getElementById(STYLE_ID2)) return;
    const style = document.createElement("style");
    style.id = STYLE_ID2;
    style.textContent = `
    .hf-panic-root {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      vertical-align: middle;
      box-sizing: border-box;
      flex: 1 1 0%;
      min-width: 0;
      width: 100%;
      max-width: none;
      margin: 0 4px;
      font-family: var(--hf-font);
    }

    .hf-panic-root.hf-panic-root--mobile {
      margin: 2px 6px;
    }

    .hf-panic-stack {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      width: 100%;
      box-sizing: border-box;
    }

    .hf-panic-btn-wrap {
      position: relative;
      width: 100%;
      box-sizing: border-box;
      flex-shrink: 0;
    }

    .hf-panic-btn {
      display: block;
      width: 100%;
      box-sizing: border-box;
      height: 33px;
      min-height: 33px;
      max-height: 33px;
      padding: 0 24px 0 10px;
      margin: 0;
      font: inherit;
      font-size: 12px;
      font-weight: 700;
      line-height: 31px;
      border-radius: 5px;
      border: 1px solid var(--hf-danger-border);
      background: var(--hf-danger-bg);
      color: var(--hf-danger);
      cursor: pointer;
      text-align: center;
      transition: transform 0.1s ease, background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
      transform: scale(1);
      transform-origin: center center;
    }

    .hf-panic-btn:hover,
    .hf-panic-btn:focus-visible {
      background: var(--hf-danger);
      border-color: var(--hf-danger);
      color: #fff;
      outline: none;
    }

    .hf-panic-btn:active:not(:disabled),
    .hf-panic-btn.is-busy {
      transform: scale(0.96);
    }

    .hf-panic-btn:disabled {
      opacity: 0.85;
      cursor: wait;
    }

    .hf-panic-gear {
      appearance: none;
      position: absolute;
      top: 50%;
      right: 7px;
      width: 16px;
      height: 16px;
      min-width: 16px;
      min-height: 16px;
      padding: 0;
      margin: 0;
      border: 0;
      border-radius: 50%;
      background: transparent;
      color: var(--hf-text-muted);
      cursor: pointer;
      font: inherit;
      font-size: 11px;
      line-height: 16px;
      text-align: center;
      z-index: 2;
      opacity: 0.8;
      transform: translateY(-50%);
      transition: color 0.15s ease, opacity 0.15s ease, transform 0.1s ease;
    }

    .hf-panic-gear:hover,
    .hf-panic-gear:focus-visible {
      color: var(--hf-accent-text);
      opacity: 1;
      outline: none;
    }

    .hf-panic-gear:active {
      transform: translateY(-50%) scale(0.9);
    }

    .hf-panic-status {
      font-size: 10px;
      line-height: 1.25;
      margin-top: 3px;
      height: 2.5em;
      min-height: 2.5em;
      max-height: 2.5em;
      overflow: hidden;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      word-break: break-word;
      box-sizing: border-box;
      color: var(--hf-text-muted);
    }

    .hf-panic-status.is-error {
      color: var(--hf-danger);
    }

    .hf-panic-status.is-ok {
      color: var(--hf-success);
    }

    .hf-panic-settings-overlay {
      z-index: 2147483640;
    }

    .hf-panic-settings-modal h2 {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      margin: 0 0 14px;
      font-size: 15px;
      color: var(--hf-accent-text);
    }

    .hf-panic-settings-modal .hf-panic-close {
      padding: 2px 8px;
      line-height: 1.2;
    }

    .hf-panic-field {
      margin-bottom: 14px;
    }

    .hf-panic-check {
      display: flex;
      align-items: flex-start;
      gap: 10px;
      min-height: 44px;
      font-size: 12px;
      line-height: 1.45;
      color: var(--hf-text);
    }

    .hf-panic-check input {
      width: 18px;
      height: 18px;
      margin-top: 2px;
      flex-shrink: 0;
      accent-color: var(--hf-accent);
    }

    .hf-panic-hint {
      font-size: 11px;
      color: var(--hf-text-muted);
      line-height: 1.45;
    }

    .hf-panic-actions {
      display: flex;
      gap: 8px;
      margin-top: 16px;
    }

    .hf-panic-actions .hf-btn {
      flex: 1;
      min-height: 40px;
      font-weight: 700;
    }

    .hf-panic-actions .hf-btn--save {
      background: var(--hf-success-bg);
      border-color: var(--hf-success-border);
      color: var(--hf-success);
    }

    .hf-panic-actions .hf-btn--save:hover {
      filter: brightness(1.12);
      color: var(--hf-success);
    }
  `;
    document.head.appendChild(style);
  }

  // src/panic/main.js
  function maybeShowPendingToast(setStatus) {
    if (!isStocksPage()) return;
    try {
      if (sessionStorage.getItem(SS_PENDING) === "1") {
        setStatus("Tap Panic to deposit all cash", false);
      }
    } catch {
    }
  }
  function init() {
    HF.theme.injectStyles();
    injectPanicStyles();
    const setStatus = createStatusSetter();
    const openSettingsModal = () => openSettings(setStatus);
    let tries = 0;
    const maxTries = 80;
    const timer = window.setInterval(() => {
      tries += 1;
      if (mountNavbar(setStatus, openSettingsModal) || tries >= maxTries) {
        clearInterval(timer);
        if (tries >= maxTries && !document.getElementById("hf-panic-root")) {
          console.warn("[Smart Panic] Could not find header anchor; retrying on DOM mutations");
          const obs = new MutationObserver(() => {
            if (mountNavbar(setStatus, openSettingsModal)) obs.disconnect();
          });
          obs.observe(document.body, { childList: true, subtree: true });
        }
      }
    }, 250);
    maybeShowPendingToast(setStatus);
    window.addEventListener("pageshow", () => {
      setTimeout(() => maybeShowPendingToast(setStatus), 300);
    });
    let resizeT;
    window.addEventListener("resize", () => {
      clearTimeout(resizeT);
      resizeT = window.setTimeout(() => {
        if (!document.getElementById("hf-panic-root")) {
          mountNavbar(setStatus, openSettingsModal);
        }
      }, 300);
    });
  }
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
})();