FI-Bypass Lite

A Tensor-only, IndexedDB-backed query/mget bypass with batch URL resolution, Library Link Assign, and a lightweight Items UI.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         FI-Bypass Lite
// @namespace    https://syncore.mooo.com/fi/
// @version      1.5.10
// @description  A Tensor-only, IndexedDB-backed query/mget bypass with batch URL resolution, Library Link Assign, and a lightweight Items UI.
// @author       TheFreeOne Guy
// @match        https://tensor.art/*
// @match        https://tensor.art
// @connect      api.tensor.art
// @connect      syncore.mooo.com
// @connect      api.telegram.org
// @connect      discord.com
// @connect      canary.discord.com
// @connect      ptb.discord.com
// @connect      discordapp.com
// @connect      localhost
// @connect      127.0.0.1
// @run-at       document-start
// @grant        unsafeWindow
// @grant        GM.cookie
// @grant        GM.xmlHttpRequest
// @grant        GM_xmlhttpRequest
// @grant        GM.registerMenuCommand
// @grant        GM.download
// @grant        GM.openInTab
// @grant        GM_registerMenuCommand
// @grant        GM_download
// @grant        GM_openInTab
// @noframes
// ==/UserScript==

(() => {
  'use strict';

  const PAGE = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
  const HOST = String(location.hostname || '').replace(/^www\./i, '').toLowerCase();
  if (HOST !== 'tensor.art') return;
  try { if (PAGE.top && PAGE.top !== PAGE) return; } catch { return; }
  if (PAGE.__fiBypassLiteInstalled) return;
  try { Object.defineProperty(PAGE, '__fiBypassLiteInstalled', { value: true, configurable: true }); }
  catch { PAGE.__fiBypassLiteInstalled = true; }

  const SCRIPT_NAME = 'FI-Bypass Lite';
  const SCRIPT_VERSION = '1.5.10';
  const CONFIG_URL = 'https://syncore.mooo.com/host/config/main.json';
  const TENSOR_API_ORIGIN = 'https://api.tensor.art';
  const API_URL_IMAGE = 'https://api.tensor.art/works/v1/generation/image/download';
  const API_URL_VIDEO = 'https://api.tensor.art/works/v1/generation/video/download';
  const TASK_QUERY_PATH = '/works/v1/works/tasks/query';
  const MGET_TASK_PATH = '/works/v1/works/mget_task';
  const DIRECT_TASK_PATH = '/works/v1/works/task';
  const TASKS_PATH = '/works/v1/works/tasks';
  const LIBRARY_ENTRY_PREFIX = '/library-web/v1/entry/';
  const DB_NAME = 'FIBypassLite';
  const DB_VERSION = 2;
  const FI_BRIDGE_BOOT_KEY = '__fiBridgeBootPreferenceV1';
  const FI_BRIDGE_BOOT_MARKER = '__FI_BRIDGE_BOOT_PREFERENCE__';
  const FI_BRIDGE_RESOLVE_REQUEST_EVENT = 'fi:bridge-resolve-request';
  const FI_BRIDGE_RESOLVE_RESPONSE_EVENT = 'fi:bridge-resolve-response';
  const FI_BRIDGE_RESOLVE_MAX_ITEMS = 30;
  const FI_BRIDGE_RESOLVE_TIMEOUT_MS = 15_000;
  const SETTINGS_KEY = 'settings';
  const CONFIG_KEY = 'remote-config';
  const CONFIG_META_KEY = 'remote-config-meta';
  const ANNOUNCEMENT_STATE_KEY = 'remote-announcement-state';
  const SIGNED_URL_SAFETY_MS = 30_000;
  const SIGNED_URL_INTERCEPT_BUFFER_MS = 120_000;
  const TASK_FOLLOWUP_IDENTITY_GRACE_MS = 5 * 60_000;
  const FI_HOST_HEALTH_FRESH_MS = 90_000;

  function fiBridgeNormalizeBootPreference(value) {
    if (!value || typeof value !== 'object') return null;
    const primary = String(value.primary || '').toLowerCase();
    return {
      enabled: value.enabled === true,
      primary: ['auto','pro','lite'].includes(primary) ? primary : 'auto',
      updatedAt: Number(value.updatedAt || 0) || 0
    };
  }

  function fiBridgeBootStorages() {
    const storages = [];
    for (const owner of [PAGE, typeof window !== 'undefined' ? window : null]) {
      try {
        const storage = owner?.localStorage;
        if (storage && !storages.includes(storage)) storages.push(storage);
      } catch {}
    }
    return storages;
  }

  function fiBridgePublishBootPreference(value) {
    const normalized = fiBridgeNormalizeBootPreference(value);
    if (!normalized) return null;
    try { PAGE[FI_BRIDGE_BOOT_MARKER] = Object.freeze({ ...normalized }); } catch {}
    return normalized;
  }

  function fiBridgeReadBootPreference() {
    const candidates = [];
    try {
      const marker = fiBridgeNormalizeBootPreference(PAGE?.[FI_BRIDGE_BOOT_MARKER]);
      if (marker) candidates.push(marker);
    } catch {}
    for (const storage of fiBridgeBootStorages()) {
      try {
        const parsed = fiBridgeNormalizeBootPreference(JSON.parse(storage.getItem(FI_BRIDGE_BOOT_KEY) || 'null'));
        if (parsed) candidates.push(parsed);
      } catch {}
    }
    if (!candidates.length) return null;
    const selected = candidates.sort((left, right) => Number(right.updatedAt || 0) - Number(left.updatedAt || 0))[0];
    return fiBridgePublishBootPreference(selected);
  }

  function fiBridgeWriteBootPreference(enabled, primary = 'auto', updatedAt = Date.now()) {
    const normalized = ['auto','pro','lite'].includes(String(primary || '').toLowerCase()) ? String(primary).toLowerCase() : 'auto';
    const value = { enabled: !!enabled, primary: normalized, updatedAt: Number(updatedAt || 0) || Date.now() };
    const serialized = JSON.stringify(value);
    for (const storage of fiBridgeBootStorages()) {
      try { storage.setItem(FI_BRIDGE_BOOT_KEY, serialized); } catch {}
    }
    return fiBridgePublishBootPreference(value);
  }

  const DEFAULT_SETTINGS = Object.freeze({
    interceptEnabled: true,
    fiBridgeEnabled: false,
    fiBridgePrimary: 'auto',
    fiBridgeSyncItems: true,
    fiBridgeSyncSettings: false,
    fiBridgeAutoSyncOnLoad: true,
    fiHostEnabled: false,
    fiHostPairing: '',
    fiHostAutoStore: true,
    fiHostUseLocalUrls: true,
    fiHostRewriteSiteMedia: false,
    fiHostSyncSettings: true,
    accountSwitcherEnabled: false,
    tensorCredentialVaultSyncEnabled: false,
    tensorCookieVaultSyncEnabled: false,
    tensorVaultLastCookieSyncAt: 0,
    rewriteQuerySize: true,
    querySize: 10,
    resolveMissingUrls: true,
    awaitFetchBackfill: true,
    resolveOnLoad: true,
    removeExpiredTasksOnLoad: true,
    removeExpiredTaskItemsOnLoad: true,
    libraryLinkAssign: true,
    preferLibraryUrls: true,
    libraryAssignToTaskStore: true,
    librarySkipDownloadRefresh: true,
    libraryRefreshFromList: true,
    libraryUseThumbnailFallback: true,
    downloadTransport: 'auto',
    reuseCapturedDownloadHeaders: false,
    cachingEnabled: true,
    cacheDays: 7,
    maxResolvePerResponse: 30,
    maxStoredTasks: 400,
    maxStoredItems: 800,
    maxStoredUrls: 1200,
    maxStoredLibraryLinks: 1600,
    maxVisibleItems: 120,
    onLoadResolveLimit: 120,
    itemsLayout: 'grid',
    cardThumbnails: false,
    remoteUpdateEnabled: true,
    remoteAnnouncementsEnabled: true,
    remoteAnnouncementNoticesEnabled: true,
    remoteConfigDelayMs: 8000,
    remoteConfigTtlMs: 3_600_000,
    debugLogs: false,
    diagnosticsEnabled: true,
    diagnosticsConsole: true,
    diagnosticsMaxEntries: 200,
    telegramDeliveryEnabled: false,
    telegramBotToken: '',
    telegramChatId: '',
    telegramApiBase: 'https://api.telegram.org',
    discordDeliveryEnabled: false,
    discordWebhookUrl: '',
    deliverySuccessEnabled: true,
    deliveryFailureEnabled: true,
    deliveryIncludeMedia: true,
    deliveryIncludeCaption: true,
    deliveryMaxCaption: 900,
    requestHeaders: {
      'X-Request-Package-Sign-Version': '0.0.1',
      'X-Request-Package-Id': '3000',
      'X-Request-Timestamp': '1766394106674',
      'X-Request-Sign': 'NDc3MTZiZDc2MDlhOWJlMTQ1YTMxNjgwYzE4NzljMDRjNTQ3ZTgzMjUyNjk1YTE5YzkzYzdhOGNmYWJiYTI1NA==',
      'X-Request-Lang': 'en-US',
      'X-Request-Sign-Type': 'HMAC_SHA256',
      'X-Request-Sign-Version': 'v1'
    }
  });

  const state = {
    settings: clone(DEFAULT_SETTINGS),
    tasks: new Map(),
    items: new Map(),
    downloads: new Map(),
    libraryLinks: new Map(),
    libraryEntries: new Map(),
    endpointHeaders: new Map(),
    bridge: { networkOwner: null, lastSyncAt: 0, lastSource: '', importedTasks: 0, importedItems: 0, lastError: '' },
    host: { connected: false, enabled: false, checkedAt: 0, lastSeenAt: 0, origin: '', runtimeInstanceId: '', transportMode: 'websocket', error: '', inventory: new Map(), pending: new Map(), nextRevision: 0, pollRevision: 0, timer: null, healthTimer: null, flushTimer: null, flushInFlight: null, refreshInFlight: null, stored: 0, reused: 0, failed: 0 },
    lastToken: '',
    lastTokenAt: 0,
    currentAccountId: '',
    db: null,
    dbReady: false,
    update: null,
    announcements: [],
    announcementState: { readIds: [], updatedAt: 0 },
    announcementStateUpdatedAt: 0,
    config: null,
    configMeta: null,
    settingsUpdatedAt: 0,
    configUpdatedAt: 0,
    configMetaUpdatedAt: 0,
    ui: null,
    activeTab: 'items',
    visibleCount: 40,
    itemFilter: 'all',
    itemSearch: '',
    diagnostics: [],
    diagnosticSequence: 0,
    deliveryDedupe: new Set(),
    telegramAccessRunId: 0,
    telegramAccessStatus: { phase: 'idle', message: 'Enter a bot token, click Initialize, then send /access to that bot.' },
    previewReturnFocus: null,
    fetchInstalled: false,
    xhrInstalled: false,
    loadRan: false,
    loadWaitInstalled: false,
    remoteTimer: null,
    autoResolveTimer: null,
    autoResolveInFlight: null,
    announcementToast: null,
    announcementNotified: new Set(),
    pruneAt: 0,
    downloadTransportFallbackUntil: 0,
    stats: {
      queries: 0,
      taskResponses: 0,
      mgetResponses: 0,
      libraryResponses: 0,
      patchedResponses: 0,
      patchedItems: 0,
      resolvedUrls: 0,
      cacheHits: 0,
      failures: 0,
      expiredTasksPruned: 0,
      onLoadResolved: 0
      ,download405Fallbacks: 0
      ,gmDownloadRequests: 0
      ,libraryTaskAssignments: 0
      ,deliveryAttempts: 0
      ,deliverySent: 0
      ,deliveryFailures: 0
      ,diagnosticErrors: 0
      ,siteMediaRewrites: 0
    }
  };

  function clone(value) {
    try { return structuredClone(value); } catch {}
    try { return JSON.parse(JSON.stringify(value)); } catch {}
    return value;
  }

  const SENSITIVE_DIAGNOSTIC_KEYS = /^(?:authorization|cookie|token|botToken|telegramBotToken|telegramChatId|chat_id|discordWebhookUrl|webhook|secret|password|fiHostPairing|apiKey)$/i;

  function redactDiagnosticString(value) {
    let text = String(value ?? '');
    text = text.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/gi, 'Bearer [redacted]');
    text = text.replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]+\b/g, '[redacted-token]');
    text = text.replace(/\b\d{5,15}:[A-Za-z0-9_-]{20,160}\b/g, '[redacted-telegram-token]');
    text = text.replace(/(https?:\/\/(?:canary\.|ptb\.)?discord(?:app)?\.com\/api\/webhooks\/)[^\s/?#]+\/[^\s?#]+/gi, '$1[redacted]');
    text = text.replace(/(https?:\/\/api\.telegram\.org\/bot)[^/\s]+/gi, '$1[redacted]');
    text = text.replace(/(https?:\/\/[^\s?#]+)\?[^\s#]*/gi, '$1?[redacted-query]');
    return text.slice(0, 4000);
  }

  function redactDiagnosticValue(value, depth = 0, seen = new WeakSet()) {
    if (depth > 4) return '[bounded]';
    if (value == null || typeof value === 'number' || typeof value === 'boolean') return value;
    if (typeof value === 'string') return redactDiagnosticString(value);
    if (value instanceof Error) return {
      name: redactDiagnosticString(value.name || 'Error'),
      message: redactDiagnosticString(value.message || ''),
      stack: redactDiagnosticString(value.stack || '').split('\n').slice(0, 12).join('\n')
    };
    if (typeof value !== 'object') return redactDiagnosticString(value);
    if (seen.has(value)) return '[circular]';
    seen.add(value);
    if (Array.isArray(value)) return value.slice(0, 30).map(entry => redactDiagnosticValue(entry, depth + 1, seen));
    const output = {};
    Object.entries(value).slice(0, 40).forEach(([key, entry]) => {
      output[String(key).slice(0, 80)] = SENSITIVE_DIAGNOSTIC_KEYS.test(key)
        ? '[redacted]'
        : redactDiagnosticValue(entry, depth + 1, seen);
    });
    return output;
  }

  function diagnostic(level, category, message, context = null, error = null) {
    const safeLevel = ['debug', 'info', 'warn', 'error'].includes(level) ? level : 'info';
    const safeCategory = String(category || 'general').replace(/[^a-z0-9_-]/gi, '').slice(0, 32) || 'general';
    const safeMessage = redactDiagnosticString(message);
    const entry = {
      id: ++state.diagnosticSequence,
      at: new Date().toISOString(),
      level: safeLevel,
      category: safeCategory,
      message: safeMessage,
      ...(context == null ? {} : { context: redactDiagnosticValue(context) }),
      ...(error == null ? {} : { error: redactDiagnosticValue(error) })
    };
    if (state.settings.diagnosticsEnabled !== false) {
      state.diagnostics.push(entry);
      const max = numberInRange(state.settings.diagnosticsMaxEntries, 200, 25, 500);
      if (state.diagnostics.length > max) state.diagnostics.splice(0, state.diagnostics.length - max);
    }
    if (safeLevel === 'error') {
      state.stats.diagnosticErrors += 1;
      if (state.settings.diagnosticsConsole !== false) console.error(`[${SCRIPT_NAME}][${safeCategory}] ${safeMessage}`, entry.context || '', entry.error || '');
    } else if (safeLevel === 'warn') {
      if (state.settings.diagnosticsConsole !== false) console.warn(`[${SCRIPT_NAME}][${safeCategory}] ${safeMessage}`, entry.context || '');
    } else if (state.settings.debugLogs && state.settings.diagnosticsConsole !== false) {
      console.debug(`[${SCRIPT_NAME}][${safeCategory}] ${safeMessage}`, entry.context || '');
    }
    updateErrorBadge();
    if (state.ui?.panel?.dataset.open === '1' && state.activeTab === 'errors') renderErrors();
    return entry;
  }

  function diagnosticCategory(message) {
    const text = String(message || '').toLowerCase();
    if (text.includes('indexeddb') || text.includes('database')) return 'idb';
    if (text.includes('library')) return 'library';
    if (text.includes('config') || text.includes('update')) return 'config';
    if (text.includes('download') || text.includes('resolve')) return 'resolver';
    if (text.includes('fetch') || text.includes('xhr') || text.includes('intercept')) return 'intercept';
    if (text.includes('telegram') || text.includes('discord') || text.includes('delivery')) return 'delivery';
    return 'runtime';
  }

  function log(...args) {
    if (!args.length) return;
    diagnostic('debug', diagnosticCategory(args[0]), args[0], args.length > 1 ? args.slice(1) : null);
  }

  function warn(...args) {
    diagnostic('warn', diagnosticCategory(args[0]), args[0], args.length > 1 ? args.slice(1) : null);
  }

  function traceError(category, message, error, context = null) {
    return diagnostic('error', category, message, context, error);
  }

  function numberInRange(value, fallback, min, max) {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? Math.max(min, Math.min(max, Math.round(parsed))) : fallback;
  }

  function sanitizeDeliveryBase(value, fallback = 'https://api.telegram.org') {
    try {
      const parsed = new URL(String(value || fallback));
      // Never allow imported settings to redirect the bot token to another
      // origin. The field remains explicit for auditing/future API-version
      // paths, but credentials can only be sent to Telegram's official host.
      if (parsed.protocol !== 'https:' || parsed.hostname.toLowerCase() !== 'api.telegram.org') return fallback;
      parsed.pathname = parsed.pathname.replace(/\/+$/, '');
      parsed.search = '';
      parsed.hash = '';
      return parsed.href.replace(/\/$/, '').slice(0, 500);
    } catch { return fallback; }
  }

  function sanitizeDiscordWebhook(value) {
    const clean = String(value || '').trim().slice(0, 1000);
    if (!clean) return '';
    try {
      const parsed = new URL(clean);
      const host = parsed.hostname.toLowerCase();
      const allowed = ['discord.com', 'canary.discord.com', 'ptb.discord.com', 'discordapp.com'].includes(host);
      if (parsed.protocol !== 'https:' || !allowed || !/^\/api\/webhooks\/[^/]+\/[^/]+/.test(parsed.pathname)) return '';
      parsed.search = '';
      parsed.hash = '';
      return parsed.href.slice(0, 1000);
    } catch { return ''; }
  }

  function sanitizeTelegramToken(value) {
    const clean = String(value || '').trim();
    return /^\d{5,15}:[A-Za-z0-9_-]{20,160}$/.test(clean) ? clean : '';
  }

  function sanitizeSettings(raw) {
    const input = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
    const next = clone(DEFAULT_SETTINGS);
    const boolKeys = [
      'interceptEnabled', 'rewriteQuerySize', 'resolveMissingUrls', 'awaitFetchBackfill',
      'resolveOnLoad', 'removeExpiredTasksOnLoad', 'removeExpiredTaskItemsOnLoad',
      'libraryLinkAssign', 'preferLibraryUrls', 'libraryAssignToTaskStore',
      'librarySkipDownloadRefresh', 'libraryRefreshFromList', 'libraryUseThumbnailFallback',
      'reuseCapturedDownloadHeaders', 'cachingEnabled', 'remoteUpdateEnabled', 'remoteAnnouncementsEnabled',
      'remoteAnnouncementNoticesEnabled', 'debugLogs',
      'diagnosticsEnabled', 'diagnosticsConsole', 'telegramDeliveryEnabled', 'discordDeliveryEnabled',
      'deliverySuccessEnabled', 'deliveryFailureEnabled', 'deliveryIncludeMedia', 'deliveryIncludeCaption'
      ,'fiBridgeEnabled', 'fiBridgeSyncItems', 'fiBridgeSyncSettings', 'fiBridgeAutoSyncOnLoad'
      ,'fiHostEnabled', 'fiHostAutoStore', 'fiHostUseLocalUrls', 'fiHostRewriteSiteMedia', 'fiHostSyncSettings', 'accountSwitcherEnabled', 'cardThumbnails'
      ,'tensorCredentialVaultSyncEnabled', 'tensorCookieVaultSyncEnabled'
    ];
    boolKeys.forEach(key => {
      if (typeof input[key] === 'boolean') next[key] = input[key];
    });
    next.querySize = numberInRange(input.querySize, next.querySize, 1, 100);
    next.cacheDays = numberInRange(input.cacheDays, next.cacheDays, 1, 90);
    next.maxResolvePerResponse = numberInRange(input.maxResolvePerResponse, next.maxResolvePerResponse, 1, 200);
    next.maxStoredTasks = numberInRange(input.maxStoredTasks, next.maxStoredTasks, 20, 2000);
    next.maxStoredItems = numberInRange(input.maxStoredItems, next.maxStoredItems, 50, 4000);
    next.maxStoredUrls = numberInRange(input.maxStoredUrls, next.maxStoredUrls, 50, 5000);
    next.maxStoredLibraryLinks = numberInRange(input.maxStoredLibraryLinks, next.maxStoredLibraryLinks, 50, 5000);
    next.maxVisibleItems = numberInRange(input.maxVisibleItems, next.maxVisibleItems, 20, 800);
    next.onLoadResolveLimit = numberInRange(input.onLoadResolveLimit, next.onLoadResolveLimit, 0, 1000);
    next.remoteConfigDelayMs = numberInRange(input.remoteConfigDelayMs, next.remoteConfigDelayMs, 0, 120_000);
    next.remoteConfigTtlMs = numberInRange(input.remoteConfigTtlMs, next.remoteConfigTtlMs, 60_000, 86_400_000);
    next.diagnosticsMaxEntries = numberInRange(input.diagnosticsMaxEntries, next.diagnosticsMaxEntries, 25, 500);
    next.deliveryMaxCaption = numberInRange(input.deliveryMaxCaption, next.deliveryMaxCaption, 100, 1800);
    next.telegramBotToken = sanitizeTelegramToken(input.telegramBotToken);
    next.telegramChatId = String(input.telegramChatId || '').trim().slice(0, 128);
    next.telegramApiBase = sanitizeDeliveryBase(input.telegramApiBase, next.telegramApiBase);
    next.discordWebhookUrl = sanitizeDiscordWebhook(input.discordWebhookUrl);
    next.fiHostPairing = String(input.fiHostPairing || '').trim().slice(0, 4000);
    next.tensorCookieVaultSyncEnabled = next.tensorCredentialVaultSyncEnabled && next.tensorCookieVaultSyncEnabled;
    next.tensorVaultLastCookieSyncAt = Math.max(0, Number(input.tensorVaultLastCookieSyncAt || 0) || 0);
    if (['grid', 'list'].includes(input.itemsLayout)) next.itemsLayout = input.itemsLayout;
    if (['auto', 'page-fetch', 'gm-request'].includes(input.downloadTransport)) next.downloadTransport = input.downloadTransport;
    if (['auto', 'pro', 'lite'].includes(String(input.fiBridgePrimary || '').toLowerCase())) next.fiBridgePrimary = String(input.fiBridgePrimary).toLowerCase();
    if (input.requestHeaders && typeof input.requestHeaders === 'object' && !Array.isArray(input.requestHeaders)) {
      // Upgrade-safe merge: old Lite rows may contain {}, or only one user
      // override. Preserve the complete Pro resolver contract and layer clean
      // saved overrides on top, matching the full userscript settings merge.
      next.requestHeaders = clone(DEFAULT_SETTINGS.requestHeaders);
      Object.entries(input.requestHeaders).slice(0, 30).forEach(([key, value]) => {
        const cleanKey = String(key || '').trim();
        const cleanValue = String(value ?? '').trim();
        if (cleanKey && cleanValue && cleanKey.toLowerCase() !== 'authorization') next.requestHeaders[cleanKey] = cleanValue;
      });
    }
    return next;
  }

  const FI_HOST_CLIENT_ID = 'fi-bypass-lite';
  const FI_HOST_TENSOR_VAULT_SYNC_ACK = 'STORE MY TENSOR ACCOUNTS IN FI HOST';
  const FI_HOST_TENSOR_VAULT_RESTORE_ACK = 'RESTORE TENSOR ACCOUNTS TO USERSCRIPT';
  const FI_HOST_TENSOR_COOKIE_INTERVAL_MS = 24 * 60 * 60 * 1000;
  const FI_HOST_TENSOR_ACCOUNT_SYNC_INTERVAL_MS = 15 * 60 * 1000;
  let fiHostTensorVaultBusy = false;
  let fiHostTensorLastSyncAt = 0;
  let fiHostTensorCommandBusy = false;
  let fiHostTensorCommandAfter = 0;
  let fiHostBridgeSocket = null;
  let fiHostBridgeReady = false;
  let fiHostBridgeReconnectTimer = null;
  let fiHostBridgeHeartbeatTimer = null;
  let fiHostBridgeFailures = 0;
  let fiHostBridgeRpcSequence = 0;
  const fiHostBridgeRpcPending = new Map();
  const FI_HOST_SAFE_MANAGED_SETTINGS = Object.freeze([
    'fiHostAutoStore', 'fiHostSyncSettings', 'accountSwitcherEnabled', 'fiBridgeEnabled', 'fiBridgePrimary'
  ]);

  function fiHostPairing() {
    if (!state.settings.fiHostEnabled) return null;
    try {
      const value = JSON.parse(String(state.settings.fiHostPairing || ''));
      if (!value || value.kind !== 'fi-host-userscript-pairing' || value.clientId !== FI_HOST_CLIENT_ID) return null;
      const hostUrl = String(value.hostUrl || '').replace(/\/+$/, '');
      const secureHostUrl = String(value.secureHostUrl || '').replace(/\/+$/, '');
      if (!/^http:\/\/(?:localhost|127\.0\.0\.1):\d{2,5}$/i.test(hostUrl)) return null;
      if (secureHostUrl && !/^https:\/\/localhost:\d{2,5}$/i.test(secureHostUrl)) return null;
      const apiKey = String(value.apiKey || '');
      if (!apiKey || apiKey.length > 512) return null;
      return Object.freeze({ hostUrl, secureHostUrl, apiKey });
    } catch { return null; }
  }

  function isFiHostLocalUrl(value) {
    try {
      const url = new URL(String(value || ''));
      return ['localhost', '127.0.0.1', '::1', '[::1]'].includes(url.hostname.toLowerCase())
        && /^https?:$/.test(url.protocol)
        && /\/v2\/items\//.test(url.pathname);
    } catch { return false; }
  }

  function isFiHostMediaElementUrl(value) {
    try {
      const url = new URL(String(value || ''));
      const local = ['localhost', '127.0.0.1', '::1', '[::1]'].includes(url.hostname.toLowerCase());
      const secureEnough = String(location.protocol || new URL(location.href).protocol || '').toLowerCase() !== 'https:' || url.protocol === 'https:';
      return local && secureEnough && /^https?:$/.test(url.protocol)
        && (/\/v2\/items\/[^/]+\/content$/i.test(url.pathname) || /\/v2\/thumbnails\/item\/[^/]+\/content$/i.test(url.pathname));
    } catch { return false; }
  }

  function fiHostRejectBridgeRpc(error) {
    const failure = error instanceof Error ? error : new Error(String(error || 'FI Host WebSocket disconnected.'));
    for (const pending of fiHostBridgeRpcPending.values()) { clearTimeout(pending.timer); pending.reject(failure); }
    fiHostBridgeRpcPending.clear();
  }

  function fiHostStopWebSocket(reason = 'stopped') {
    if (fiHostBridgeReconnectTimer) clearTimeout(fiHostBridgeReconnectTimer);
    if (fiHostBridgeHeartbeatTimer) clearInterval(fiHostBridgeHeartbeatTimer);
    fiHostBridgeReconnectTimer = fiHostBridgeHeartbeatTimer = null;
    fiHostBridgeReady = false;
    fiHostRejectBridgeRpc(new Error(`FI Host WebSocket ${reason}.`));
    const socket = fiHostBridgeSocket; fiHostBridgeSocket = null;
    if (socket) {
      try { socket.onopen = socket.onmessage = socket.onerror = socket.onclose = null; socket.close(); } catch {}
    }
  }

  function fiHostWebSocketEligible(path, options = {}) {
    if (options.forceHttp === true || state.host.transportMode === 'http' || !fiHostBridgeReady || fiHostBridgeSocket?.readyState !== 1) return false;
    const method = String(options.method || 'GET').toUpperCase();
    if (!['GET','POST','PUT','PATCH','DELETE'].includes(method) || !/^\/v[12]\//.test(String(path || '')) || /\/(?:content|preview|export)(?:\/|$)/i.test(String(path || ''))) return false;
    let bodyText = '';
    try { if (options.body !== undefined) bodyText = JSON.stringify(options.body); } catch { return false; }
    return bodyText.length <= 3 * 1024 * 1024;
  }

  function fiHostWebSocketRequest(path, options = {}) {
    if (!fiHostWebSocketEligible(path, options)) return Promise.reject(new Error('FI Host WebSocket RPC is not ready for this request.'));
    const id = `lite-${Date.now().toString(36)}-${(++fiHostBridgeRpcSequence).toString(36)}`;
    const timeoutMs = Math.max(1000, Math.min(600000, Number(options.timeout || 12000)));
    return new Promise((resolve,reject) => {
      const timer = setTimeout(() => { fiHostBridgeRpcPending.delete(id); reject(new Error(`FI Host WebSocket request timed out after ${timeoutMs} ms.`)); }, timeoutMs);
      fiHostBridgeRpcPending.set(id, { resolve, reject, timer });
      try {
        fiHostBridgeSocket.send(JSON.stringify({ type:'rpc', id, method:String(options.method || 'GET').toUpperCase(), path:String(path), headers:options.headers && typeof options.headers === 'object' ? options.headers : {}, bodyText:options.body === undefined ? '' : JSON.stringify(options.body) }));
      } catch (error) { clearTimeout(timer); fiHostBridgeRpcPending.delete(id); reject(error); }
    });
  }

  function fiHostStartWebSocket() {
    if (state.host.transportMode === 'http' || !state.settings.fiHostEnabled) { fiHostStopWebSocket('disabled by Host transport policy'); return false; }
    if (fiHostBridgeSocket && (fiHostBridgeSocket.readyState === 0 || fiHostBridgeSocket.readyState === 1)) return true;
    const pairing = fiHostPairing(); const NativeWebSocket = PAGE.WebSocket || (typeof WebSocket === 'function' ? WebSocket : null);
    if (!pairing || !NativeWebSocket) return false;
    if (fiHostBridgeReconnectTimer) clearTimeout(fiHostBridgeReconnectTimer);
    fiHostBridgeReconnectTimer = null;
    try {
      const preferSecure = String(location.protocol || '').toLowerCase() === 'https:' && pairing.secureHostUrl;
      const url = new URL(preferSecure ? pairing.secureHostUrl : pairing.hostUrl);
      url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
      url.pathname = '/v1/events'; url.search = ''; url.searchParams.set('access_token', pairing.apiKey);
      const socket = new NativeWebSocket(url.toString()); fiHostBridgeSocket = socket;
      socket.onopen = () => {
        if (fiHostBridgeSocket !== socket) return;
        fiHostBridgeFailures = 0;
        socket.send(JSON.stringify({ type:'userscript-hello', clientId:FI_HOST_CLIENT_ID, version:SCRIPT_VERSION, page:String(location.href || '').slice(0,500), stored:state.host.stored, failed:state.host.failed }));
      };
      socket.onmessage = event => {
        let payload; try { payload = JSON.parse(String(event?.data || '{}')); } catch { return; }
        const type = String(payload?.type || '');
        if (type === 'rpc-result') {
          const pending = fiHostBridgeRpcPending.get(String(payload?.id || '')); if (!pending) return;
          clearTimeout(pending.timer); fiHostBridgeRpcPending.delete(String(payload.id));
          if (payload?.transportError) return pending.reject(new Error(String(payload.transportError)));
          let body = {}; try { body = JSON.parse(String(payload?.bodyText || '{}')); } catch { body = {}; }
          if (Number(payload?.status || 0) < 200 || Number(payload?.status || 0) >= 300 || body?.ok === false) { const error = new Error(String(body?.error || `FI Host WebSocket returned ${payload?.status || 0}`).slice(0,500)); error.status=Number(payload?.status||0); return pending.reject(error); }
          pending.resolve(body); return;
        }
        if (type === 'userscript-ready') {
          state.host.transportMode = String(payload?.transport?.mode || 'websocket').toLowerCase() === 'http' ? 'http' : 'websocket';
          if (state.host.transportMode === 'http') { fiHostStopWebSocket('changed to HTTP by FI Host'); return; }
          fiHostBridgeReady = true; state.host.checkedAt = state.host.lastSeenAt = Date.now(); state.host.enabled = payload?.config?.enabled === true; state.host.connected = state.host.enabled; state.host.error = state.host.enabled ? '' : 'The Lite userscript bridge is disabled in FI Host Settings.';
          if (payload?.config?.mediaOrigin) state.host.origin = String(payload.config.mediaOrigin); if (payload?.config?.runtimeInstanceId) state.host.runtimeInstanceId = String(payload.config.runtimeInstanceId);
          if (payload?.config?.settings) fiHostApplyManagedSettings(payload.config);
          fiHostScheduleHealthExpiry();
          if (fiHostBridgeHeartbeatTimer) clearInterval(fiHostBridgeHeartbeatTimer);
          fiHostBridgeHeartbeatTimer = setInterval(() => {
            if (fiHostBridgeSocket === socket && socket.readyState === 1) socket.send(JSON.stringify({ type:'userscript-heartbeat', at:Date.now(), page:String(location.href || '').slice(0,500), stored:state.host.stored, failed:state.host.failed }));
          }, Math.max(30000, Number(payload?.transport?.heartbeatMs || 60000)));
          fiHostPollTensorAccountCommands().catch(error => traceError('host','Tensor account restore WebSocket wake failed',error));
          fiHostSyncTensorVault().catch(error => traceError('host','Encrypted Tensor account WebSocket sync failed',error));
          return;
        }
        if (type === 'userscript-heartbeat-ack') { state.host.checkedAt = state.host.lastSeenAt = Date.now(); state.host.connected = state.host.enabled === true; state.host.error = ''; fiHostScheduleHealthExpiry(); return; }
        if (type === 'command-created') fiHostPollTensorAccountCommands().catch(error => traceError('host','Tensor account restore WebSocket wake failed',error));
      };
      socket.onerror = () => { try { socket.close(); } catch {} };
      socket.onclose = () => {
        if (fiHostBridgeSocket === socket) fiHostBridgeSocket = null;
        fiHostBridgeReady = false; if (fiHostBridgeHeartbeatTimer) clearInterval(fiHostBridgeHeartbeatTimer); fiHostBridgeHeartbeatTimer = null;
        fiHostRejectBridgeRpc(new Error('FI Host WebSocket bridge disconnected.'));
        if (state.host.transportMode === 'http' || !state.settings.fiHostEnabled) return;
        fiHostBridgeFailures = Math.min(8,fiHostBridgeFailures+1);
        fiHostBridgeReconnectTimer = setTimeout(() => { fiHostBridgeReconnectTimer=null; fiHostStartWebSocket(); }, Math.min(60000,1500*(2**Math.min(5,fiHostBridgeFailures))));
      };
      return true;
    } catch { return false; }
  }

  function fiHostRequest(path, options = {}) {
    if (fiHostWebSocketEligible(path, options)) return fiHostWebSocketRequest(path, options).catch(error => {
      if (fiHostBridgeReady) throw error;
      return fiHostHttpRequest(path, options);
    });
    return fiHostHttpRequest(path, options);
  }

  function fiHostHttpRequest(path, options = {}) {
    const pairing = fiHostPairing();
    const request = gmRequestFunction();
    if (!pairing) return Promise.reject(new Error('Paste a valid FI Host Lite pairing first.'));
    if (!request) return Promise.reject(new Error('GM.xmlHttpRequest is unavailable.'));
    const url = `${pairing.hostUrl}${String(path || '').startsWith('/') ? path : `/${path}`}`;
    return new Promise((resolve, reject) => {
      let settled = false;
      const finish = callback => value => { if (!settled) { settled = true; callback(value); } };
      const onLoad = finish(response => {
        const status = Number(response?.status || 0);
        let body = {};
        try { body = response?.response && typeof response.response === 'object' ? response.response : JSON.parse(String(response?.responseText || '{}')); }
        catch { body = {}; }
        if (status < 200 || status >= 300 || body?.ok === false) {
          const error = new Error(String(body?.error || `FI Host returned HTTP ${status || 0}`).slice(0, 500));
          error.status = status;
          if (status !== 404) fiHostMarkUnavailable(error);
          return reject(error);
        }
        resolve(body);
      });
      const onError = finish(errorLike => {
        const error = errorLike instanceof Error ? errorLike : new Error('FI Host is offline or unreachable.');
        fiHostMarkUnavailable(error);
        reject(error);
      });
      const headers = { 'X-FI-Host-Key': pairing.apiKey, 'X-FI-Userscript-Client': FI_HOST_CLIENT_ID, ...(options.headers && typeof options.headers === 'object' ? options.headers : {}) };
      let data;
      if (options.body !== undefined) {
        headers['Content-Type'] = 'application/json';
        data = JSON.stringify(options.body);
      }
      try {
        const pending = request({ method: String(options.method || 'GET').toUpperCase(), url, headers, data, timeout: Number(options.timeout || 12000), responseType: 'text', onload: onLoad, onerror: onError, ontimeout: onError, onabort: onError });
        if (pending && typeof pending.then === 'function') pending.then(onLoad).catch(onError);
      } catch (error) { onError(error); }
    });
  }

  async function fiHostTensorCookies() {
    const rows = new Map();
    const add = cookie => {
      const name = String(cookie?.name || '').trim(); const value = String(cookie?.value ?? '');
      if (!name || !value) return;
      const domain = String(cookie?.domain || '.tensor.art').toLowerCase().replace(/^\./, '');
      if (!/(?:^|\.)tensor(?:hub)?\.art$/.test(domain)) return;
      rows.set(`${name}|${domain}|${cookie?.path || '/'}`, { name, value, domain: `.${domain}`, path: String(cookie?.path || '/'), expiresAt: Number(cookie?.expires || cookie?.expirationDate || 0) || 0, httpOnly: cookie?.httpOnly === true, secure: cookie?.secure !== false, sameSite: String(cookie?.sameSite || '') });
    };
    try { for (const cookie of await PAGE.cookieStore?.getAll?.({ domain: 'tensor.art' }) || []) add(cookie); } catch {}
    try { if (typeof GM !== 'undefined' && GM.cookie?.list) for (const cookie of await GM.cookie.list({ url: 'https://tensor.art/' }) || []) add(cookie); } catch {}
    try { for (const part of String(document.cookie || '').split(';')) { const index = part.indexOf('='); if (index > 0) add({ name: part.slice(0,index).trim(), value: decodeURIComponent(part.slice(index+1).trim()), domain: location.hostname, path:'/', secure:true }); } } catch {}
    return [...rows.values()].slice(0, 64);
  }

  async function fiHostSyncTensorVault(options = {}) {
    if (fiHostTensorVaultBusy || state.settings.tensorCredentialVaultSyncEnabled !== true || !state.host.connected) return { status: 'skipped' };
    if (options.force !== true && Date.now() - fiHostTensorLastSyncAt < FI_HOST_TENSOR_ACCOUNT_SYNC_INTERVAL_MS) return { status: 'fresh' };
    fiHostTensorVaultBusy = true;
    try {
      const includeCookies = state.settings.tensorCookieVaultSyncEnabled === true
        && (options.forceCookies === true || Date.now() - Number(state.settings.tensorVaultLastCookieSyncAt || 0) >= FI_HOST_TENSOR_COOKIE_INTERVAL_MS);
      const cookies = includeCookies ? await fiHostTensorCookies() : [];
      const accounts = liteAccountRows().map(account => {
        const payload = decodeTensorTokenPayload(account.token) || {}; const isCurrent = account.active || account.token === state.lastToken;
        return {
          token: account.token, userId: String(account.userId || payload.userId || payload.uid || payload.sub || ''), username: String(payload.username || payload.handle || ''), nickname: account.nickname,
          avatarUrl: String(account.avatar || ''), deviceId: String(payload.deviceId || payload.device_id || ''), deviceName: String(payload.deviceName || ''),
          expiresAt: Number(payload.exp || 0) * 1000, isCurrent, cookies: isCurrent ? cookies : [], cookieSyncedAt: isCurrent && includeCookies ? Date.now() : 0,
          analytics: { tasks: [...state.tasks.values()].filter(task => String(task?.ownerAccountId || '') === String(account.userId || '')).length, bypassed: [...state.items.values()].filter(item => String(item?.ownerAccountId || '') === String(account.userId || '') && !!item?.url).length, failed: 0 },
          lastSeenAt: Date.now(),
        };
      });
      if (!accounts.length) return { status: 'empty' };
      const result = await fiHostRequest('/v2/tensor-accounts/sync', { method:'POST', body:{ source:'lite', acknowledgement:FI_HOST_TENSOR_VAULT_SYNC_ACK, includeCookies, accounts }, timeout:20000 });
      fiHostTensorLastSyncAt = Date.now();
      if (includeCookies) { state.settings.tensorVaultLastCookieSyncAt = Date.now(); saveSettings(); }
      return { status:'stored', stored:Number(result?.stored || 0), cookies:includeCookies };
    } finally { fiHostTensorVaultBusy = false; }
  }

  function fiHostRestoreTensorAccounts(snapshot) {
    const accounts = Array.isArray(snapshot?.accounts) ? snapshot.accounts.slice(0, 100) : []; let stored = {};
    try { stored = JSON.parse(PAGE.localStorage?.getItem('freeBypassUserAccounts') || '{}') || {}; } catch { stored = {}; }
    let restored = 0;
    for (const account of accounts) {
      const token = String(account?.token || '').replace(/^Bearer\s+/i, '').trim(); const payload = decodeTensorTokenPayload(token);
      if (!payload || !/^eyJ[^.]*\.[^.]+\.[^.]+$/.test(token)) continue;
      const userId = String(account?.userId || payload.userId || payload.uid || payload.sub || tokenOwnerFingerprint(token));
      stored[token] = { ...(stored[token] || {}), userId, nickname:String(account?.nickname || account?.displayName || `Account ${userId.slice(-6)}`), avatar:String(account?.avatarUrl || ''), timestamp:Date.now(), jwtDeviceId:String(account?.deviceId || payload.deviceId || ''), jwtExpMs:Number(account?.expiresAt || payload.exp * 1000 || 0) };
      restored += 1;
    }
    PAGE.localStorage?.setItem('freeBypassUserAccounts', JSON.stringify(stored));
    if (restored && state.activeTab === 'settings') renderSettings();
    return { restored, available:Object.keys(stored).length, switched:false, cookiesApplied:false };
  }

  async function fiHostPollTensorAccountCommands() {
    if (fiHostTensorCommandBusy || !state.host.connected || state.settings.fiHostEnabled !== true) return { processed:0 };
    fiHostTensorCommandBusy = true; let processed = 0;
    try {
      const waitMs = fiHostBridgeReady ? 0 : document.hidden ? 55000 : 25000;
      const list = await fiHostRequest(`/v2/commands?status=pending&after=${Math.max(0,fiHostTensorCommandAfter-1)}&limit=10&waitMs=${waitMs}`, { headers:{'X-FI-Command-Protocol':'2'}, timeout:Math.max(8000,waitMs+5000), forceHttp:waitMs>0 });
      for (const command of Array.isArray(list?.items) ? list.items : []) {
        const createdAt = Number(command?.createdAt || 0); let claimToken = '';
        try {
          const claim = await fiHostRequest(`/v2/commands/${encodeURIComponent(command.id)}/claim`, { method:'POST', headers:{'X-FI-Command-Protocol':'2'}, timeout:8000 });
          claimToken = String(claim?.claimToken || ''); if (!claimToken) continue;
          const snapshot = await fiHostRequest(`/v2/tensor-accounts/exports/${encodeURIComponent(command.id)}/claim-secret`, { method:'POST', body:{claimToken}, timeout:15000 });
          const result = fiHostRestoreTensorAccounts(snapshot);
          await fiHostRequest(`/v2/commands/${encodeURIComponent(command.id)}/result`, { method:'POST', body:{ok:true,claimToken,result:{schema:'fi.tensor-account-restore-result.v1',...result,credentialsInResult:false}}, timeout:8000 });
        } catch (error) {
          if (claimToken) await fiHostRequest(`/v2/commands/${encodeURIComponent(command.id)}/result`, { method:'POST', body:{ok:false,claimToken,error:String(error?.message || error).slice(0,500)}, timeout:8000 }).catch(()=>{});
        }
        fiHostTensorCommandAfter = Math.max(fiHostTensorCommandAfter, createdAt); processed += 1;
      }
      return { processed };
    } finally { fiHostTensorCommandBusy = false; }
  }

  function fiHostApplyManagedSettings(config) {
    if (!state.settings.fiHostSyncSettings || config?.settings?.fiHostSyncSettings === false) return false;
    let changed = false;
    for (const key of FI_HOST_SAFE_MANAGED_SETTINGS) {
      if (!Object.prototype.hasOwnProperty.call(config?.settings || {}, key)) continue;
      const next = config.settings[key];
      if (state.settings[key] === next) continue;
      state.settings[key] = next;
      changed = true;
    }
    if (changed) {
      fiBridgeWriteBootPreference(state.settings.fiBridgeEnabled, state.settings.fiBridgePrimary);
      saveSettings();
    }
    return changed;
  }

  function fiHostConnectionHealthy() {
    const checkedAt = Number(state.host.checkedAt || 0);
    return state.settings.fiHostEnabled === true
      && state.settings.fiHostUseLocalUrls !== false
      && !!fiHostPairing()
      && state.host.enabled === true
      && state.host.connected === true
      && checkedAt > 0
      && Date.now() - checkedAt <= FI_HOST_HEALTH_FRESH_MS
      && fiBridgeOwnsSharedRoutes();
  }

  function fiHostMarkUnavailable(error, options = {}) {
    const message = String(error?.message || error || 'FI Host is offline or unreachable.').slice(0, 300);
    const changed = state.host.connected || state.host.error !== message;
    state.host.connected = false;
    state.host.error = message;
    state.host.pending.clear();
    for (const [key, entry] of [...state.downloads]) {
      if (!isFiHostLocalUrl(entry?.url)) continue;
      state.downloads.delete(key);
      if (state.dbReady) database.remove('downloads', key);
    }
    clearTimeout(state.host.healthTimer);
    state.host.healthTimer = null;
    clearTimeout(state.host.flushTimer);
    state.host.flushTimer = 0;
    fiHostSyncSiteMediaRuntime({ restore: true });
    if (changed || options.forceRender === true) emitItemsChanged(options.reason || 'host-unavailable');
    return false;
  }

  function fiHostScheduleHealthExpiry() {
    clearTimeout(state.host.healthTimer);
    if (!state.host.connected || !Number(state.host.checkedAt || 0)) {
      state.host.healthTimer = null;
      return false;
    }
    state.host.healthTimer = setTimeout(() => {
      state.host.healthTimer = null;
      if (!state.host.connected || Date.now() - Number(state.host.checkedAt || 0) <= FI_HOST_HEALTH_FRESH_MS) return;
      fiHostMarkUnavailable(new Error('FI Host health check expired.'), { forceRender: true, reason: 'host-health-expired' });
    }, FI_HOST_HEALTH_FRESH_MS + 50);
    return true;
  }

  function fiHostForgetItem(id, reason = 'host-item-missing', options = {}) {
    const cleanId = String(id || '').trim();
    if (!cleanId) return false;
    state.host.inventory.delete(cleanId);
    const current = state.items.get(cleanId);
    if (current) {
      const remote = fiHostRemoteCandidate(current);
      const next = { ...current, updatedAt: Date.now() };
      delete next.fiHostId;
      delete next.fiHostMediaId;
      delete next.fiHostLocalUrl;
      delete next.fiHostPreviewUrl;
      delete next.fiHostUpdatedAt;
      delete next.fiHostSource;
      for (const key of ['url', 'bypassedUrl', 'downloadUrl', 'mediaUrl', 'resourceUrl']) {
        if (isFiHostLocalUrl(next[key])) next[key] = remote || '';
      }
      state.items.set(cleanId, next);
      if (state.settings.cachingEnabled) database.put('items', next);
    }
    if (options.notify !== false) {
      fiHostRebuildSiteMediaIndex();
      emitItemsChanged(reason);
    }
    return true;
  }

  function fiHostItemIdFromLocalUrl(value) {
    try {
      const pathname = decodeURIComponent(new URL(String(value || '')).pathname);
      const match = pathname.match(/\/v2\/(?:items\/(?:fi-item-)?|thumbnails\/item\/)([^/]+)\/content$/i);
      return String(match?.[1] || '').replace(/^fi-item-/i, '').trim();
    } catch { return ''; }
  }

  function fiHostHandleLocalMediaError(eventOrUrl, itemIdHint = '') {
    const target = typeof eventOrUrl === 'string' ? null : eventOrUrl?.target;
    const values = typeof eventOrUrl === 'string' ? [eventOrUrl] : [
      target?.currentSrc, target?.src, target?.poster,
      target?.getAttribute?.('src'), target?.getAttribute?.('poster'),
      target?.getAttribute?.('srcset'), target?.getAttribute?.('preview-list')
    ];
    const candidates = values.flatMap(value => {
      const raw = String(value || '').trim();
      return raw ? [raw, ...(raw.match(/https?:\/\/[^\s"',\]]+/g) || [])] : [];
    });
    const localUrl = candidates.find(value => isFiHostMediaElementUrl(value) || isFiHostLocalUrl(value));
    if (!localUrl) return false;
    const id = String(itemIdHint || fiHostItemIdFromLocalUrl(localUrl)).trim();
    if (id) fiHostForgetItem(id, 'host-local-media-error', { notify: false });
    fiHostMarkUnavailable(new Error('FI Host local media failed to load.'), { forceRender: true, reason: 'host-local-media-error' });
    return true;
  }

  function fiHostApplyItem(hosted, reason = 'lookup') {
    const id = String(hosted?.itemId || hosted?.imageId || '').trim();
    const localUrl = String(hosted?.localUrl || hosted?.bypassedUrl || '');
    if (!id || !hosted?.mediaId || !isFiHostLocalUrl(localUrl)) return false;
    const current = state.items.get(id) || { id, imageId: id, ownerAccountId: state.currentAccountId || '' };
    const next = {
      ...current,
      fiHostId: String(hosted.id || `fi-item-${id}`),
      fiHostMediaId: String(hosted.mediaId),
      fiHostLocalUrl: localUrl,
      fiHostPreviewUrl: String(hosted.previewUrl || hosted.thumbnailUrl || ''),
      fiHostUpdatedAt: Date.now(),
      fiHostSource: reason,
      ownerAccountId: state.currentAccountId || current.ownerAccountId || '',
      updatedAt: Date.now(),
    };
    state.host.inventory.set(id, { ...hosted, localUrl });
    state.items.set(id, next);
    if (state.settings.cachingEnabled) database.put('items', next);
    fiHostTrackSiteMediaItem(next, { ...hosted, localUrl });
    return true;
  }

  function fiHostLocalCandidate(item) {
    if (!fiHostConnectionHealthy()) return '';
    const id = itemId(item);
    const hosted = state.host.inventory.get(id);
    const url = String(hosted?.localUrl || item?.fiHostLocalUrl || '');
    return hosted?.mediaId && isFiHostLocalUrl(url) ? url : '';
  }

  function fiHostRemoteCandidate(item) {
    if (!item) return '';
    const library = libraryLinkForCurrentAccount(itemId(item));
    const candidates = [
      library?.librarySignedUrl, library?.signedUrl, item.librarySignedUrl,
      item.originalTaskUrl, item.bypassedUrl, item.downloadUrl, item.mediaUrl, item.resourceUrl, item.url
    ];
    return String(candidates.find(url => isUsableMediaUrl(url, 0) && !isFiHostLocalUrl(url)) || '');
  }

  async function fiHostLookupItem(id, options = {}) {
    const cleanId = String(id || '').trim();
    if (!cleanId || !state.host.connected || !fiBridgeOwnsSharedRoutes()) return null;
    if (!options.refresh && state.host.inventory.has(cleanId)) return state.host.inventory.get(cleanId);
    try {
      const result = await fiHostRequest(`/v2/items/by-item/${encodeURIComponent(cleanId)}`, { timeout: 7000 });
      if (result?.item) fiHostApplyItem(result.item, 'shared-item-lookup');
      return result?.item || null;
    } catch (error) {
      if (Number(error?.status || 0) !== 404) throw error;
      fiHostForgetItem(cleanId, 'host-item-not-found');
      return null;
    }
  }

  async function fiHostLookupItems(ids) {
    const itemIds = [...new Set((Array.isArray(ids) ? ids : []).map(id => String(id || '').trim()).filter(isTensorDownloadableId))].slice(0, 500);
    if (!itemIds.length || !state.host.connected || !fiBridgeOwnsSharedRoutes()) return [];
    const result = await fiHostRequest('/v2/items/lookup', { method: 'POST', body: { itemIds }, timeout: 10000 });
    const rows = Array.isArray(result?.items) ? result.items : [];
    rows.forEach(item => fiHostApplyItem(item, 'shared-item-batch-lookup'));
    const returned = new Set(rows.map(item => String(item?.itemId || item?.imageId || '')).filter(Boolean));
    const missingIds = itemIds.filter(id => !returned.has(id));
    missingIds.forEach(id => fiHostForgetItem(id, 'host-item-not-found', { notify: false }));
    if (missingIds.length) {
      fiHostRebuildSiteMediaIndex();
      emitItemsChanged('host-items-not-found');
    }
    return rows;
  }

  async function fiHostMaterializeItem(item, options = {}) {
    if (!state.host.connected || !state.settings.fiHostAutoStore || !fiBridgeOwnsSharedRoutes()) return null;
    const id = itemId(item);
    if (!isTensorDownloadableId(id)) return null;
    const existing = options.skipLookup ? null : await fiHostLookupItem(id).catch(() => null);
    if (existing?.mediaId) { state.host.reused += 1; return existing; }
    const sourceUrl = fiHostRemoteCandidate(item);
    if (!sourceUrl) return null;
    const body = {
      itemId: id,
      imageId: id,
      taskId: String(item.taskId || ''),
      sourceUrl,
      mimeType: String(item.mimeType || item.libraryMimeType || ''),
      downloadFileName: String(item.downloadFileName || item.fileName || item.libraryFileName || ''),
      taskExpiresAt: Number(item.taskExpireAtMs || 0),
      metadata: {
        remoteUrl: sourceUrl,
        sourceClient: FI_HOST_CLIENT_ID,
        sourceVersion: SCRIPT_VERSION,
        type: String(item.type || ''),
        width: Number(item.width || 0) || '',
        height: Number(item.height || 0) || '',
        prompt: String(item.prompt || '').slice(0, 12000),
        parameters: String(item.parameters || '').slice(0, 24000),
        workspaceType: String(item.workspaceType || ''),
      }
    };
    if (!options.skipUpsert) await fiHostRequest(`/v2/items/${encodeURIComponent(`fi-item-${id}`)}`, { method: 'PUT', body, timeout: 12000 });
    const result = await fiHostRequest(`/v2/items/${encodeURIComponent(`fi-item-${id}`)}/materialize`, { method: 'POST', body, timeout: 30000 });
    if (result?.item?.mediaId) {
      fiHostApplyItem(result.item, 'materialized');
      state.host.stored += 1;
      return result.item;
    }
    if (result?.job && !result.completed) {
      [2500, 7000, 15000].forEach(delay => setTimeout(() => {
        if (state.host.connected && !state.host.inventory.get(id)?.mediaId) fiHostLookupItem(id, { refresh: true }).catch(() => {});
      }, delay));
    }
    return result?.item || null;
  }

  function fiHostScheduleItem(item, reason = 'observed') {
    if (!state.host.connected || !fiBridgeOwnsSharedRoutes() || !item || !isTensorDownloadableId(itemId(item))) return;
    const id = itemId(item);
    const revision = ++state.host.nextRevision;
    state.host.pending.set(id, { revision, item: clone(item), reason });
    clearTimeout(state.host.flushTimer);
    state.host.flushTimer = setTimeout(fiHostFlushPending, 40);
  }

  async function fiHostFlushPending() {
    if (state.host.flushInFlight || !state.host.connected || !fiBridgeOwnsSharedRoutes() || !state.host.pending.size) return state.host.flushInFlight;
    const batch = [...state.host.pending.entries()].slice(0, 60);
    for (const [id, pending] of batch) {
      if (state.host.pending.get(id)?.revision === pending.revision) state.host.pending.delete(id);
    }
    state.host.flushInFlight = (async () => {
      try {
        const existingRows = await fiHostLookupItems(batch.map(([id]) => id));
        const existingIds = new Set(existingRows.filter(row => row?.mediaId).map(row => String(row.itemId || row.imageId || '')));
        state.host.reused += existingIds.size;
        const missing = batch.filter(([id]) => !existingIds.has(id) && !state.host.pending.has(id));
        const upserts = missing.map(([id, pending]) => {
          const sourceUrl = fiHostRemoteCandidate(pending.item);
          if (!sourceUrl) return null;
          return { id: `fi-item-${id}`, body: {
            itemId: id, imageId: id, taskId: String(pending.item.taskId || ''), sourceUrl,
            mimeType: String(pending.item.mimeType || pending.item.libraryMimeType || ''),
            downloadFileName: String(pending.item.downloadFileName || pending.item.fileName || pending.item.libraryFileName || ''),
            taskExpiresAt: Number(pending.item.taskExpireAtMs || 0),
            metadata: { remoteUrl: sourceUrl, sourceClient: FI_HOST_CLIENT_ID, sourceVersion: SCRIPT_VERSION }
          } };
        }).filter(Boolean);
        if (upserts.length) await fiHostRequest('/v2/items/batch', { method: 'PUT', body: { items: upserts }, timeout: 15000 });
        const concurrency = 2;
        let cursor = 0;
        await Promise.all(Array.from({ length: Math.min(concurrency, missing.length) }, async () => {
          while (cursor < missing.length && state.host.connected) {
            const [, pending] = missing[cursor++];
            try { await fiHostMaterializeItem(pending.item, { skipLookup: true, skipUpsert: true }); }
            catch (error) {
              state.host.failed += 1;
              traceError('host', 'FI Host Item storage failed', error, { itemId: itemId(pending.item), reason: pending.reason });
            }
            await new Promise(resolve => setTimeout(resolve, 0));
          }
        }));
        if (state.ui?.panel?.dataset.open === '1' && state.activeTab === 'items') renderItems();
      } finally {
        state.host.flushInFlight = null;
        if (state.host.pending.size && state.host.connected) {
          clearTimeout(state.host.flushTimer);
          state.host.flushTimer = setTimeout(fiHostFlushPending, 80);
        }
      }
    })();
    return state.host.flushInFlight;
  }

  async function fiHostBackfillExistingForBody(body) {
    if (!state.host.connected || !fiBridgeOwnsSharedRoutes()) return 0;
    const ids = [];
    for (const task of taskListFromBody(body)) {
      for (const item of Array.isArray(task?.items) ? task.items : []) {
        const id = itemId(item);
        if (isTensorDownloadableId(id) && !state.host.inventory.has(id) && !ids.includes(id)) ids.push(id);
        if (ids.length >= 40) break;
      }
      if (ids.length >= 40) break;
    }
    const rows = await fiHostLookupItems(ids).catch(() => []);
    return rows.filter(row => row?.mediaId).length;
  }

  async function fiHostRefresh(options = {}) {
    if (state.host.refreshInFlight) return state.host.refreshInFlight;
    if (!state.settings.fiHostEnabled || !fiHostPairing()) {
      state.host.connected = false;
      state.host.enabled = false;
      clearTimeout(state.host.healthTimer);
      state.host.healthTimer = null;
      fiHostSyncSiteMediaRuntime({ restore: true });
      emitItemsChanged('host-disabled');
      return null;
    }
    state.host.refreshInFlight = (async () => {
      try {
        const wasConnected = state.host.connected;
        const config = await fiHostRequest(`/v2/userscript-clients/${FI_HOST_CLIENT_ID}/heartbeat`, {
          method: 'POST', timeout: 8000, forceHttp:true,
          body: { version: SCRIPT_VERSION, page: location.href, stored: state.host.stored, failed: state.host.failed }
        });
        state.host.checkedAt = Date.now();
        state.host.enabled = config?.enabled === true;
        state.host.connected = config?.enabled === true;
        state.host.lastSeenAt = Date.now();
        state.host.origin = String(config?.mediaOrigin || '');
        state.host.runtimeInstanceId = String(config?.runtimeInstanceId || '');
        state.host.transportMode = String(config?.transport?.mode || 'websocket').toLowerCase() === 'http' ? 'http' : 'websocket';
        state.host.error = config?.enabled === true ? '' : 'The Lite userscript bridge is disabled in FI Host Settings.';
        fiHostScheduleHealthExpiry();
        if (config?.enabled === true && config?.settings) fiHostApplyManagedSettings(config);
        if (!wasConnected && state.host.connected) {
          if (fiBridgeOwnsSharedRoutes()) [...state.items.values()].filter(isEntryForCurrentAccount).slice(0, 120).forEach(item => fiHostScheduleItem(item, 'connection-ready'));
        }
        fiHostRebuildSiteMediaIndex();
        if (wasConnected !== state.host.connected) emitItemsChanged(state.host.connected ? 'host-online' : 'host-disabled');
        if (state.host.transportMode === 'websocket') fiHostStartWebSocket();
        else {
          fiHostStopWebSocket('changed to HTTP by FI Host');
          fiHostSyncTensorVault().catch(error => traceError('host', 'Encrypted Tensor account sync failed', error));
        }
        return config;
      } catch (error) {
        state.host.checkedAt = Date.now();
        fiHostMarkUnavailable(error, { forceRender: true });
        if (options.manual) traceError('host', 'FI Host connection test failed', error);
        return null;
      } finally {
        state.host.refreshInFlight = null;
      }
    })();
    return state.host.refreshInFlight;
  }

  function fiHostStartPolling() {
    const revision = ++state.host.pollRevision;
    clearTimeout(state.host.timer);
    if (!state.settings.fiHostEnabled || !fiHostPairing()) {
      fiHostStopWebSocket('disabled');
      state.host.connected = false;
      clearTimeout(state.host.healthTimer);
      state.host.healthTimer = null;
      fiHostSyncSiteMediaRuntime({ restore: true });
      return;
    }
    const poll = async () => {
      let completedLongPoll = false;
      if (!fiHostBridgeReady) {
        if (state.host.transportMode === 'http' && state.host.connected) {
          try {
            await fiHostPollTensorAccountCommands();
            state.host.checkedAt = state.host.lastSeenAt = Date.now();
            state.host.error = '';
            fiHostScheduleHealthExpiry();
            completedLongPoll = true;
          } catch (error) {
            fiHostMarkUnavailable(error, { forceRender:true });
          }
        } else await fiHostRefresh();
      }
      if (revision !== state.host.pollRevision || !state.settings.fiHostEnabled || !fiHostPairing()) return;
      const delay = fiHostBridgeReady ? 10 * 60 * 1000 : state.host.transportMode === 'http' ? (completedLongPoll ? 250 : document.hidden ? 2 * 60 * 1000 : 30 * 1000) : (document.hidden ? 2 * 60 * 1000 : 30 * 1000);
      state.host.timer = setTimeout(poll, delay);
    };
    poll();
  }

  const FI_BRIDGE_SAFE_SETTING_KEYS = Object.freeze(['libraryLinkAssign']);

  function fiBridgeConfig() {
    const boot = fiBridgeReadBootPreference();
    const primary = boot?.primary || (['auto','pro','lite'].includes(state.settings.fiBridgePrimary) ? state.settings.fiBridgePrimary : 'auto');
    return {
      enabled: boot ? boot.enabled === true : state.settings.fiBridgeEnabled === true,
      primary,
      syncItems: state.settings.fiBridgeSyncItems !== false,
      syncSettings: state.settings.fiBridgeSyncSettings === true,
      autoSync: state.settings.fiBridgeAutoSyncOnLoad !== false
    };
  }

  function fiBridgeResolvedPrimary() {
    const config = fiBridgeConfig();
    if (config.primary === 'pro' || config.primary === 'lite') return config.primary;
    return 'lite';
  }

  function fiBridgeExpectedNetworkOwner() {
    const config = fiBridgeConfig();
    if (config.enabled) return fiBridgeResolvedPrimary();
    if (config.primary === 'pro' || config.primary === 'lite') return config.primary;
    const advertisedOwner = String(PAGE.__FI_BRIDGE_NETWORK_OWNER__ || state.bridge.networkOwner || '').toLowerCase();
    if (advertisedOwner === 'pro' || advertisedOwner === 'lite') return advertisedOwner;
    return (PAGE.__FI_PRO_ACTIVE__ || PAGE.__freeBypassTensorRequestListenerInstalled) ? 'pro' : 'lite';
  }

  function fiBridgeAdvertiseNetworkOwner(owner = fiBridgeExpectedNetworkOwner()) {
    const normalized = owner === 'lite' ? 'lite' : 'pro';
    state.bridge.networkOwner = normalized;
    try { PAGE.__FI_BRIDGE_NETWORK_OWNER__ = normalized; } catch {}
    return normalized;
  }

  function fiBridgeOwnsSharedRoutes() {
    return fiBridgeAdvertiseNetworkOwner() === 'lite';
  }

  function fiBridgeCanDelegateResolution() {
    const config = fiBridgeConfig();
    return config.enabled === true
      && fiBridgeAdvertiseNetworkOwner() === 'pro'
      && !!(PAGE.__FI_PRO_ACTIVE__ || PAGE.__freeBypassTensorRequestListenerInstalled);
  }

  async function fiBridgeResolveThroughOwner(candidates, options = {}) {
    if (!fiBridgeCanDelegateResolution()) {
      throw new Error('Lite is not the URL owner and the Pro resolver bridge is unavailable. Enable FI Bridge with Pro as owner, or select Lite as owner and reload Tensor.');
    }
    const items = [...new Map((Array.isArray(candidates) ? candidates : [])
      .map(entry => ({ imageId: String(entry?.id || entry?.imageId || '').trim(), mimeType: String(entry?.mimeType || '').slice(0, 160) }))
      .filter(entry => isTensorDownloadableId(entry.imageId))
      .map(entry => [entry.imageId, entry])).values()].slice(0, FI_BRIDGE_RESOLVE_MAX_ITEMS);
    if (!items.length) return new Map();
    state.bridge.resolveSequence = Number(state.bridge.resolveSequence || 0) + 1;
    const requestId = `lite-${Date.now().toString(36)}-${state.bridge.resolveSequence.toString(36)}`;
    const response = await new Promise((resolve, reject) => {
      let settled = false;
      const finish = callback => value => {
        if (settled) return;
        settled = true;
        clearTimeout(timer);
        try { PAGE.removeEventListener?.(FI_BRIDGE_RESOLVE_RESPONSE_EVENT, onResponse); } catch {}
        callback(value);
      };
      const onResponse = event => {
        const detail = event?.detail;
        if (!detail || detail.requestId !== requestId || detail.source !== 'pro') return;
        finish(resolve)(detail);
      };
      const timer = setTimeout(finish(() => reject(new Error('The Pro resolver did not answer before the bridge timeout.'))), FI_BRIDGE_RESOLVE_TIMEOUT_MS);
      try { PAGE.addEventListener(FI_BRIDGE_RESOLVE_RESPONSE_EVENT, onResponse); }
      catch (error) { finish(reject)(error); return; }
      try {
        const EventCtor = PAGE.CustomEvent || CustomEvent;
        PAGE.dispatchEvent(new EventCtor(FI_BRIDGE_RESOLVE_REQUEST_EVENT, {
          detail: {
            apiVersion: '1.0', requestId, source: 'lite', reason: String(options.reason || 'lite-resolver').slice(0, 80),
            force: options.force === true, items: items.map(entry => ({ imageId: entry.imageId, mimeType: entry.mimeType }))
          }
        }));
      } catch (error) { finish(reject)(error); }
    });
    const resolved = new Map();
    for (const row of Array.isArray(response?.results) ? response.results : []) {
      const id = String(row?.imageId || '').trim();
      const url = String(row?.url || '').trim();
      if (items.some(entry => entry.imageId === id) && isUsableMediaUrl(url, 0) && !isFiHostLocalUrl(url)) resolved.set(id, url);
    }
    state.bridge.delegatedResolves = Number(state.bridge.delegatedResolves || 0) + resolved.size;
    if (!resolved.size && response?.error) throw new Error(String(response.error).slice(0, 300));
    return resolved;
  }

  function fiBridgeStatus() {
    const config = fiBridgeConfig();
    return Object.freeze({
      apiVersion: '1.0',
      enabled: config.enabled,
      configuredPrimary: config.primary,
      resolvedPrimary: fiBridgeResolvedPrimary(),
      networkOwner: fiBridgeAdvertiseNetworkOwner(),
      peers: Object.freeze({ pro: !!(PAGE.__FI_PRO_ACTIVE__ || PAGE.__freeBypassTensorRequestListenerInstalled), lite: true }),
      capabilities: Object.freeze({ items: config.syncItems, settings: config.syncSettings, secrets: false, rawDatabaseHandles: false }),
      runtime: Object.freeze({ ...state.bridge })
    });
  }

  function fiBridgeApplyBootPreference(options = {}) {
    const boot = fiBridgeReadBootPreference();
    const settingsUpdatedAt = Number(state.settingsUpdatedAt || 0);
    if (options.publishNewerSettings === true && ((!boot && settingsUpdatedAt > 0) || (boot && settingsUpdatedAt > Number(boot.updatedAt || 0)))) {
      fiBridgeWriteBootPreference(state.settings.fiBridgeEnabled, state.settings.fiBridgePrimary, settingsUpdatedAt || Date.now());
      return false;
    }
    if (!boot) return false;
    state.settings.fiBridgeEnabled = boot.enabled;
    state.settings.fiBridgePrimary = boot.primary;
    return true;
  }

  function fiBridgeActivateNetworkOwner() {
    const config = fiBridgeConfig();
    const expectedOwner = fiBridgeExpectedNetworkOwner();
    const ownsNetwork = expectedOwner === 'lite';
    if (!ownsNetwork) {
      fiBridgeAdvertiseNetworkOwner(expectedOwner);
      state.host.pending.clear();
      clearTimeout(state.host.flushTimer);
      fiHostSyncSiteMediaRuntime({ restore: true });
      diagnostic('info', 'bridge', 'Lite is secondary; request interception stayed disabled', { primary: state.bridge.networkOwner });
      return false;
    }
    fiBridgeAdvertiseNetworkOwner('lite');
    try { Object.defineProperty(PAGE, '__FI_BYPASS_LITE_ACTIVE__', { value: true, configurable: true }); }
    catch { PAGE.__FI_BYPASS_LITE_ACTIVE__ = true; }
    try { PAGE.__FI_BRIDGE_LITE_CAPABILITIES__ = Object.freeze({ owner: 'lite', sharedEndpointKinds: Object.freeze(['query','mget','task','tasks','library','download-image','download-video']), hostItems: true, version: SCRIPT_VERSION }); } catch {}
    try { PAGE.__FI_BRIDGE_NETWORK_OWNER__ = 'lite'; } catch {}
    installFetchInterceptor();
    installXhrInterceptor();
    fiHostRebuildSiteMediaIndex();
    diagnostic('info', 'bridge', 'Lite owns Tensor request interception', { bridgeEnabled: config.enabled, primary: fiBridgeResolvedPrimary() });
    return true;
  }

  function fiBridgeReconcileNetworkOwner(reason = 'runtime') {
    const previousOwner = String(PAGE.__FI_BRIDGE_NETWORK_OWNER__ || state.bridge.networkOwner || '');
    const activated = fiBridgeActivateNetworkOwner();
    const currentOwner = String(PAGE.__FI_BRIDGE_NETWORK_OWNER__ || state.bridge.networkOwner || '');
    if (previousOwner && previousOwner !== currentOwner) {
      diagnostic('info', 'bridge', activated ? 'Lite reclaimed shared Tensor routes after preference hydration' : 'Lite yielded shared Tensor routes to Pro', { previousOwner, currentOwner, reason });
      emitItemsChanged('bridge-live-reconciled');
    }
    return activated;
  }

  function fiBridgeScheduleAutoElection(attempt = 0) {
    if (PAGE.__FI_PRO_ACTIVE__ || PAGE.__freeBypassTensorRequestListenerInstalled || attempt >= 5) {
      fiBridgeActivateNetworkOwner();
      return;
    }
    setTimeout(() => fiBridgeScheduleAutoElection(attempt + 1), 20);
  }


  const FI_HOST_SITE_MEDIA_SELECTOR = 'img[src],video[src],video[poster],audio[src],source[src],[srcset],[preview-list]';
  const FI_HOST_SITE_MEDIA_ATTRIBUTES = Object.freeze(['src', 'poster', 'srcset', 'preview-list']);
  const FI_HOST_SITE_MEDIA_MAX_ROOTS = 96;
  const FI_HOST_SITE_MEDIA_MAX_NODES_PER_SLICE = 96;
  const FI_HOST_SITE_MEDIA_MAX_REWRITES = 4096;
  const FI_HOST_SITE_MEDIA_MAX_ASSIGNMENTS_PER_REVISION = 2;
  const fiHostSiteMediaRuntime = {
    exact: new Map(),
    identities: new Map(),
    roots: new Set(),
    restorations: new Map(),
    assignments: new WeakMap(),
    traversals: new WeakMap(),
    continuations: new WeakSet(),
    reloadAt: new WeakMap(),
    observer: null,
    handle: null,
    visibilityHandler: null,
    revision: 0
  };

  function fiHostSiteMediaActive() {
    return state.settings.fiHostRewriteSiteMedia === true
      && fiHostConnectionHealthy();
  }

  function fiHostSiteMediaIdentity(value) {
    try {
      const url = new URL(String(value || ''), location.href);
      if (!/^https?:$/.test(url.protocol) || isFiHostMediaElementUrl(url.href)) return '';
      const hostname = String(url.hostname || '').toLowerCase();
      if (!/(^|\.)(?:tensorartassets\.com|cloudflarestorage\.com)$/.test(hostname)) return '';
      const pathname = String(url.pathname || '').replace(/\/{2,}/g, '/');
      return pathname && pathname !== '/' ? `${hostname}${pathname}` : '';
    } catch { return ''; }
  }

  function fiHostSiteMediaRemoteUrls(item, hosted = {}) {
    const values = new Set();
    const add = value => {
      if (Array.isArray(value)) {
        value.slice(0, 32).forEach(add);
        return;
      }
      if (typeof value !== 'string') return;
      const direct = String(value || '').trim();
      if (fiHostSiteMediaIdentity(direct)) values.add(direct);
      for (const match of direct.match(/https?:\/\/[^\s"',\]]+/g) || []) {
        if (fiHostSiteMediaIdentity(match)) values.add(match);
      }
    };
    const library = libraryLinkForCurrentAccount(itemId(item));
    [
      hosted.sourceUrl, hosted.metadata?.remoteUrl, hosted.metadata?.sourceUrl,
      library?.librarySignedUrl, library?.libraryThumbnailUrl,
      item?.originalTaskUrl, item?.remoteUrl, item?.sourceUrl, item?.librarySignedUrl, item?.libraryThumbnailUrl,
      item?.url, item?.bypassedUrl, item?.downloadUrl, item?.mediaUrl, item?.resourceUrl, item?.originUrl,
      item?.processImageUrl, item?.previewUrl, item?.thumbnailUrl, item?.coverUrl, item?.posterUrl,
      item?.src, item?.srcset, item?.previewList, item?.['preview-list']
    ].forEach(add);
    return [...values];
  }

  function fiHostSiteMediaPreviewUrl(item, hosted, contentUrl, kind) {
    const direct = [
      hosted?.previewUrl, hosted?.thumbnailUrl, item?.fiHostPreviewUrl
    ].map(value => String(value || '').trim()).find(isFiHostMediaElementUrl);
    if (direct) return direct;
    if (hosted?.thumbnail && contentUrl) {
      try {
        const preview = new URL(contentUrl);
        preview.pathname = `/v2/thumbnails/item/${encodeURIComponent(itemId(item))}/content`;
        if (isFiHostMediaElementUrl(preview.href)) return preview.href;
      } catch {}
    }
    return kind === 'image' ? contentUrl : '';
  }

  function fiHostSiteMediaDescriptor(item, hosted = state.host.inventory.get(itemId(item)) || {}) {
    const contentUrl = String(hosted?.localUrl || item?.fiHostLocalUrl || '').trim();
    if (!hosted?.mediaId || !isFiHostMediaElementUrl(contentUrl)) return null;
    const mimeType = String(item?.mimeType || item?.libraryMimeType || hosted?.hostedMedia?.mime || '').trim().toLowerCase().slice(0, 160);
    const kind = mediaKind(mimeType);
    if (!kind) return null;
    const revision = ++fiHostSiteMediaRuntime.revision;
    return Object.freeze({
      imageId: itemId(item),
      contentUrl,
      previewUrl: fiHostSiteMediaPreviewUrl(item, hosted, contentUrl, kind),
      mimeType,
      kind,
      revision
    });
  }

  function fiHostTrackSiteMediaItem(item, hosted = state.host.inventory.get(itemId(item)) || {}) {
    if (!item || !fiHostSiteMediaActive()) return 0;
    const descriptor = fiHostSiteMediaDescriptor(item, hosted);
    if (!descriptor) return 0;
    let added = 0;
    for (const remote of fiHostSiteMediaRemoteUrls(item, hosted)) {
      fiHostSiteMediaRuntime.exact.set(remote, descriptor);
      const identity = fiHostSiteMediaIdentity(remote);
      if (identity) fiHostSiteMediaRuntime.identities.set(identity, descriptor);
      added++;
    }
    while (fiHostSiteMediaRuntime.exact.size > FI_HOST_SITE_MEDIA_MAX_REWRITES) {
      const oldest = fiHostSiteMediaRuntime.exact.keys().next().value;
      if (oldest == null) break;
      fiHostSiteMediaRuntime.exact.delete(oldest);
    }
    if (added) fiHostSyncSiteMediaRuntime({ scan: true });
    return added;
  }

  function fiHostRebuildSiteMediaIndex() {
    fiHostSiteMediaRuntime.exact.clear();
    fiHostSiteMediaRuntime.identities.clear();
    if (fiHostSiteMediaActive()) {
      [...state.items.values()]
        .filter(isEntryForCurrentAccount)
        .slice(0, state.settings.maxStoredItems)
        .forEach(item => fiHostTrackSiteMediaItem(item));
    }
    fiHostSyncSiteMediaRuntime({ scan: fiHostSiteMediaRuntime.exact.size > 0, restore: fiHostSiteMediaRuntime.exact.size === 0 });
    return fiHostSiteMediaRuntime.exact.size;
  }

  function fiHostSiteMediaDescriptorForUrl(value) {
    const raw = String(value || '').trim();
    return fiHostSiteMediaRuntime.exact.get(raw)
      || fiHostSiteMediaRuntime.identities.get(fiHostSiteMediaIdentity(raw))
      || null;
  }

  function fiHostSiteMediaTarget(node, attribute, descriptor) {
    if (!descriptor?.kind) return '';
    const tag = String(node?.tagName || '').toLowerCase();
    const attr = String(attribute || '').toLowerCase();
    const preview = descriptor.previewUrl || (descriptor.kind === 'image' ? descriptor.contentUrl : '');
    if (attr === 'poster' || attr === 'srcset' || attr === 'preview-list' || tag === 'img') return preview;
    if (tag === 'video') return descriptor.kind === 'video' && attr === 'src' ? descriptor.contentUrl : '';
    if (tag === 'audio') return descriptor.kind === 'audio' && attr === 'src' ? descriptor.contentUrl : '';
    if (tag === 'source') {
      const parentTag = String(node.closest?.('video,audio')?.tagName || '').toLowerCase();
      if (parentTag === 'video' && descriptor.kind === 'video') return descriptor.contentUrl;
      if (parentTag === 'audio' && descriptor.kind === 'audio') return descriptor.contentUrl;
    }
    return '';
  }

  function fiHostSiteMediaUiNode(node) {
    try { return !!node?.closest?.('#fi-lite-panel,#fi-lite-fab,.fi-l-preview,.fi-l-remote-toast'); }
    catch { return false; }
  }

  function fiHostRememberSiteMediaRestoration(node, attribute, remote, local) {
    let record = fiHostSiteMediaRuntime.restorations.get(node);
    if (!record) {
      if (fiHostSiteMediaRuntime.restorations.size >= FI_HOST_SITE_MEDIA_MAX_REWRITES) {
        fiHostSiteMediaRuntime.restorations.delete(fiHostSiteMediaRuntime.restorations.keys().next().value);
      }
      record = new Map();
      fiHostSiteMediaRuntime.restorations.set(node, record);
    }
    record.set(attribute, { remote, local });
  }

  function fiHostRewriteSiteMediaRoot(node) {
    if (!node || !fiHostSiteMediaRuntime.exact.size) return 0;
    let changed = 0;
    const rewriteAttribute = (target, attribute) => {
      if (!target?.hasAttribute?.(attribute) || fiHostSiteMediaUiNode(target)) return false;
      const current = String(target.getAttribute(attribute) || '').trim();
      if (!current || isFiHostMediaElementUrl(current)) return false;
      let descriptor = fiHostSiteMediaDescriptorForUrl(current);
      let replacement = descriptor ? fiHostSiteMediaTarget(target, attribute, descriptor) : '';
      if (!descriptor && (attribute === 'srcset' || attribute === 'preview-list')) {
        let highestRevision = 0;
        replacement = current.replace(/https?:\/\/[^\s"',\]]+/g, candidate => {
          const match = fiHostSiteMediaDescriptorForUrl(candidate);
          highestRevision = Math.max(highestRevision, Number(match?.revision || 0));
          return fiHostSiteMediaTarget(target, attribute, match) || candidate;
        });
        if (replacement === current) return false;
        descriptor = { revision: highestRevision || fiHostSiteMediaRuntime.revision };
      }
      const compound = attribute === 'srcset' || attribute === 'preview-list';
      if (!replacement || replacement === current || (!compound && !isFiHostMediaElementUrl(replacement))) return false;
      let assignments = fiHostSiteMediaRuntime.assignments.get(target);
      if (!assignments) {
        assignments = new Map();
        fiHostSiteMediaRuntime.assignments.set(target, assignments);
      }
      const previous = assignments.get(attribute);
      if (previous?.revision === descriptor.revision
        && previous?.target === replacement
        && Number(previous?.attempts || 0) >= FI_HOST_SITE_MEDIA_MAX_ASSIGNMENTS_PER_REVISION) return false;
      const attempts = previous?.revision === descriptor.revision ? Number(previous.attempts || 0) + 1 : 1;
      assignments.set(attribute, { revision: descriptor.revision, target: replacement, attempts });
      fiHostRememberSiteMediaRestoration(target, attribute, current, replacement);
      target.setAttribute(attribute, replacement);
      state.stats.siteMediaRewrites += 1;
      return true;
    };
    const rewriteOne = target => {
      let nodeChanged = false;
      for (const attribute of FI_HOST_SITE_MEDIA_ATTRIBUTES) {
        if (rewriteAttribute(target, attribute)) nodeChanged = true;
      }
      if (!nodeChanged) return;
      changed++;
      try {
        const media = target.matches?.('source') ? target.closest?.('video,audio') : null;
        const now = Date.now();
        if (!document.hidden && typeof media?.load === 'function' && now - Number(fiHostSiteMediaRuntime.reloadAt.get(media) || 0) >= 1500) {
          fiHostSiteMediaRuntime.reloadAt.set(media, now);
          media.load();
        }
      } catch {}
    };
    if (node?.nodeType === 1 && node.matches?.(FI_HOST_SITE_MEDIA_SELECTOR)) rewriteOne(node);
    try {
      let traversal = fiHostSiteMediaRuntime.traversals.get(node);
      if (!traversal) {
        const owner = node?.ownerDocument || (node?.nodeType === 9 ? node : document);
        if (typeof owner?.createTreeWalker !== 'function') return changed;
        const showElement = typeof NodeFilter !== 'undefined' ? NodeFilter.SHOW_ELEMENT : 1;
        traversal = { walker: owner.createTreeWalker(node, showElement), current: null };
        fiHostSiteMediaRuntime.traversals.set(node, traversal);
      }
      const started = typeof performance?.now === 'function' ? performance.now() : Date.now();
      let inspected = 0;
      let target = traversal.current || traversal.walker.nextNode();
      while (target) {
        if (target !== node && target.matches?.(FI_HOST_SITE_MEDIA_SELECTOR)) rewriteOne(target);
        inspected++;
        target = traversal.walker.nextNode();
        const elapsed = (typeof performance?.now === 'function' ? performance.now() : Date.now()) - started;
        if (inspected >= FI_HOST_SITE_MEDIA_MAX_NODES_PER_SLICE || elapsed >= 4) break;
      }
      traversal.current = target;
      if (target) fiHostSiteMediaRuntime.continuations.add(node);
      else {
        fiHostSiteMediaRuntime.continuations.delete(node);
        fiHostSiteMediaRuntime.traversals.delete(node);
      }
    } catch {
      fiHostSiteMediaRuntime.continuations.delete(node);
      fiHostSiteMediaRuntime.traversals.delete(node);
    }
    return changed;
  }

  function fiHostCancelSiteMediaFlush() {
    if (fiHostSiteMediaRuntime.handle != null) {
      try { cancelAnimationFrame(fiHostSiteMediaRuntime.handle); } catch {}
      try { clearTimeout(fiHostSiteMediaRuntime.handle); } catch {}
    }
    fiHostSiteMediaRuntime.handle = null;
    fiHostSiteMediaRuntime.roots.clear();
  }

  function fiHostQueueSiteMediaRoot(node) {
    if (!node || document.hidden || !fiHostSiteMediaActive() || !fiHostSiteMediaRuntime.exact.size) return false;
    if (fiHostSiteMediaRuntime.roots.size < FI_HOST_SITE_MEDIA_MAX_ROOTS) fiHostSiteMediaRuntime.roots.add(node);
    if (fiHostSiteMediaRuntime.handle != null) return true;
    const flush = () => {
      fiHostSiteMediaRuntime.handle = null;
      if (document.hidden || !fiHostSiteMediaActive() || !fiHostSiteMediaRuntime.exact.size) {
        fiHostSiteMediaRuntime.roots.clear();
        return;
      }
      const started = typeof performance?.now === 'function' ? performance.now() : Date.now();
      let processed = 0;
      const continuations = [];
      for (const target of fiHostSiteMediaRuntime.roots) {
        fiHostSiteMediaRuntime.roots.delete(target);
        if (target?.isConnected !== false) {
          try { fiHostRewriteSiteMediaRoot(target); } catch {}
          if (fiHostSiteMediaRuntime.continuations.has(target)) continuations.push(target);
        }
        processed++;
        const elapsed = (typeof performance?.now === 'function' ? performance.now() : Date.now()) - started;
        if (processed >= 24 || elapsed >= 7) break;
      }
      continuations.forEach(target => {
        if (fiHostSiteMediaRuntime.roots.size < FI_HOST_SITE_MEDIA_MAX_ROOTS) fiHostSiteMediaRuntime.roots.add(target);
      });
      if (fiHostSiteMediaRuntime.roots.size) fiHostQueueSiteMediaRoot(fiHostSiteMediaRuntime.roots.values().next().value);
    };
    try {
      fiHostSiteMediaRuntime.handle = typeof requestAnimationFrame === 'function'
        ? requestAnimationFrame(flush)
        : setTimeout(flush, 16);
    } catch {
      fiHostSiteMediaRuntime.handle = setTimeout(flush, 16);
    }
    return true;
  }

  function fiHostRestoreSiteMedia() {
    try { fiHostSiteMediaRuntime.observer?.disconnect(); } catch {}
    fiHostSiteMediaRuntime.observer = null;
    fiHostCancelSiteMediaFlush();
    for (const [node, attributes] of fiHostSiteMediaRuntime.restorations) {
      if (!node || node.isConnected === false) continue;
      for (const [attribute, record] of attributes) {
        try {
          if (String(node.getAttribute?.(attribute) || '') === record.local) node.setAttribute(attribute, record.remote);
        } catch {}
      }
    }
    fiHostSiteMediaRuntime.restorations.clear();
    fiHostSiteMediaRuntime.assignments = new WeakMap();
    fiHostSiteMediaRuntime.traversals = new WeakMap();
    fiHostSiteMediaRuntime.continuations = new WeakSet();
  }

  function fiHostSyncSiteMediaRuntime(options = {}) {
    const active = fiHostSiteMediaActive() && fiHostSiteMediaRuntime.exact.size > 0;
    if (!active || options.restore === true) {
      if (options.restore === true || !fiHostSiteMediaActive()) fiHostRestoreSiteMedia();
      else {
        try { fiHostSiteMediaRuntime.observer?.disconnect(); } catch {}
        fiHostSiteMediaRuntime.observer = null;
        fiHostCancelSiteMediaFlush();
      }
      if (!state.settings.fiHostRewriteSiteMedia && fiHostSiteMediaRuntime.visibilityHandler) {
        try { document.removeEventListener('visibilitychange', fiHostSiteMediaRuntime.visibilityHandler); } catch {}
        fiHostSiteMediaRuntime.visibilityHandler = null;
      }
      return false;
    }
    if (!fiHostSiteMediaRuntime.visibilityHandler) {
      fiHostSiteMediaRuntime.visibilityHandler = () => {
        if (document.hidden) {
          try { fiHostSiteMediaRuntime.observer?.disconnect(); } catch {}
          fiHostSiteMediaRuntime.observer = null;
          fiHostCancelSiteMediaFlush();
        } else {
          fiHostSyncSiteMediaRuntime({ scan: true });
        }
      };
      try { document.addEventListener('visibilitychange', fiHostSiteMediaRuntime.visibilityHandler, { passive: true }); } catch {}
    }
    if (document.hidden) return true;
    if (options.scan !== false) {
      try { fiHostQueueSiteMediaRoot(document.documentElement || document.body || document); } catch {}
    }
    const Observer = PAGE.MutationObserver || (typeof MutationObserver === 'function' ? MutationObserver : null);
    if (fiHostSiteMediaRuntime.observer || !Observer) return true;
    try {
      const root = document.documentElement || document.body;
      if (!root) return true;
      fiHostSiteMediaRuntime.observer = new Observer(mutations => {
        if (document.hidden || !fiHostSiteMediaActive()) return;
        for (const mutation of mutations) {
          if (mutation.type === 'attributes') {
            const assignment = fiHostSiteMediaRuntime.assignments.get(mutation.target)?.get(mutation.attributeName);
            const current = String(mutation.target?.getAttribute?.(mutation.attributeName) || '');
            if (assignment?.target === current) continue;
            fiHostQueueSiteMediaRoot(mutation.target);
          } else {
            for (const added of mutation.addedNodes || []) {
              if (added?.nodeType === 1) fiHostQueueSiteMediaRoot(added);
            }
          }
        }
      });
      fiHostSiteMediaRuntime.observer.observe(root, {
        subtree: true,
        childList: true,
        attributes: true,
        attributeFilter: FI_HOST_SITE_MEDIA_ATTRIBUTES
      });
    } catch {
      try { fiHostSiteMediaRuntime.observer?.disconnect(); } catch {}
      fiHostSiteMediaRuntime.observer = null;
    }
    return true;
  }

  function fiBridgeParseProValue(row) {
    const value = row?.v ?? row?.value ?? null;
    if (typeof value !== 'string') return clone(value);
    try { return JSON.parse(value); } catch { return value; }
  }

  function fiBridgeSanitizePeerSettings(value) {
    const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
    const clean = {};
    FI_BRIDGE_SAFE_SETTING_KEYS.forEach(key => {
      if (Object.prototype.hasOwnProperty.call(source, key)) clean[key] = clone(source[key]);
    });
    return clean;
  }

  async function fiBridgeOpenExistingProDb() {
    if (typeof indexedDB === 'undefined') throw new Error('IndexedDB is unavailable.');
    if (!(PAGE.__FI_PRO_ACTIVE__ || PAGE.__freeBypassTensorRequestListenerInstalled)) {
      if (typeof indexedDB.databases !== 'function') throw new Error('Pro is not detected on this page.');
      const databases = await indexedDB.databases();
      if (!databases.some(entry => entry?.name === 'FreeBypassDB')) throw new Error('Pro IndexedDB was not found on this Tensor origin.');
    }
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('FreeBypassDB');
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error || new Error('Could not open Pro IndexedDB.'));
      request.onupgradeneeded = () => {
        try { request.transaction?.abort(); } catch {}
        reject(new Error('Pro IndexedDB does not exist yet.'));
      };
    });
  }

  async function fiBridgeReadProKeys(keys) {
    const db = await fiBridgeOpenExistingProDb();
    try {
      if (!db.objectStoreNames.contains('keyval')) throw new Error('Pro keyval store is unavailable.');
      return await new Promise((resolve, reject) => {
        const values = {};
        const tx = db.transaction('keyval', 'readonly');
        const store = tx.objectStore('keyval');
        keys.forEach(key => {
          const request = store.get(key);
          request.onsuccess = () => { values[key] = fiBridgeParseProValue(request.result); };
        });
        tx.oncomplete = () => resolve(values);
        tx.onerror = () => reject(tx.error || new Error('Pro snapshot read failed.'));
        tx.onabort = () => reject(tx.error || new Error('Pro snapshot read was aborted.'));
      });
    } finally {
      try { db.close(); } catch {}
    }
  }

  function fiBridgeCollection(value, limit) {
    const source = Array.isArray(value) ? value : (value && typeof value === 'object' ? Object.values(value) : []);
    return source.filter(entry => entry && typeof entry === 'object').slice(0, limit).map(clone);
  }

  function fiBridgeReadProLibraryLinks(tasks, items, limit) {
    let raw = {};
    try { raw = JSON.parse(PAGE.localStorage?.getItem('freeBypassLibraryLinks') || '{}') || {}; } catch {}
    const knownIds = new Set();
    for (const task of tasks || []) for (const item of Array.isArray(task?.items) ? task.items : []) {
      const id = itemId(item);
      if (id) knownIds.add(id);
    }
    for (const item of items || []) {
      const id = itemId(item);
      if (id) knownIds.add(id);
    }
    const rows = [];
    for (const [imageId, value] of Object.entries(raw && typeof raw === 'object' ? raw : {})) {
      if (!value || typeof value !== 'object' || !value.libraryEntryId || value.savedToLibrary === false) continue;
      const explicitOwner = String(value.ownerAccountId || value.libraryOwnerId || '').trim();
      if (explicitOwner ? explicitOwner !== String(state.currentAccountId || '') : !knownIds.has(String(imageId))) continue;
      rows.push({ ...clone(value), imageId: String(imageId), id: String(imageId) });
      if (rows.length >= limit) break;
    }
    return rows;
  }

  function fiBridgePeerRowMatchesCurrentAccount(entry) {
    const explicitOwner = String(entry?.ownerAccountId || entry?.userId || entry?.ownerId || entry?.rawTask?.userId || '').trim();
    if (!explicitOwner) return true;
    return !!state.currentAccountId && explicitOwner === String(state.currentAccountId);
  }

  async function fiBridgeReadProSnapshot(options = {}) {
    const limit = Math.max(1, Math.min(2000, Number(options.limit) || 800));
    await getToken().catch(() => '');
    const values = await fiBridgeReadProKeys(['freeBypassTaskCache', 'freeBypassFiItemsLibraryV1', 'freeBypassSettings']);
    const tasks = fiBridgeCollection(values.freeBypassTaskCache, limit).filter(fiBridgePeerRowMatchesCurrentAccount);
    const items = fiBridgeCollection(values.freeBypassFiItemsLibraryV1, limit).filter(fiBridgePeerRowMatchesCurrentAccount);
    const library = fiBridgeReadProLibraryLinks(tasks, items, limit);
    return Object.freeze({
      source: 'pro',
      readAt: Date.now(),
      accountId: state.currentAccountId || '',
      tasks: Object.freeze(tasks),
      items: Object.freeze(items),
      library: Object.freeze(library),
      settings: Object.freeze(fiBridgeSanitizePeerSettings(values.freeBypassSettings)),
      counts: Object.freeze({ tasks: tasks.length, items: items.length, library: library.length })
    });
  }

  async function fiBridgeSyncFromPro(options = {}) {
    const config = fiBridgeConfig();
    if (!config.enabled && options.force !== true) throw new Error('FI Bridge is disabled.');
    const snapshot = await fiBridgeReadProSnapshot(options);
    await getToken().catch(() => '');
    let importedTasks = 0;
    let importedItems = 0;
    let importedLibrary = 0;
    if (config.syncItems || options.force === true) {
      if (snapshot.tasks.length) {
        const taskMap = {};
        snapshot.tasks.forEach(task => {
          const id = taskId(task);
          if (id) taskMap[id] = task;
        });
        const records = buildObservedRecords({ data: { tasks: taskMap } });
        importedTasks = records.taskRecords.length;
        importedItems += records.itemRecords.length;
        if (state.settings.cachingEnabled && state.currentAccountId) await database.batchObserved(records.taskRecords, records.itemRecords);
      }
      const looseItems = snapshot.items.map(raw => {
        const id = itemId(raw) || String(raw?.id || '');
        if (!id) return null;
        const current = state.items.get(id) || {};
        const merged = { ...current, ...clone(raw), id, imageId: raw.imageId || id, ownerAccountId: state.currentAccountId || current.ownerAccountId || '', firstSeenAt: Number(current.firstSeenAt || raw.firstSeenAt || Date.now()), updatedAt: Date.now(), bridgeSource: 'pro' };
        state.items.set(id, merged);
        return merged;
      }).filter(Boolean);
      importedItems += looseItems.length;
      if (looseItems.length && state.settings.cachingEnabled && state.currentAccountId) await database.batchPut('items', looseItems);
      for (const link of snapshot.library || []) {
        if (fiBridgeApplyLibraryLink(link, 'pro')) importedLibrary += 1;
      }
    }
    if (config.syncSettings && snapshot.settings.libraryLinkAssign !== undefined) {
      state.settings.libraryLinkAssign = snapshot.settings.libraryLinkAssign === true;
      saveSettings();
    }
    state.bridge = { ...state.bridge, lastSyncAt: Date.now(), lastSource: 'pro', importedTasks, importedItems, importedLibrary, lastError: '' };
    emitItemsChanged('bridge-pro');
    if ((importedTasks || importedItems) && state.settings.resolveMissingUrls) scheduleAutomaticStoredResolution('bridge-pro-sync');
    try { PAGE.dispatchEvent(new CustomEvent('fi:bridge-sync', { detail: { source: 'pro', importedTasks, importedItems } })); } catch {}
    return Object.freeze({ importedTasks, importedItems, importedLibrary, status: fiBridgeStatus() });
  }

  async function fiBridgeAutoSyncFromPeer() {
    const config = fiBridgeConfig();
    if (!config.enabled || !config.autoSync || fiBridgeResolvedPrimary() !== 'pro') return null;
    try { return await fiBridgeSyncFromPro(); }
    catch (error) {
      state.bridge.lastError = String(error?.message || error).slice(0, 500);
      traceError('bridge', 'Automatic Pro bridge sync failed', error);
      return null;
    }
  }

  const database = (() => {
    let readyPromise = null;
    let openGeneration = 0;

    function open() {
      if (readyPromise) return readyPromise;
      const generation = ++openGeneration;
      readyPromise = new Promise(resolve => {
        if (typeof indexedDB === 'undefined') {
          warn('IndexedDB is unavailable; using session memory only.');
          resolve(null);
          return;
        }
        let request;
        try { request = indexedDB.open(DB_NAME, DB_VERSION); }
        catch (error) {
          warn('IndexedDB open failed.', error);
          resolve(null);
          return;
        }
        request.onupgradeneeded = event => {
          const db = event.target.result;
          if (!db.objectStoreNames.contains('kv')) db.createObjectStore('kv', { keyPath: 'key' });
          if (!db.objectStoreNames.contains('tasks')) {
            const store = db.createObjectStore('tasks', { keyPath: 'id' });
            store.createIndex('updatedAt', 'updatedAt');
          }
          if (!db.objectStoreNames.contains('items')) {
            const store = db.createObjectStore('items', { keyPath: 'id' });
            store.createIndex('updatedAt', 'updatedAt');
          }
          if (!db.objectStoreNames.contains('downloads')) {
            const store = db.createObjectStore('downloads', { keyPath: 'key' });
            store.createIndex('updatedAt', 'updatedAt');
          }
          if (!db.objectStoreNames.contains('library')) {
            const store = db.createObjectStore('library', { keyPath: 'imageId' });
            store.createIndex('updatedAt', 'updatedAt');
            store.createIndex('libraryEntryId', 'libraryEntryId', { unique: false });
          }
        };
        request.onsuccess = () => {
          const openedDb = request.result;
          state.db = openedDb;
          openedDb.onversionchange = () => {
            try { openedDb.close(); } catch {}
            if (state.db === openedDb) state.db = null;
            openGeneration += 1;
            readyPromise = null;
            state.dbReady = false;
          };
          resolve(openedDb);
        };
        request.onerror = () => {
          warn('IndexedDB initialization failed.', request.error);
          resolve(null);
        };
        request.onblocked = () => warn('IndexedDB upgrade is blocked by another tab.');
      }).then(async db => {
        if (db) await hydrate(db);
        if (generation !== openGeneration) return null;
        state.dbReady = true;
        return !db || state.db === db ? db : null;
      });
      return readyPromise;
    }

    function request(storeName, mode, operation) {
      return open().then(db => new Promise(resolve => {
        if (!db) { resolve(null); return; }
        try {
          const tx = db.transaction(storeName, mode);
          const store = tx.objectStore(storeName);
          const req = operation(store, tx);
          if (req && typeof req === 'object') {
            req.onsuccess = () => resolve(req.result ?? true);
            req.onerror = () => { traceError('idb', 'IndexedDB request failed', req.error, { storeName, mode }); resolve(null); };
          } else {
            tx.oncomplete = () => resolve(true);
            tx.onerror = () => { traceError('idb', 'IndexedDB transaction failed', tx.error, { storeName, mode }); resolve(null); };
            tx.onabort = () => { traceError('idb', 'IndexedDB transaction aborted', tx.error, { storeName, mode }); resolve(null); };
          }
        } catch (error) {
          traceError('idb', 'IndexedDB operation failed', error, { storeName, mode });
          resolve(null);
        }
      }));
    }

    function get(store, key) {
      return request(store, 'readonly', objectStore => objectStore.get(key));
    }

    function put(store, value) {
      // Re-check persisted cache policy after hydration. An early XHR response
      // may queue this call while defaults are still active, but a saved
      // cachingEnabled=false setting must win before the transaction starts.
      if (store !== 'kv') {
        return open().then(() => state.settings.cachingEnabled
          ? request(store, 'readwrite', objectStore => objectStore.put(value))
          : null);
      }
      return request(store, 'readwrite', objectStore => objectStore.put(value));
    }

    function remove(store, key) {
      return request(store, 'readwrite', objectStore => objectStore.delete(key));
    }

    function clear(store) {
      return request(store, 'readwrite', objectStore => objectStore.clear());
    }

    function cursorNewest(storeName, limit, visit, existingDb = null) {
      const run = db => new Promise(resolve => {
        if (!db) { resolve(0); return; }
        let seen = 0;
        try {
          const tx = db.transaction(storeName, 'readonly');
          const store = tx.objectStore(storeName);
          const source = store.indexNames.contains('updatedAt') ? store.index('updatedAt') : store;
          const req = source.openCursor(null, 'prev');
          req.onsuccess = event => {
            const cursor = event.target.result;
            if (!cursor || seen >= limit) { resolve(seen); return; }
            seen += 1;
            try { visit(cursor.value); } catch {}
            cursor.continue();
          };
          req.onerror = () => { traceError('idb', 'IndexedDB cursor read failed', req.error, { storeName }); resolve(seen); };
        } catch (error) { traceError('idb', 'IndexedDB cursor could not start', error, { storeName }); resolve(seen); }
      });
      // Hydration runs inside open()'s readiness chain, so it must use the
      // already-open handle instead of recursively waiting on that same chain.
      return existingDb ? run(existingDb) : open().then(run);
    }

    function batchObserved(tasks, items) {
      return open().then(db => new Promise(resolve => {
        if (!db || !state.settings.cachingEnabled) { resolve(false); return; }
        try {
          const tx = db.transaction(['tasks', 'items'], 'readwrite');
          const taskStore = tx.objectStore('tasks');
          const itemStore = tx.objectStore('items');
          tasks.forEach(task => taskStore.put(task));
          items.forEach(item => itemStore.put(item));
          tx.oncomplete = () => resolve(true);
          tx.onerror = () => { traceError('idb', 'IndexedDB observed batch failed', tx.error, { taskCount: tasks.length, itemCount: items.length }); resolve(false); };
          tx.onabort = () => { traceError('idb', 'IndexedDB observed batch aborted', tx.error, { taskCount: tasks.length, itemCount: items.length }); resolve(false); };
        } catch (error) { traceError('idb', 'IndexedDB observed batch could not start', error); resolve(false); }
      }));
    }

    function batchPut(storeName, values) {
      const rows = Array.isArray(values) ? values.filter(Boolean) : [];
      if (!rows.length) return Promise.resolve(true);
      return open().then(db => new Promise(resolve => {
        if (!db || (!state.settings.cachingEnabled && storeName !== 'kv')) { resolve(false); return; }
        try {
          const tx = db.transaction(storeName, 'readwrite');
          const store = tx.objectStore(storeName);
          rows.forEach(value => store.put(value));
          tx.oncomplete = () => resolve(true);
          tx.onerror = () => { traceError('idb', 'IndexedDB batch write failed', tx.error, { storeName, rowCount: rows.length }); resolve(false); };
          tx.onabort = () => { traceError('idb', 'IndexedDB batch write aborted', tx.error, { storeName, rowCount: rows.length }); resolve(false); };
        } catch (error) { traceError('idb', 'IndexedDB batch write could not start', error, { storeName, rowCount: rows.length }); resolve(false); }
      }));
    }

    function prune(storeName, maxEntries) {
      return open().then(db => new Promise(resolve => {
        if (!db) { resolve(0); return; }
        try {
          const tx = db.transaction(storeName, 'readwrite');
          const store = tx.objectStore(storeName);
          const countRequest = store.count();
          countRequest.onsuccess = () => {
            let remaining = Math.max(0, Number(countRequest.result || 0) - maxEntries);
            if (!remaining) return;
            const source = store.indexNames.contains('updatedAt') ? store.index('updatedAt') : store;
            const cursorRequest = source.openCursor(null, 'next');
            cursorRequest.onsuccess = event => {
              const cursor = event.target.result;
              if (!cursor || remaining <= 0) return;
              cursor.delete();
              remaining -= 1;
              cursor.continue();
            };
          };
          tx.oncomplete = () => resolve(true);
          tx.onerror = () => { traceError('idb', 'IndexedDB prune failed', tx.error, { storeName, maxEntries }); resolve(false); };
          tx.onabort = () => { traceError('idb', 'IndexedDB prune aborted', tx.error, { storeName, maxEntries }); resolve(false); };
        } catch (error) { traceError('idb', 'IndexedDB prune could not start', error, { storeName, maxEntries }); resolve(false); }
      }));
    }

    async function hydrate(db) {
      const readDirect = (storeName, key) => new Promise(resolve => {
        try {
          const req = db.transaction(storeName, 'readonly').objectStore(storeName).get(key);
          req.onsuccess = () => resolve(req.result || null);
          req.onerror = () => { traceError('idb', 'IndexedDB hydration read failed', req.error, { storeName }); resolve(null); };
        } catch (error) { traceError('idb', 'IndexedDB hydration read could not start', error, { storeName }); resolve(null); }
      });
      const [settingsRow, configRow, configMetaRow, announcementStateRow] = await Promise.all([
        readDirect('kv', SETTINGS_KEY), readDirect('kv', CONFIG_KEY), readDirect('kv', CONFIG_META_KEY), readDirect('kv', ANNOUNCEMENT_STATE_KEY)
      ]);
      const settingsRowTs = Number(settingsRow?.updatedAt || 0);
      const configRowTs = Number(configRow?.updatedAt || 0);
      const configMetaRowTs = Number(configMetaRow?.updatedAt || 0);
      const announcementStateRowTs = Number(announcementStateRow?.updatedAt || 0);
      if (settingsRowTs >= Number(state.settingsUpdatedAt || 0)) {
        state.settings = sanitizeSettings(settingsRow?.value);
        state.settingsUpdatedAt = settingsRowTs;
      }
      fiBridgeApplyBootPreference({ publishNewerSettings: true });
      fiBridgeReconcileNetworkOwner('indexeddb-hydration');
      if (configRowTs >= Number(state.configUpdatedAt || 0)) {
        state.config = configRow?.value || null;
        state.configUpdatedAt = configRowTs;
      }
      if (configMetaRowTs >= Number(state.configMetaUpdatedAt || 0)) {
        state.configMeta = configMetaRow?.value || null;
        state.configMetaUpdatedAt = configMetaRowTs;
      }
      if (announcementStateRowTs >= Number(state.announcementStateUpdatedAt || 0)) {
        const readIds = Array.isArray(announcementStateRow?.value?.readIds) ? announcementStateRow.value.readIds.map(String).filter(Boolean).slice(-100) : [];
        state.announcementState = { readIds: [...new Set(readIds)], updatedAt: announcementStateRowTs };
        state.announcementStateUpdatedAt = announcementStateRowTs;
      }
      applyRemoteContentState(state.config);
      refreshRemoteContentUi();
      if (state.settings.cachingEnabled) {
        await Promise.all([
          cursorNewest('tasks', state.settings.maxStoredTasks, entry => {
            if (!entry?.id || !entry?.ownerAccountId) return;
            const current = state.tasks.get(String(entry.id));
            if (!current || Number(entry.updatedAt || 0) > Number(current.updatedAt || 0)) state.tasks.set(String(entry.id), entry);
          }, db),
          cursorNewest('downloads', state.settings.maxStoredUrls, entry => {
            if (!entry?.key || !entry?.ownerAccountId || !isFreshCacheEntry(entry) || !isUsableMediaUrl(entry.url, 0)) return;
            const current = state.downloads.get(entry.key);
            if (!current || Number(entry.updatedAt || 0) > Number(current.updatedAt || 0)) state.downloads.set(entry.key, entry);
          }, db),
          cursorNewest('items', state.settings.maxStoredItems, entry => {
            if (!entry?.id || !entry?.ownerAccountId || !isFreshCacheEntry(entry)) return;
            const key = String(entry.id);
            const current = state.items.get(key);
            if (!current || Number(entry.updatedAt || 0) > Number(current.updatedAt || 0)) state.items.set(key, entry);
          }, db),
          cursorNewest('library', state.settings.maxStoredLibraryLinks, entry => {
            if (!entry?.imageId || !entry?.ownerAccountId) return;
            const key = String(entry.imageId);
            const current = state.libraryLinks.get(key);
            if (!current || Number(entry.updatedAt || 0) > Number(current.updatedAt || 0)) state.libraryLinks.set(key, entry);
            if (entry.libraryEntryId) state.libraryEntries.set(String(entry.libraryEntryId), entry.libraryEntryData || entry);
          }, db)
        ]);
        // The dedicated Library store is authoritative and intentionally
        // outlives task/item cache-age trimming. Recreate a lightweight card
        // projection so a saved Library item remains visible after restart
        // even when its generation task has already been removed.
        state.libraryLinks.forEach((link, imageId) => {
          const current = state.items.get(String(imageId));
          if (current && Number(current.updatedAt || 0) >= Number(link.updatedAt || 0)) return;
          state.items.set(String(imageId), {
            ...(current || {}), ...link,
            id: String(imageId), imageId: String(imageId),
            mimeType: current?.mimeType || link.libraryMimeType || '',
            url: link.librarySignedUrl || link.libraryThumbnailUrl || current?.url || '',
            ownerAccountId: link.ownerAccountId,
            updatedAt: Number(link.updatedAt || Date.now())
          });
        });
      }
      emitItemsChanged('hydrate');
      log('IndexedDB hydration complete', { tasks: state.tasks.size, items: state.items.size, urls: state.downloads.size, libraryLinks: state.libraryLinks.size });
    }

    return { open, get, put, remove, clear, batchObserved, batchPut, prune };
  })();

  function saveSettings() {
    state.settings = sanitizeSettings(state.settings);
    state.settingsUpdatedAt = Date.now();
    database.put('kv', { key: SETTINGS_KEY, value: clone(state.settings), updatedAt: state.settingsUpdatedAt });
    if (state.ui?.panel && state.activeTab === 'settings') renderSettings();
  }

  function parseAmzDate(value) {
    const match = String(value || '').match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z$/);
    if (!match) return null;
    return Date.UTC(+match[1], +match[2] - 1, +match[3], +match[4], +match[5], +match[6]);
  }

  function normalizeTimestampMs(value) {
    if (value == null || value === '') return null;
    const numeric = Number(value);
    if (Number.isFinite(numeric) && numeric > 0) return numeric < 1e12 ? numeric * 1000 : numeric;
    const parsed = Date.parse(String(value));
    return Number.isFinite(parsed) ? parsed : null;
  }

  function taskExpiryMs(task) {
    return normalizeTimestampMs(task?.expireAt ?? task?.expiresAt ?? task?.expiredAt ?? task?.expirationTime);
  }

  function isTaskExpired(task, now = Date.now()) {
    const expiry = Number(task?.taskExpireAtMs || taskExpiryMs(task));
    return Number.isFinite(expiry) && expiry > 0 && expiry <= Number(now);
  }

  function signedUrlExpiry(url) {
    try {
      const parsed = new URL(String(url), location.href);
      const amzDate = parsed.searchParams.get('X-Amz-Date') || parsed.searchParams.get('x-amz-date');
      const amzSeconds = Number(parsed.searchParams.get('X-Amz-Expires') || parsed.searchParams.get('x-amz-expires'));
      if (Number.isFinite(amzSeconds) && amzSeconds > 0) return (parseAmzDate(amzDate) || Date.now()) + amzSeconds * 1000;
      const absolute = parsed.searchParams.get('Expires') || parsed.searchParams.get('expires')
        || parsed.searchParams.get('exp') || parsed.searchParams.get('expiry');
      return normalizeTimestampMs(absolute);
    } catch { return null; }
  }

  function isBlockedPlaceholderUrl(url) {
    if (!url) return false;
    return /(?:\/system\/)?(?:reviewing\.png|forbidden\.jpg)|\/forbidden_[^/?#]+\.(?:jpe?g|png|webp)(?:[?#]|$)/i.test(String(url));
  }

  function isDownloadEndpoint(url) {
    try {
      const parsed = new URL(normalizeUrl(url));
      const endpoint = `${parsed.origin}${parsed.pathname}`;
      return endpoint === API_URL_IMAGE || endpoint === API_URL_VIDEO;
    } catch { return false; }
  }

  function downloadEndpointKind(url) {
    try { return new URL(normalizeUrl(url)).pathname.endsWith('/video/download') ? 'video' : 'image'; }
    catch { return 'image'; }
  }

  function isUsableMediaUrl(url, minRemainingMs = SIGNED_URL_INTERCEPT_BUFFER_MS) {
    if (!url || isBlockedPlaceholderUrl(url) || isDownloadEndpoint(url)) return false;
    const expiry = signedUrlExpiry(url);
    return expiry == null || expiry - Date.now() > minRemainingMs;
  }

  function mediaKind(mimeType, fallback = '') {
    const mime = String(mimeType || '').toLowerCase();
    if (mime.startsWith('video/')) return 'video';
    if (mime.startsWith('image/')) return 'image';
    return fallback;
  }

  function downloadKey(id, kind = '') {
    return `${String(id)}|${kind || 'media'}`;
  }

  function cacheDownload(id, url, mimeType = '', kindHint = '') {
    const cleanId = String(id || '').trim();
    if (!cleanId || !state.currentAccountId || !isUsableMediaUrl(url, 0) || isFiHostLocalUrl(url)) return false;
    const kind = kindHint || mediaKind(mimeType) || 'media';
    const entry = {
      key: downloadKey(cleanId, kind),
      id: cleanId,
      kind,
      mimeType: String(mimeType || ''),
      url: String(url),
      ownerAccountId: state.currentAccountId || '',
      expAt: signedUrlExpiry(url),
      updatedAt: Date.now()
    };
    state.downloads.set(entry.key, entry);
    if (state.settings.cachingEnabled) database.put('downloads', entry);
    const existing = storedItemForCurrentAccount(cleanId);
    if (existing) {
      const libraryUrl = state.settings.libraryLinkAssign && state.settings.preferLibraryUrls
        ? libraryCandidateUrl(libraryLinkForCurrentAccount(cleanId), 0)
        : '';
      const merged = {
        ...existing,
        bypassedUrl: entry.url,
        url: libraryUrl || entry.url,
        ownerAccountId: state.currentAccountId || existing.ownerAccountId || '',
        updatedAt: Date.now()
      };
      state.items.set(cleanId, merged);
      if (state.settings.cachingEnabled) database.put('items', merged);
    }
    return true;
  }

  function isEntryForCurrentAccount(entry) {
    const owner = String(entry?.ownerAccountId || '').trim();
    return !!owner && !!state.currentAccountId && owner === String(state.currentAccountId);
  }

  function isFreshCacheEntry(entry) {
    const updatedAt = Number(entry?.updatedAt || 0);
    if (!Number.isFinite(updatedAt) || updatedAt <= 0) return false;
    return Date.now() - updatedAt <= state.settings.cacheDays * 86_400_000;
  }

  function storedItemForCurrentAccount(id) {
    const key = String(id || '').trim();
    if (!key) return null;
    const entry = state.items.get(key);
    if (!entry || !isEntryForCurrentAccount(entry)) return null;
    if (isFreshCacheEntry(entry)) return entry;
    // cacheDays expires temporary task/download evidence, not the dedicated
    // Library association. Keep a lightweight Library-backed item projection
    // so it remains visible and resolvable across long-lived sessions.
    const library = libraryLinkForCurrentAccount(key);
    if (library) {
      const libraryUrl = libraryCandidateUrl(library, 0);
      const detached = {
        id: key,
        imageId: key,
        mimeType: entry.mimeType || library.libraryMimeType || '',
        ...library,
        taskExpired: true,
        taskId: '',
        taskExpireAtMs: null,
        ...(libraryUrl ? { url: libraryUrl, bypassedUrl: libraryUrl } : {}),
        updatedAt: Date.now()
      };
      state.items.set(key, detached);
      if (state.settings.cachingEnabled) database.put('items', detached);
      return detached;
    }
    state.items.delete(key);
    if (state.dbReady) database.remove('items', key);
    return null;
  }

  function libraryLinkForCurrentAccount(id) {
    const entry = state.libraryLinks.get(String(id || '').trim());
    return entry && isEntryForCurrentAccount(entry) ? entry : null;
  }

  function cachedDownload(id, mimeType = '', minRemainingMs = SIGNED_URL_INTERCEPT_BUFFER_MS) {
    if (!state.settings.cachingEnabled) return null;
    const cleanId = String(id || '').trim();
    const preferred = mediaKind(mimeType);
    const keys = [downloadKey(cleanId, preferred), downloadKey(cleanId, 'media'), downloadKey(cleanId, 'image'), downloadKey(cleanId, 'video')];
    for (const key of keys) {
      const entry = state.downloads.get(key);
      if (!entry) continue;
      if (!isEntryForCurrentAccount(entry)) continue;
      if (isFiHostLocalUrl(entry.url)) {
        state.downloads.delete(key);
        if (state.dbReady) database.remove('downloads', key);
        continue;
      }
      if (!isFreshCacheEntry(entry)) {
        state.downloads.delete(key);
        database.remove('downloads', key);
        continue;
      }
      if (isUsableMediaUrl(entry.url, minRemainingMs)) {
        state.stats.cacheHits += 1;
        return entry.url;
      }
      if (!isUsableMediaUrl(entry.url, 0)) {
        state.downloads.delete(key);
        database.remove('downloads', key);
      }
    }
    return null;
  }

  function itemId(item) {
    return String(item?.imageId || item?.id || '').trim();
  }

  function isTensorDownloadableId(value) {
    if (!['string', 'number', 'bigint'].includes(typeof value)) return false;
    const id = String(value).trim();
    return /^\d{6,}$/.test(id) && id !== '0';
  }

  function libraryCandidateUrl(entry, minRemainingMs = 0) {
    if (!entry) return null;
    const signed = entry.librarySignedUrl || entry.signedUrl || '';
    if (isUsableMediaUrl(signed, minRemainingMs) && !isFiHostLocalUrl(signed)) return signed;
    if (state.settings.libraryUseThumbnailFallback !== false) {
      const thumbnail = entry.libraryThumbnailUrl || entry.thumbnailUrl || '';
      if (isUsableMediaUrl(thumbnail, minRemainingMs) && !isFiHostLocalUrl(thumbnail)) return thumbnail;
    }
    return null;
  }

  function candidateUrl(item, minRemainingMs = SIGNED_URL_INTERCEPT_BUFFER_MS, options = {}) {
    if (!item) return null;
    if (options.remoteOnly !== true) {
      const local = fiHostLocalCandidate(item);
      if (local) return local;
    }
    const ignoreLibrary = options.ignoreLibrary === true;
    const id = itemId(item);
    const library = libraryLinkForCurrentAccount(id);
    if (!ignoreLibrary && state.settings.libraryLinkAssign && library
      && (state.settings.preferLibraryUrls || state.settings.librarySkipDownloadRefresh)) {
      const permanent = libraryCandidateUrl(library, 0);
      if (permanent) return permanent;
    }
    const itemOwner = String(item?.ownerAccountId || '').trim();
    if (itemOwner && !isEntryForCurrentAccount(item)) return null;
    const itemFresh = !itemOwner || isFreshCacheEntry(item);
    const cached = cachedDownload(id, item.mimeType, minRemainingMs);
    if (cached) return cached;
    const stored = storedItemForCurrentAccount(id);
    const libraryUrls = ignoreLibrary ? new Set([
      library?.librarySignedUrl, library?.signedUrl, library?.libraryThumbnailUrl, library?.thumbnailUrl,
      item.librarySignedUrl, item.libraryThumbnailUrl, stored?.librarySignedUrl, stored?.libraryThumbnailUrl
    ].filter(Boolean).map(String)) : null;
    const candidates = [
      ...(itemFresh ? [item.originalTaskUrl, item.bypassedUrl, item.downloadUrl, item.mediaUrl, item.resourceUrl] : []),
      stored?.originalTaskUrl, stored?.bypassedUrl, stored?.downloadUrl, stored?.mediaUrl, stored?.resourceUrl, stored?.url
    ];
    const taskOrDownloadUrl = candidates.find(url => isUsableMediaUrl(url, minRemainingMs) && !isFiHostLocalUrl(url)
      && (!ignoreLibrary || !libraryUrls.has(String(url))));
    if (taskOrDownloadUrl) return taskOrDownloadUrl;
    // A linked Library object remains a valid fallback even when the user has
    // asked for temporary generation URLs to be preferred.
    return !ignoreLibrary && state.settings.libraryLinkAssign ? libraryCandidateUrl(library, 0) : null;
  }

  function hasReusableLibraryUrl(item) {
    if (!state.settings.libraryLinkAssign || state.settings.librarySkipDownloadRefresh === false) return false;
    return !!libraryCandidateUrl(libraryLinkForCurrentAccount(itemId(item)), 0);
  }

  function needsDownloadRefresh(item, minRemainingMs = SIGNED_URL_INTERCEPT_BUFFER_MS) {
    if (!item || hasReusableLibraryUrl(item)) return false;
    return !candidateUrl(item, minRemainingMs, { ignoreLibrary: true });
  }

  function looksBlocked(item) {
    return !!item && (item.invalid === true || [item.url, item.downloadUrl, item.processImageUrl, item.previewUrl].some(isBlockedPlaceholderUrl));
  }

  function withBypass(item, bypassUrl) {
    if (!item || !bypassUrl) return item;
    const next = { ...item, blockedOnOrigin: item.blockedOnOrigin || looksBlocked(item), bypassedUrl: bypassUrl };
    ['url', 'downloadUrl', 'mediaUrl', 'resourceUrl', 'originUrl'].forEach(key => {
      if (key === 'url' || !next[key] || isBlockedPlaceholderUrl(next[key])) next[key] = bypassUrl;
    });
    ['processImageUrl', 'previewUrl', 'thumbnailUrl', 'coverUrl', 'posterUrl', 'src'].forEach(key => {
      if (next[key] !== undefined && (!next[key] || isBlockedPlaceholderUrl(next[key]))) next[key] = bypassUrl;
    });
    next.invalid = false;
    next.status = 'FINISH';
    next.needConvertUrl = false;
    next.processPercent = 100;
    next.processProgress = 100;
    if (typeof next.feedbackType === 'string' && next.feedbackType !== 'DEFAULT') next.feedbackType = 'DEFAULT';
    const fileName = String(next.downloadFileName || next.fileName || '').trim();
    if (fileName && !fileName.startsWith('FREEInterent-')) next.downloadFileName = `FREEInterent-${fileName}`;
    return next;
  }

  function normalizeTask(task) {
    if (!task || typeof task !== 'object') return task;
    const next = { ...task };
    if (String(next.status || '').toUpperCase() === 'FINISH') {
      if (typeof next.failMessage === 'string') next.failMessage = '';
      if (typeof next.failCode === 'string') next.failCode = 'DEFAULT';
    }
    return next;
  }

  function taskId(task) {
    return String(task?.taskId || task?.routeId || task?.id || '').trim();
  }

  function isTaskRecord(value) {
    return !!value && typeof value === 'object' && !Array.isArray(value)
      && !!taskId(value) && (Array.isArray(value.items) || value.status != null);
  }

  function taskListFromBody(body) {
    if (!body || typeof body !== 'object') return [];
    const containers = [body?.data?.tasks, body?.tasks, body?.data?.results, body?.results];
    for (const value of containers) {
      if (Array.isArray(value)) return value.filter(isTaskRecord);
      if (value && typeof value === 'object') return Object.values(value).filter(isTaskRecord);
    }
    const single = body?.data?.task || body?.task || body?.data?.result?.task;
    if (isTaskRecord(single)) return [single];
    if (isTaskRecord(body?.data)) return [body.data];
    if (isTaskRecord(body?.result)) return [body.result];
    return [];
  }

  function mapTasksInBody(body, mapper) {
    if (!body || typeof body !== 'object') return { changed: false, body };
    let changed = false;
    const mapArray = list => list.map(task => {
      const next = mapper(task);
      if (next !== task) changed = true;
      return next;
    });
    const mapObject = object => Object.fromEntries(Object.entries(object).map(([key, task]) => {
      const next = mapper(task);
      if (next !== task) changed = true;
      return [key, next];
    }));
    if (Array.isArray(body?.data?.tasks)) {
      const tasks = mapArray(body.data.tasks);
      return changed ? { changed, body: { ...body, data: { ...body.data, tasks } } } : { changed, body };
    }
    if (body?.data?.tasks && typeof body.data.tasks === 'object') {
      const tasks = mapObject(body.data.tasks);
      return changed ? { changed, body: { ...body, data: { ...body.data, tasks } } } : { changed, body };
    }
    if (body?.data?.task && typeof body.data.task === 'object') {
      const task = mapper(body.data.task);
      return task !== body.data.task ? { changed: true, body: { ...body, data: { ...body.data, task } } } : { changed: false, body };
    }
    if (Array.isArray(body.tasks)) {
      const tasks = mapArray(body.tasks);
      return changed ? { changed, body: { ...body, tasks } } : { changed, body };
    }
    if (body.tasks && typeof body.tasks === 'object') {
      const tasks = mapObject(body.tasks);
      return changed ? { changed, body: { ...body, tasks } } : { changed, body };
    }
    if (Array.isArray(body?.data?.results)) {
      const results = mapArray(body.data.results);
      return changed ? { changed, body: { ...body, data: { ...body.data, results } } } : { changed, body };
    }
    if (Array.isArray(body.results)) {
      const results = mapArray(body.results);
      return changed ? { changed, body: { ...body, results } } : { changed, body };
    }
    if (isTaskRecord(body?.data)) {
      const data = mapper(body.data);
      return data !== body.data ? { changed: true, body: { ...body, data } } : { changed: false, body };
    }
    if (isTaskRecord(body?.result)) {
      const result = mapper(body.result);
      return result !== body.result ? { changed: true, body: { ...body, result } } : { changed: false, body };
    }
    return { changed: false, body };
  }

  function isFinishedTask(task) {
    return ['FINISH', 'FINISHED', 'COMPLETED', 'SUCCESS'].includes(String(task?.status || '').toUpperCase());
  }

  function patchBodySync(body) {
    let patchedItems = 0;
    const mapped = mapTasksInBody(body, rawTask => {
      if (!rawTask || !isFinishedTask(rawTask) || !Array.isArray(rawTask.items) || isTaskExpired(rawTask)) return rawTask;
      let taskChanged = false;
      const items = rawTask.items.map(item => {
        if (!item || !itemId(item)) return item;
        const bypass = candidateUrl(item);
        if (!bypass || (!looksBlocked(item) && item.bypassedUrl === bypass && item.url === bypass)) return item;
        taskChanged = true;
        patchedItems += 1;
        return withBypass(item, bypass);
      });
      if (!taskChanged) return rawTask;
      return { ...normalizeTask(rawTask), items };
    });
    return mapped.changed ? { changed: true, patchedItems, body: mapped.body } : { changed: false, body, patchedItems: 0 };
  }

  function buildObservedRecords(body) {
    const taskRecords = [];
    const itemRecords = [];
    const now = Date.now();
    taskListFromBody(body).forEach(task => {
      const id = taskId(task);
      if (!id) return;
      const previousTask = state.tasks.get(id) || null;
      const taskRecord = {
        ...clone(task), id, taskId: task.taskId || id,
        ownerAccountId: state.currentAccountId || '',
        taskExpireAtMs: taskExpiryMs(task), updatedAt: now
      };
      if (state.settings.libraryAssignToTaskStore && Array.isArray(taskRecord.items)) {
        taskRecord.items = taskRecord.items.map(rawItem => {
          const library = libraryLinkForCurrentAccount(itemId(rawItem));
          return library ? projectTaskItemWithLibrary(rawItem, library) : rawItem;
        });
      }
      state.tasks.set(id, taskRecord);
      taskRecords.push(taskRecord);
      (Array.isArray(task.items) ? task.items : []).forEach(rawItem => {
        const idValue = itemId(rawItem);
        if (!idValue) return;
        const current = storedItemForCurrentAccount(idValue);
        const merged = {
          ...(current || {}),
          ...clone(rawItem),
          id: idValue,
          imageId: rawItem.imageId || idValue,
          originalTaskUrl: fiHostSiteMediaIdentity(rawItem.url) ? rawItem.url : (current?.originalTaskUrl || ''),
          taskId: task.taskId || task.routeId || id,
          ownerAccountId: state.currentAccountId || current?.ownerAccountId || '',
          taskCreatedAt: task.createdAt || null,
          taskExpireAtMs: taskExpiryMs(task),
          taskStatus: task.status || '',
          blockedOnOrigin: current?.blockedOnOrigin || looksBlocked(rawItem),
          firstSeenAt: Number(current?.firstSeenAt || now),
          updatedAt: now
        };
        const library = libraryLinkForCurrentAccount(idValue);
        if (library) Object.assign(merged, library);
        const bypass = candidateUrl(merged, 0);
        const finalItem = bypass ? { ...withBypass(merged, bypass), updatedAt: now } : merged;
        state.items.set(idValue, finalItem);
        itemRecords.push(finalItem);
        fiHostScheduleItem(finalItem, 'task-observed');
      });
      scheduleTaskDelivery(previousTask, taskRecord);
    });
    return { taskRecords, itemRecords };
  }

  function persistObservedBody(body) {
    const records = buildObservedRecords(body);
    trimMap(state.items, state.settings.maxStoredItems);
    if (state.settings.cachingEnabled && state.currentAccountId) {
      const ownedTasks = records.taskRecords.filter(entry => isEntryForCurrentAccount(entry));
      const ownedItems = records.itemRecords.filter(entry => isEntryForCurrentAccount(entry));
      database.batchObserved(ownedTasks, ownedItems).then(() => maybePrune());
    }
    emitItemsChanged('query');
  }

  function maybePrune() {
    const now = Date.now();
    if (now - state.pruneAt < 60_000) return;
    state.pruneAt = now;
    database.prune('tasks', state.settings.maxStoredTasks);
    database.prune('items', state.settings.maxStoredItems);
    database.prune('downloads', state.settings.maxStoredUrls);
    database.prune('library', state.settings.maxStoredLibraryLinks);
    trimMap(state.tasks, state.settings.maxStoredTasks);
    trimMap(state.items, state.settings.maxStoredItems);
    trimMap(state.downloads, state.settings.maxStoredUrls);
  }

  function trimMap(map, max) {
    if (map.size <= max) return;
    [...map.entries()]
      .sort((a, b) => Number(b[1]?.updatedAt || 0) - Number(a[1]?.updatedAt || 0))
      .slice(max)
      .forEach(([key]) => map.delete(key));
  }

  function normalizeUrl(input) {
    try {
      const raw = typeof input === 'string' ? input : (input instanceof URL ? input.href : input?.url);
      if (!raw) return '';
      const url = new URL(String(raw), location.href);
      url.hash = '';
      return url.href;
    } catch { return String(input || ''); }
  }

  function isTaskQueryEndpoint(input) {
    try {
      const url = new URL(normalizeUrl(input));
      return url.origin === TENSOR_API_ORIGIN && url.pathname === TASK_QUERY_PATH;
    } catch { return false; }
  }

  function tensorEndpointKind(input) {
    try {
      const url = new URL(normalizeUrl(input));
      if (url.origin !== TENSOR_API_ORIGIN) return '';
      const path = url.pathname.replace(/\/+$/, '') || '/';
      if (path === TASK_QUERY_PATH) return 'query';
      if (path === MGET_TASK_PATH) return 'mget';
      if (path === DIRECT_TASK_PATH) return 'task';
      if (path === TASKS_PATH || path.startsWith(`${TASKS_PATH}/`)) return 'tasks';
      const libraryBase = LIBRARY_ENTRY_PREFIX.replace(/\/$/, '');
      if (path === libraryBase || path.startsWith(libraryBase + '/')) return 'library';
      if (path === new URL(API_URL_IMAGE).pathname) return 'download-image';
      if (path === new URL(API_URL_VIDEO).pathname) return 'download-video';
      return '';
    } catch { return ''; }
  }

  function isTaskApiEndpoint(input) {
    return ['query', 'mget', 'task', 'tasks'].includes(tensorEndpointKind(input));
  }

  function isLibraryEndpoint(input) {
    return tensorEndpointKind(input) === 'library';
  }

  function isRelevantTensorEndpoint(input) {
    return !!tensorEndpointKind(input);
  }

  function parseRequestPayload(body) {
    if (body == null) return {};
    if (typeof body === 'string') {
      try { return JSON.parse(body); } catch {
        try { return Object.fromEntries(new URLSearchParams(body)); } catch { return {}; }
      }
    }
    if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) return Object.fromEntries(body);
    if (typeof FormData !== 'undefined' && body instanceof FormData) {
      const result = {};
      body.forEach((value, key) => {
        if (key in result) result[key] = [...(Array.isArray(result[key]) ? result[key] : [result[key]]), value];
        else result[key] = value;
      });
      return result;
    }
    return body && typeof body === 'object' ? body : {};
  }

  function libraryEndpointInfo(input, method = '') {
    try {
      const url = new URL(normalizeUrl(input));
      if (url.origin !== TENSOR_API_ORIGIN || !url.pathname.startsWith(LIBRARY_ENTRY_PREFIX)) return null;
      const segment = decodeURIComponent(url.pathname.slice(LIBRARY_ENTRY_PREFIX.length).split('/')[0] || '');
      const keyword = new Set(['create', 'delete', 'list', 'update', 'download', 'batch', 'move', 'copy']);
      const restEntryId = segment && !keyword.has(segment) ? segment : '';
      const upperMethod = String(method || '').toUpperCase();
      return {
        action: restEntryId && (!upperMethod || upperMethod === 'DELETE') ? 'delete' : segment,
        restEntryId
      };
    } catch { return null; }
  }

  function libraryEntryForImage(imageId) {
    return libraryLinkForCurrentAccount(String(imageId || ''));
  }

  function imageIdForLibraryEntry(entryId) {
    const cleanEntryId = String(entryId || '').trim();
    if (!cleanEntryId) return '';
    for (const [imageId, row] of state.libraryLinks) {
      if (isEntryForCurrentAccount(row) && String(row.libraryEntryId || '') === cleanEntryId) return String(imageId);
    }
    for (const [imageId, item] of state.items) {
      if (isEntryForCurrentAccount(item) && String(item.libraryEntryId || '') === cleanEntryId) return String(imageId);
    }
    return '';
  }

  function libraryPatch(imageId, entry) {
    const id = String(imageId || '').trim();
    if (!id || !entry?.id || !state.currentAccountId) return null;
    return {
      imageId: id,
      savedToLibrary: true,
      libraryEntryId: String(entry.id),
      librarySignedUrl: String(entry.signedUrl || ''),
      libraryThumbnailUrl: String(entry.thumbnailUrl || ''),
      libraryOriginalPath: String(entry.originalPath || ''),
      libraryFileName: String(entry.fileName || ''),
      libraryCreatedAt: entry.createdAt || '',
      libraryModifiedAt: entry.modifiedAt || '',
      libraryOwnerId: String(entry.ownerId || ''),
      libraryType: String(entry.type || ''),
      libraryMimeType: String(entry.exif?.mimeType || entry.mimeType || ''),
      libraryWidth: Number(entry.exif?.width || entry.width || 0),
      libraryHeight: Number(entry.exif?.height || entry.height || 0),
      libraryFileSize: entry.exif?.fileSizeInBytes || entry.fileSizeInBytes || '',
      libraryEntryData: clone(entry),
      ownerAccountId: state.currentAccountId,
      linkedAt: Date.now(),
      updatedAt: Date.now()
    };
  }

  const LIBRARY_PROJECTION_FIELDS = Object.freeze([
    'savedToLibrary', 'libraryEntryId', 'librarySignedUrl', 'libraryThumbnailUrl',
    'libraryOriginalPath', 'libraryFileName', 'libraryCreatedAt', 'libraryModifiedAt',
    'libraryOwnerId', 'libraryType', 'libraryMimeType', 'libraryWidth', 'libraryHeight',
    'libraryFileSize', 'libraryEntryData', 'libraryUrlAssigned', 'libraryLinkedAt'
  ]);

  function fiBridgeApplyLibraryLink(raw, source = 'peer') {
    const id = String(raw?.imageId || raw?.id || '').trim();
    const libraryEntryId = String(raw?.libraryEntryId || raw?.libraryEntryData?.id || '').trim();
    const explicitOwner = String(raw?.ownerAccountId || '').trim();
    if (!id || !libraryEntryId || !state.currentAccountId || (explicitOwner && explicitOwner !== String(state.currentAccountId))) return false;
    const link = {
      imageId: id,
      savedToLibrary: true,
      libraryEntryId,
      ownerAccountId: state.currentAccountId,
      linkedAt: Number(raw?.linkedAt || raw?.libraryLinkedAt || Date.now()),
      updatedAt: Date.now(),
      bridgeSource: source
    };
    for (const key of LIBRARY_PROJECTION_FIELDS) {
      if (key === 'savedToLibrary' || key === 'libraryEntryId') continue;
      if (Object.prototype.hasOwnProperty.call(raw || {}, key)) link[key] = clone(raw[key]);
    }
    state.libraryLinks.set(id, link);
    if (link.libraryEntryData?.id) state.libraryEntries.set(String(link.libraryEntryData.id), clone(link.libraryEntryData));
    const existing = storedItemForCurrentAccount(id) || state.items.get(id) || {};
    const base = { ...existing, ...link, id, imageId: id, ownerAccountId: state.currentAccountId };
    const merged = projectTaskItemWithLibrary(base, link);
    state.items.set(id, merged);
    if (state.settings.cachingEnabled) {
      database.put('library', link);
      database.put('items', merged);
    }
    updateTaskStoreLibraryProjection(id, link, false);
    fiHostScheduleItem(merged, `bridge-library-${source}`);
    fiHostRebuildSiteMediaIndex();
    return true;
  }

  function projectTaskItemWithLibrary(rawItem, link) {
    if (!rawItem || !link || !state.settings.libraryAssignToTaskStore) return rawItem;
    const url = libraryCandidateUrl(link, 0);
    const next = {
      ...rawItem,
      ...link,
      originalTaskUrl: rawItem.originalTaskUrl !== undefined ? rawItem.originalTaskUrl : (rawItem.url || ''),
      libraryUrlAssigned: !!url,
      libraryLinkedAt: Number(link.linkedAt || Date.now())
    };
    if (url && (state.settings.preferLibraryUrls || state.settings.librarySkipDownloadRefresh)) {
      return withBypass(next, url);
    }
    return next;
  }

  function clearTaskItemLibraryProjection(rawItem, removedLink = null) {
    if (!rawItem) return rawItem;
    const next = { ...rawItem };
    const removedUrls = new Set([
      removedLink?.librarySignedUrl, removedLink?.libraryThumbnailUrl,
      rawItem.librarySignedUrl, rawItem.libraryThumbnailUrl
    ].filter(Boolean).map(String));
    LIBRARY_PROJECTION_FIELDS.forEach(key => { delete next[key]; });
    if (Object.prototype.hasOwnProperty.call(next, 'originalTaskUrl')) {
      next.url = next.originalTaskUrl || '';
      delete next.originalTaskUrl;
    }
    if (removedUrls.has(String(next.bypassedUrl || ''))) delete next.bypassedUrl;
    if (removedUrls.has(String(next.downloadUrl || ''))) delete next.downloadUrl;
    if (removedUrls.has(String(next.mediaUrl || ''))) delete next.mediaUrl;
    if (removedUrls.has(String(next.resourceUrl || ''))) delete next.resourceUrl;
    return next;
  }

  function updateTaskStoreLibraryProjection(imageId, link, unlink = false) {
    if (!state.settings.libraryAssignToTaskStore) return 0;
    const id = String(imageId || '').trim();
    if (!id) return 0;
    const changedTasks = [];
    for (const [taskKey, task] of state.tasks) {
      if (!isEntryForCurrentAccount(task) || !Array.isArray(task.items)) continue;
      let changed = false;
      const items = task.items.map(rawItem => {
        if (itemId(rawItem) !== id) return rawItem;
        changed = true;
        return unlink ? clearTaskItemLibraryProjection(rawItem, link) : projectTaskItemWithLibrary(rawItem, link);
      });
      if (!changed) continue;
      const nextTask = { ...task, items, updatedAt: Date.now() };
      state.tasks.set(taskKey, nextTask);
      changedTasks.push(nextTask);
    }
    if (changedTasks.length && state.settings.cachingEnabled) database.batchPut('tasks', changedTasks);
    state.stats.libraryTaskAssignments += changedTasks.length;
    return changedTasks.length;
  }

  function applyLibraryLink(imageId, entry) {
    if (!state.settings.libraryLinkAssign) return false;
    const patch = libraryPatch(imageId, entry);
    if (!patch) return false;
    state.libraryLinks.set(patch.imageId, patch);
    state.libraryEntries.set(patch.libraryEntryId, clone(entry));
    const existing = storedItemForCurrentAccount(patch.imageId) || state.items.get(patch.imageId) || {};
    const merged = {
      ...existing,
      ...patch,
      id: patch.imageId,
      imageId: patch.imageId,
      originalTaskUrl: existing.originalTaskUrl !== undefined ? existing.originalTaskUrl : (existing.url || ''),
      mimeType: existing.mimeType || patch.libraryMimeType || '',
      url: ((state.settings.preferLibraryUrls || state.settings.librarySkipDownloadRefresh) && libraryCandidateUrl(patch, 0))
        ? libraryCandidateUrl(patch, 0)
        : (existing.url || patch.libraryThumbnailUrl || '')
    };
    state.items.set(patch.imageId, merged);
    if (state.settings.cachingEnabled) {
      database.put('library', patch);
      database.put('items', merged);
    }
    updateTaskStoreLibraryProjection(patch.imageId, patch, false);
    fiHostScheduleItem(merged, 'library-link');
    fiHostRebuildSiteMediaIndex();
    return true;
  }

  function unlinkLibraryEntry(entryId) {
    const id = imageIdForLibraryEntry(entryId);
    if (!id) return false;
    const removedLink = state.libraryLinks.get(id) || null;
    const existing = state.items.get(id);
    state.libraryLinks.delete(id);
    state.libraryEntries.delete(String(entryId));
    database.remove('library', id);
    if (existing) {
      const next = clearTaskItemLibraryProjection(existing, removedLink);
      next.savedToLibrary = false;
      next.updatedAt = Date.now();
      const fallback = cachedDownload(id, next.mimeType, 0);
      if (fallback) next.url = fallback;
      state.items.set(id, next);
      if (state.settings.cachingEnabled) database.put('items', next);
    }
    updateTaskStoreLibraryProjection(id, removedLink, true);
    fiHostRebuildSiteMediaIndex();
    return true;
  }

  function processLibraryPayload(url, requestBody, payload, method = '') {
    try {
      const info = libraryEndpointInfo(url, method);
      if (!info) return 0;
      const body = parseRequestPayload(requestBody);
      const explicitFailure = payload && payload.code != null && String(payload.code) !== '0';
      if (explicitFailure) {
        traceError('library', 'Tensor Library response reported a failure', new Error(String(payload?.message || `code ${payload.code}`)), { action: info.action });
        return 0;
      }
      state.stats.libraryResponses += 1;
      let changed = 0;
      if (info.action === 'create') {
        const entry = payload?.data?.result || payload?.result;
        const imageId = String(body?.generationImageId || body?.imageId || '').trim();
        if (entry?.id) {
          state.libraryEntries.set(String(entry.id), clone(entry));
          if (imageId && applyLibraryLink(imageId, entry)) changed += 1;
        }
      } else if (info.action === 'list') {
        const entries = Array.isArray(payload?.data?.results) ? payload.data.results : (Array.isArray(payload?.results) ? payload.results : []);
        entries.forEach(entry => {
          if (!entry?.id) return;
          state.libraryEntries.set(String(entry.id), clone(entry));
          const imageId = imageIdForLibraryEntry(entry.id)
            || String(entry.generationImageId || entry.imageId || entry.exif?.generationImageId || '').trim();
          if (imageId && state.settings.libraryRefreshFromList !== false && applyLibraryLink(imageId, entry)) changed += 1;
        });
      } else if (info.action === 'delete') {
        let entryIds = Array.isArray(body?.entryIds) ? body.entryIds.map(String) : [];
        if (!entryIds.length && body?.entryId) entryIds = [String(body.entryId)];
        if (!entryIds.length && info.restEntryId) entryIds = [info.restEntryId];
        entryIds.forEach(entryId => { if (unlinkLibraryEntry(entryId)) changed += 1; });
      }
      if (changed) emitItemsChanged(`library-${info.action}`);
      diagnostic('debug', 'library', `Library ${info.action} response processed`, { changed });
      maybePrune();
      return changed;
    } catch (error) {
      traceError('library', 'Library response processing failed', error, { method: String(method || '') });
      return 0;
    }
  }

  function headersObject(headersLike) {
    const result = {};
    if (!headersLike) return result;
    try {
      const headers = new Headers(headersLike);
      headers.forEach((value, key) => { result[key.toLowerCase()] = String(value); });
      return result;
    } catch {}
    try {
      Object.entries(headersLike).forEach(([key, value]) => { result[String(key).toLowerCase()] = String(value); });
    } catch {}
    return result;
  }

  function bearerFromHeaders(headersLike) {
    const value = headersObject(headersLike).authorization || '';
    const match = value.match(/^Bearer\s+(.+)$/i);
    return match ? match[1].trim() : '';
  }

  function isTensorApiUrl(url) {
    try {
      return new URL(normalizeUrl(url)).origin === TENSOR_API_ORIGIN;
    } catch { return false; }
  }

  function isUsableTensorToken(token) {
    const value = String(token || '').trim();
    if (value.length < 16 || /\s/.test(value)) return false;
    const payload = decodeTensorTokenPayload(value);
    if (Number(payload?.exp) > 0 && Number(payload.exp) * 1000 <= Date.now() + 15_000) return false;
    return true;
  }

  function decodeTensorTokenPayload(token) {
    const part = String(token || '').split('.')[1];
    if (!part) return null;
    try { return JSON.parse(atob(part.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(part.length / 4) * 4, '='))); }
    catch { return null; }
  }

  function tokenOwnerFingerprint(token) {
    const value = String(token || '');
    let first = 0x811c9dc5;
    let second = 0x9e3779b9;
    for (let index = 0; index < value.length; index += 1) {
      const code = value.charCodeAt(index);
      first = Math.imul(first ^ code, 0x01000193) >>> 0;
      second = Math.imul(second ^ (code + index), 0x85ebca6b) >>> 0;
    }
    return `token:${first.toString(16).padStart(8, '0')}${second.toString(16).padStart(8, '0')}`;
  }

  function rememberTensorToken(token, options = {}) {
    const value = String(token || '').trim();
    if (!isUsableTensorToken(value)) return '';
    state.lastToken = value;
    if (options.refreshVerifiedAt !== false) state.lastTokenAt = Date.now();
    const payload = decodeTensorTokenPayload(value);
    const accountId = String(payload?.userId || payload?.uid || payload?.sub || '').trim() || tokenOwnerFingerprint(value);
    state.currentAccountId = accountId;
    return value;
  }

  function clearTensorIdentity() {
    state.lastToken = '';
    state.lastTokenAt = 0;
    state.currentAccountId = '';
  }

  function captureRequest(url, headersLike) {
    if (!isTensorApiUrl(url)) return;
    const headers = headersObject(headersLike);
    const token = bearerFromHeaders(headers);
    if (isUsableTensorToken(token)) rememberTensorToken(token);
    // Package identity and language are reusable across Tensor calls.
    const selected = {};
    const reusable = new Set([
      'x-request-package-sign-version',
      'x-request-package-id',
      'x-request-lang'
    ]);
    Object.entries(headers).forEach(([key, value]) => {
      const lower = String(key || '').toLowerCase();
      if (reusable.has(lower)) selected[lower] = value;
    });
    if (Object.keys(selected).length) {
      const record = { headers: selected, updatedAt: Date.now() };
      state.endpointHeaders.set('*', record);
    }
    // A live signature/timestamp is reusable only for the exact generation
    // download endpoint that produced it. Never replay a query signature on a
    // download path; the static requestHeaders stay aligned with the Pro
    // resolver until Lite observes a newer endpoint-specific contract.
    if (state.settings.reuseCapturedDownloadHeaders !== false) {
      let pathname = '';
      try { pathname = new URL(normalizeUrl(url)).pathname; } catch {}
      const endpoint = [API_URL_IMAGE, API_URL_VIDEO].find(value => {
        try { return new URL(value).pathname === pathname; } catch { return false; }
      });
      if (endpoint) {
        const exact = {};
        const allowed = new Set([
          'x-request-package-sign-version', 'x-request-package-id', 'x-request-timestamp',
          'x-request-sign', 'x-request-lang', 'x-request-sign-type', 'x-request-sign-version'
        ]);
        Object.entries(headers).forEach(([key, value]) => {
          const lower = String(key || '').toLowerCase();
          if (allowed.has(lower)) exact[lower] = value;
        });
        if (Object.keys(exact).length) state.endpointHeaders.set(endpoint, { headers: exact, updatedAt: Date.now() });
      }
    }
  }

  async function getToken(options = {}) {
    if (!options.skipMemory && isUsableTensorToken(state.lastToken)) return rememberTensorToken(state.lastToken, { refreshVerifiedAt: false });
    try {
      const cookie = await PAGE.cookieStore?.get?.('ta_token_prod');
      if (isUsableTensorToken(cookie?.value)) return rememberTensorToken(cookie.value);
    } catch {}
    try {
      if (typeof GM !== 'undefined' && GM.cookie?.list) {
        const cookies = await GM.cookie.list({ name: 'ta_token_prod', url: 'https://tensor.art' });
        if (isUsableTensorToken(cookies?.[0]?.value)) return rememberTensorToken(cookies[0].value);
      }
    } catch {}
    try {
      const match = document.cookie.match(/(?:^|;\s*)ta_token_prod=([^;]+)/);
      const cookieToken = match?.[1] ? decodeURIComponent(match[1]) : '';
      if (isUsableTensorToken(cookieToken)) return rememberTensorToken(cookieToken);
    } catch {}
    if (options.preserveRecentMemoryOnMiss === true
      && isUsableTensorToken(state.lastToken)
      && Date.now() - Number(state.lastTokenAt || 0) <= TASK_FOLLOWUP_IDENTITY_GRACE_MS) {
      return rememberTensorToken(state.lastToken, { refreshVerifiedAt: false });
    }
    clearTensorIdentity();
    return '';
  }

  async function reconcileRequestIdentity(url, headersLike) {
    if (!isRelevantTensorEndpoint(url)) return state.lastToken;
    const bearer = bearerFromHeaders(headersLike);
    if (isUsableTensorToken(bearer)) return rememberTensorToken(bearer);
    // Tensor's active task/create/mget follow-ups do not consistently repeat
    // the bearer header. Keep a recently verified identity for those bounded
    // follow-ups so a newly finished task is not saved ownerless and hidden.
    // A tasks/query request intentionally does not receive this grace: a
    // headerless/cookieless query remains the logout/account-switch boundary.
    return getToken({
      skipMemory: true,
      preserveRecentMemoryOnMiss: tensorEndpointKind(url) !== 'query'
    });
  }

  function endpointRequestHeaders(endpoint, token) {
    const result = { 'Content-Type': 'application/json' };
    Object.assign(result, state.settings.requestHeaders || {});
    // Default contract intentionally mirrors fetchDownloadUrlBatch in the full
    // userscript: bearer + JSON content type + configured request headers only.
    // Captured page signatures are path-bound and short-lived, so replay is an
    // explicit expert opt-in instead of silently changing the proven contract.
    if (state.settings.reuseCapturedDownloadHeaders === true) {
      const generic = state.endpointHeaders.get('*');
      if (generic && Date.now() - generic.updatedAt < 300_000) Object.assign(result, generic.headers);
      const exact = state.endpointHeaders.get(endpoint);
      if (exact && Date.now() - exact.updatedAt < 300_000) Object.assign(result, exact.headers);
    }
    result.Authorization = `Bearer ${token}`;
    return result;
  }

  function parseDownloadPayload(payload) {
    const root = payload?.data?.data || payload?.data || payload || {};
    return [...(root.images || []), ...(root.videos || []), ...(root.items || []), ...(root.medias || [])]
      .map(entry => ({
        id: String(entry?.imageId || entry?.mediaId || entry?.id || '').trim(),
        url: entry?.url || entry?.downloadUrl || '',
        mimeType: entry?.mimeType || '',
        fileName: entry?.filename || entry?.downloadFileName || entry?.fileName || ''
      }))
      .filter(entry => entry.id && entry.url);
  }

  function cacheDownloadPayload(payload, kindHint = '') {
    let count = 0;
    parseDownloadPayload(payload).forEach(entry => {
      if (cacheDownload(entry.id, entry.url, entry.mimeType, kindHint)) count += 1;
    });
    if (count) {
      state.stats.resolvedUrls += count;
      emitItemsChanged('download');
      parseDownloadPayload(payload).forEach(entry => {
        const item = state.items.get(String(entry.id));
        if (item) fiHostScheduleItem(item, 'download-resolved');
      });
    }
    return count;
  }

  let nativeFetch = typeof PAGE.fetch === 'function' ? PAGE.fetch.bind(PAGE) : null;

  function gmRequestFunction() {
    if (typeof GM !== 'undefined' && typeof GM.xmlHttpRequest === 'function') {
      return GM.xmlHttpRequest.bind(GM);
    }
    if (typeof GM_xmlhttpRequest === 'function') return GM_xmlhttpRequest;
    return null;
  }

  function gmDownloadJsonRequest(endpoint, headers, body) {
    const request = gmRequestFunction();
    if (!request) return Promise.reject(new Error('GM.xmlHttpRequest/GM_xmlhttpRequest is unavailable'));
    state.stats.gmDownloadRequests += 1;
    return new Promise((resolve, reject) => {
      let settled = false;
      const finish = callback => value => {
        if (settled) return;
        settled = true;
        callback(value);
      };
      const onLoad = finish(response => {
        const status = Number(response?.status || 0);
        if (status < 200 || status >= 300) {
          const error = new Error(`${status || 0} ${response?.statusText || 'GM request failed'}`);
          error.status = status;
          reject(error);
          return;
        }
        try {
          const parsed = response?.response && typeof response.response === 'object'
            ? response.response
            : JSON.parse(String(response?.responseText || '{}'));
          resolve(parsed);
        } catch (error) { reject(error); }
      });
      const onError = finish(() => reject(new Error('GM download request network failure')));
      try {
        const pending = request({
          method: 'POST',
          url: endpoint,
          headers,
          data: body,
          timeout: 10_000,
          responseType: 'text',
          anonymous: false,
          onload: onLoad,
          onerror: onError,
          ontimeout: finish(() => reject(new Error('GM download request timed out'))),
          onabort: finish(() => reject(new Error('GM download request aborted')))
        });
        // GM4-style implementations may return a Promise instead of invoking
        // callbacks. Supporting both keeps the recovery path portable across
        // Tampermonkey, Violentmonkey, and newer GM APIs.
        if (pending && typeof pending.then === 'function') pending.then(onLoad, onError);
      } catch (error) {
        finish(reject)(error);
      }
    });
  }

  async function pageDownloadJsonRequest(endpoint, headers, body) {
    if (!nativeFetch) throw new Error('Page fetch is unavailable');
    const controller = typeof AbortController === 'function' ? new AbortController() : null;
    const timeout = controller ? setTimeout(() => controller.abort(), 10_000) : null;
    try {
      // Match the full resolver exactly: POST JSON with no extra credentials
      // mode. Supplying credentials:'include' changed the browser preflight on
      // some Tensor deployments and could surface as 405 Method Not Allowed.
      const response = await nativeFetch(endpoint, {
        method: 'POST',
        headers,
        body,
        ...(controller ? { signal: controller.signal } : {})
      });
      if (!response.ok) {
        const error = new Error(`${response.status} ${response.statusText}`);
        error.status = Number(response.status || 0);
        throw error;
      }
      return response.json();
    } finally {
      if (timeout) clearTimeout(timeout);
    }
  }

  async function requestDownloadBatch(ids, endpoint, token) {
    const unique = [...new Set((Array.isArray(ids) ? ids : [])
      .filter(isTensorDownloadableId)
      .map(value => String(value).trim()))].slice(0, 30);
    if (!unique.length || !isUsableTensorToken(token)) return new Map();
    const headers = endpointRequestHeaders(endpoint, token);
    const body = JSON.stringify({ ids: unique });
    const configuredTransport = state.settings.downloadTransport || 'auto';
    const stickyGmFallback = configuredTransport === 'auto' && Date.now() < Number(state.downloadTransportFallbackUntil || 0);
    try {
      let payload;
      if (configuredTransport === 'gm-request' || stickyGmFallback) {
        payload = await gmDownloadJsonRequest(endpoint, headers, body);
      } else {
        try {
          payload = await pageDownloadJsonRequest(endpoint, headers, body);
        } catch (error) {
          const canRetryWithGm = configuredTransport === 'auto'
            && (Number(error?.status || 0) === 405 || Number(error?.status || 0) === 0 || error?.name === 'TypeError');
          if (!canRetryWithGm) throw error;
          if (Number(error?.status || 0) === 405) state.stats.download405Fallbacks += 1;
          state.downloadTransportFallbackUntil = Date.now() + 10 * 60_000;
          payload = await gmDownloadJsonRequest(endpoint, headers, body);
        }
      }
      const kind = endpoint === API_URL_VIDEO ? 'video' : 'image';
      cacheDownloadPayload(payload, kind);
      return new Map(parseDownloadPayload(payload).map(entry => [entry.id, entry.url]));
    } catch (error) {
      state.stats.failures += 1;
      traceError('resolver', 'Download URL batch failed', error, { endpointKind: endpoint === API_URL_VIDEO ? 'video' : 'image', idCount: unique.length });
      return new Map();
    }
  }

  function taskTerminalOutcome(task) {
    const status = String(task?.status || '').toUpperCase();
    if (['FINISH', 'FINISHED', 'COMPLETED', 'SUCCESS'].includes(status)) return 'success';
    if (['FAIL', 'FAILED', 'ERROR', 'CANCELED', 'CANCELLED'].includes(status)) return 'failure';
    return '';
  }

  function taskDisplayName(task) {
    return String(
      task?.workflowTemplateInfo?.name || task?.workflowInfo?.name || task?.baseModel?.name ||
      task?.baseModel?.baseModel || task?.taskType || 'Tensor task'
    ).trim().slice(0, 160) || 'Tensor task';
  }

  function deliveryCaption(task, outcome, mediaUrl = '') {
    const title = `${outcome === 'success' ? '✅' : '❌'} ${taskDisplayName(task)}`;
    const taskKey = taskId(task) || 'unknown';
    const finishAt = normalizeTimestampMs(task?.taskFinishAt) || Date.now();
    const cost = Number(task?.credits);
    const prompt = String(task?.inputData?.prompt || '').replace(/\s+/g, ' ').trim();
    const lines = [title, `Task: ${taskKey}`, `Status: ${String(task?.status || outcome).toUpperCase()}`];
    if (Number.isFinite(cost)) lines.push(`Cost: ${cost} credits`);
    lines.push(`Time: ${new Date(finishAt).toLocaleString()}`);
    if (task?.failMessage) lines.push(`Reason: ${String(task.failMessage).replace(/\s+/g, ' ').slice(0, 300)}`);
    if (prompt) lines.push(`Prompt: ${prompt.slice(0, 300)}`);
    if (mediaUrl && mediaKind(task?.items?.[0]?.mimeType) === 'video') lines.push(mediaUrl);
    return lines.join('\n').slice(0, state.settings.deliveryMaxCaption);
  }

  function gmDeliveryRequest(url, payload, channel) {
    const request = gmRequestFunction();
    if (!request) return Promise.reject(new Error('GM request transport is unavailable'));
    return new Promise((resolve, reject) => {
      let settled = false;
      const finish = callback => value => {
        if (settled) return;
        settled = true;
        callback(value);
      };
      const onLoad = finish(response => {
        const status = Number(response?.status || 0);
        if (status < 200 || status >= 300) {
          const error = new Error(`${channel} returned HTTP ${status || 0}`);
          error.status = status;
          reject(error);
          return;
        }
        resolve({ status });
      });
      const onError = finish(() => reject(new Error(`${channel} network request failed`)));
      try {
        const pending = request({
          method: 'POST', url,
          headers: { 'Content-Type': 'application/json' },
          data: JSON.stringify(payload),
          timeout: 12_000,
          responseType: 'text',
          anonymous: false,
          onload: onLoad,
          onerror: onError,
          ontimeout: finish(() => reject(new Error(`${channel} request timed out`))),
          onabort: finish(() => reject(new Error(`${channel} request was aborted`)))
        });
        if (pending && typeof pending.then === 'function') pending.then(onLoad, onError);
      } catch (error) { finish(reject)(error); }
    });
  }

  function gmTelegramApiRequest(method, payload = {}, timeoutMs = 12_000) {
    const request = gmRequestFunction();
    const token = sanitizeTelegramToken(state.settings.telegramBotToken);
    if (!request) return Promise.reject(new Error('GM request transport is unavailable'));
    if (!token) return Promise.reject(new Error('Enter a valid Telegram bot token first'));
    const base = sanitizeDeliveryBase(state.settings.telegramApiBase);
    return new Promise((resolve, reject) => {
      let settled = false;
      const finish = callback => value => {
        if (settled) return;
        settled = true;
        callback(value);
      };
      const onLoad = finish(response => {
        const status = Number(response?.status || 0);
        let body = null;
        try { body = JSON.parse(String(response?.responseText ?? response?.response ?? '')); } catch {}
        if (status < 200 || status >= 300 || body?.ok !== true) {
          const description = String(body?.description || '').replace(/\s+/g, ' ').trim().slice(0, 240);
          reject(new Error(description || `Telegram returned HTTP ${status || 0}`));
          return;
        }
        resolve(Array.isArray(body.result) ? body.result : body.result ?? null);
      });
      const onError = finish(() => reject(new Error('Telegram network request failed')));
      try {
        const pending = request({
          method: 'POST',
          url: `${base}/bot${token}/${encodeURIComponent(String(method || ''))}`,
          headers: { 'Content-Type': 'application/json' },
          data: JSON.stringify(payload),
          timeout: Math.max(4_000, Number(timeoutMs) || 12_000),
          responseType: 'text',
          anonymous: false,
          onload: onLoad,
          onerror: onError,
          ontimeout: finish(() => reject(new Error('Telegram initialization request timed out'))),
          onabort: finish(() => reject(new Error('Telegram initialization request was aborted')))
        });
        if (pending && typeof pending.then === 'function') pending.then(onLoad, onError);
      } catch (error) { finish(reject)(error); }
    });
  }

  function telegramAccessCommand(update, notBeforeMs = 0) {
    const message = update?.message || update?.edited_message || update?.channel_post || null;
    if (!message || !/^\/access(?:@[A-Za-z0-9_]+)?(?:\s|$)/i.test(String(message.text || '').trim())) return null;
    const sentAt = Number(message.date || 0) * 1000;
    if (notBeforeMs && sentAt && sentAt < notBeforeMs) return null;
    const chatId = String(message.chat?.id ?? '').trim();
    if (!chatId) return null;
    const label = String(message.chat?.title || message.chat?.username || [message.chat?.first_name, message.chat?.last_name].filter(Boolean).join(' ') || 'Telegram chat').trim().slice(0, 100);
    return { chatId, label };
  }

  function setTelegramAccessStatus(phase, message) {
    state.telegramAccessStatus = { phase, message: String(message || '').slice(0, 320) };
    if (state.ui?.panel && state.activeTab === 'settings') renderSettings();
  }

  async function initializeTelegramAccess() {
    if (!sanitizeTelegramToken(state.settings.telegramBotToken)) {
      setTelegramAccessStatus('error', 'Enter and save a valid Telegram bot token before initializing.');
      diagnostic('warn', 'telegram', 'Telegram /access initialization needs a valid bot token');
      return false;
    }
    if (['starting','waiting'].includes(state.telegramAccessStatus?.phase)) {
      state.telegramAccessRunId++;
      setTelegramAccessStatus('idle', 'Initialization cancelled. Click Initialize when you are ready to send /access.');
      return false;
    }
    const runId = ++state.telegramAccessRunId;
    const startedAt = Date.now();
    const deadline = startedAt + 120_000;
    setTelegramAccessStatus('starting', 'Connecting to Telegram and establishing a fresh update position…');
    try {
      const baseline = await gmTelegramApiRequest('getUpdates', { timeout: 0, limit: 100, allowed_updates: ['message','edited_message','channel_post'] }, 12_000);
      if (runId !== state.telegramAccessRunId) return false;
      let offset = (Array.isArray(baseline) ? baseline : []).reduce((max, update) => Math.max(max, Number(update?.update_id) || 0), 0) + 1;
      // If /access arrived just after the click while the baseline request was in
      // flight, accept it; older commands remain ignored.
      const immediate = (Array.isArray(baseline) ? baseline : []).map(update => telegramAccessCommand(update, startedAt)).find(Boolean);
      if (immediate) {
        state.settings.telegramChatId = immediate.chatId;
        state.telegramAccessRunId++;
        state.telegramAccessStatus = { phase: 'success', message: `Connected to ${immediate.label}. Chat ID was saved automatically.` };
        saveSettings();
        diagnostic('info', 'telegram', 'Telegram /access initialization completed');
        return true;
      }
      setTelegramAccessStatus('waiting', 'Connected. Send /access to your bot now; Lite will wait for up to 2 minutes. Click Cancel to stop.');
      while (runId === state.telegramAccessRunId && Date.now() < deadline) {
        const updates = await gmTelegramApiRequest('getUpdates', {
          offset,
          timeout: 20,
          limit: 100,
          allowed_updates: ['message','edited_message','channel_post']
        }, 26_000);
        if (runId !== state.telegramAccessRunId) return false;
        for (const update of Array.isArray(updates) ? updates : []) {
          offset = Math.max(offset, (Number(update?.update_id) || 0) + 1);
          const access = telegramAccessCommand(update, startedAt);
          if (!access) continue;
          state.settings.telegramChatId = access.chatId;
          state.telegramAccessRunId++;
          state.telegramAccessStatus = { phase: 'success', message: `Connected to ${access.label}. Chat ID was saved automatically.` };
          saveSettings();
          diagnostic('info', 'telegram', 'Telegram /access initialization completed');
          return true;
        }
      }
      if (runId === state.telegramAccessRunId) {
        state.telegramAccessRunId++;
        setTelegramAccessStatus('error', 'No new /access command was received within 2 minutes. Click Initialize to try again.');
        diagnostic('warn', 'telegram', 'Telegram /access initialization timed out');
      }
      return false;
    } catch (error) {
      if (runId !== state.telegramAccessRunId) return false;
      state.telegramAccessRunId++;
      setTelegramAccessStatus('error', `Initialization failed: ${String(error?.message || error).slice(0, 220)}`);
      traceError('telegram', 'Telegram /access initialization failed', error);
      return false;
    }
  }

  async function taskMediaForDelivery(task) {
    if (state.settings.deliveryIncludeMedia === false || !Array.isArray(task?.items)) return { url: '', kind: '' };
    for (const item of task.items.slice(0, 4)) {
      const id = itemId(item);
      let url = fiHostRemoteCandidate(item) || '';
      if (!isUsableMediaUrl(url, 0) && isTensorDownloadableId(id)) url = await resolveOne(id, item?.mimeType || '');
      if (isFiHostLocalUrl(url)) url = fiHostRemoteCandidate(state.items.get(id) || item);
      if (isUsableMediaUrl(url, 0)) return { url, kind: mediaKind(item?.mimeType || '') };
    }
    return { url: '', kind: '' };
  }

  async function sendTelegramTask(task, outcome, media) {
    const token = sanitizeTelegramToken(state.settings.telegramBotToken);
    const chatId = String(state.settings.telegramChatId || '').trim();
    if (!state.settings.telegramDeliveryEnabled || !token || !chatId) return false;
    const base = sanitizeDeliveryBase(state.settings.telegramApiBase);
    const caption = state.settings.deliveryIncludeCaption === false && media.url ? '' : deliveryCaption(task, outcome, media.url);
    const method = media.url ? (media.kind === 'video' ? 'sendVideo' : 'sendPhoto') : 'sendMessage';
    const payload = media.url
      ? { chat_id: chatId, [media.kind === 'video' ? 'video' : 'photo']: media.url, ...(caption ? { caption } : {}) }
      : { chat_id: chatId, text: caption };
    await gmDeliveryRequest(`${base}/bot${token}/${method}`, payload, 'Telegram');
    return true;
  }

  async function sendDiscordTask(task, outcome, media) {
    const webhook = sanitizeDiscordWebhook(state.settings.discordWebhookUrl);
    if (!state.settings.discordDeliveryEnabled || !webhook) return false;
    const description = state.settings.deliveryIncludeCaption === false && media.url ? '' : deliveryCaption(task, outcome, media.url);
    const color = outcome === 'success' ? 0x34d399 : 0xfb7185;
    const embed = { title: taskDisplayName(task), ...(description ? { description } : {}), color, timestamp: new Date().toISOString() };
    if (media.url && media.kind !== 'video') embed.image = { url: media.url };
    const content = media.url && media.kind === 'video' ? media.url : undefined;
    await gmDeliveryRequest(webhook, { username: SCRIPT_NAME, ...(content ? { content } : {}), embeds: [embed], allowed_mentions: { parse: [] } }, 'Discord');
    return true;
  }

  async function deliverTaskTransition(task, outcome) {
    const channels = [];
    if (state.settings.telegramDeliveryEnabled) channels.push(['telegram', sendTelegramTask]);
    if (state.settings.discordDeliveryEnabled) channels.push(['discord', sendDiscordTask]);
    if (!channels.length) return [];
    const media = outcome === 'success' ? await taskMediaForDelivery(task) : { url: '', kind: '' };
    const results = [];
    for (const [channel, sender] of channels) {
      state.stats.deliveryAttempts += 1;
      try {
        const sent = await sender(task, outcome, media);
        if (sent) {
          state.stats.deliverySent += 1;
          diagnostic('info', 'delivery', `${channel} task delivery sent`, { outcome, taskId: taskId(task), hasMedia: !!media.url });
          results.push({ channel, ok: true });
        }
      } catch (error) {
        state.stats.deliveryFailures += 1;
        traceError('delivery', `${channel} task delivery failed`, error, { outcome, taskId: taskId(task) });
        results.push({ channel, ok: false });
      }
    }
    return results;
  }

  function scheduleTaskDelivery(previousTask, task) {
    const outcome = taskTerminalOutcome(task);
    if (!outcome) return;
    if (outcome === 'success' && state.settings.deliverySuccessEnabled === false) return;
    if (outcome === 'failure' && state.settings.deliveryFailureEnabled === false) return;
    if (!state.settings.telegramDeliveryEnabled && !state.settings.discordDeliveryEnabled) return;
    if (previousTask && taskTerminalOutcome(previousTask) === outcome) return;
    const key = `${state.currentAccountId || 'unknown'}:${taskId(task)}:${outcome}`;
    if (state.deliveryDedupe.has(key)) return;
    state.deliveryDedupe.add(key);
    if (state.deliveryDedupe.size > 500) state.deliveryDedupe.delete(state.deliveryDedupe.values().next().value);
    Promise.resolve().then(() => deliverTaskTransition(clone(task), outcome)).catch(error => {
      traceError('delivery', 'Task delivery scheduler failed', error, { outcome, taskId: taskId(task) });
    });
  }

  async function resolveCandidateUrls(candidates, options = {}) {
    const normalized = [...new Map((Array.isArray(candidates) ? candidates : [])
      .map(entry => ({ id: String(entry?.id || entry?.imageId || '').trim(), mimeType: String(entry?.mimeType || '') }))
      .filter(entry => isTensorDownloadableId(entry.id))
      .map(entry => [entry.id, entry])).values()];
    if (!normalized.length) return new Map();
    if (!fiBridgeOwnsSharedRoutes()) return fiBridgeResolveThroughOwner(normalized, options);
    const token = await getToken();
    if (!token) throw new Error('No Tensor token is available for URL resolution.');
    const resolved = new Map();
    for (let offset = 0; offset < normalized.length; offset += FI_BRIDGE_RESOLVE_MAX_ITEMS) {
      const batchItems = normalized.slice(offset, offset + FI_BRIDGE_RESOLVE_MAX_ITEMS);
      const ids = batchItems.map(entry => entry.id);
      const imageMap = await requestDownloadBatch(ids, API_URL_IMAGE, token);
      imageMap.forEach((url, id) => resolved.set(id, url));
      const videoMisses = batchItems
        .filter(entry => mediaKind(entry.mimeType) === 'video' && !resolved.has(entry.id))
        .map(entry => entry.id);
      if (videoMisses.length) {
        const videoMap = await requestDownloadBatch(videoMisses, API_URL_VIDEO, token);
        videoMap.forEach((url, id) => resolved.set(id, url));
      }
    }
    return resolved;
  }

  async function resolveMissingForBody(body) {
    if (!state.settings.resolveMissingUrls) return new Map();
    if (fiBridgeOwnsSharedRoutes()) await fiHostBackfillExistingForBody(body);
    const candidates = [];
    for (const task of taskListFromBody(body)) {
      if (!task || !isFinishedTask(task) || isTaskExpired(task)) continue;
      for (const item of Array.isArray(task.items) ? task.items : []) {
        const id = itemId(item);
        if (!isTensorDownloadableId(id)) continue;
        // Tensor task objects are metadata. Even an apparently usable preview
        // URL is not necessarily the signed download URL. Resolve every fresh
        // FINISH item that does not already have a reusable library/download
        // projection, exactly as the full script does.
        if (!needsDownloadRefresh(item)) continue;
        candidates.push({ id, mimeType: item.mimeType || '' });
        if (candidates.length >= state.settings.maxResolvePerResponse) break;
      }
      if (candidates.length >= state.settings.maxResolvePerResponse) break;
    }
    if (!candidates.length) return new Map();
    try { return await resolveCandidateUrls(candidates, { reason: 'task-response-auto' }); }
    catch (error) {
      traceError('resolver', 'Automatic response URL resolution failed', error, { candidates: candidates.length });
      return new Map();
    }
  }

  async function patchBodyAsync(body, source = 'fetch', options = {}) {
    await database.open();
    const endpointKind = options.endpointKind || (source.includes('mget') ? 'mget' : source.includes('query') ? 'query' : 'task');
    state.stats.taskResponses += 1;
    if (endpointKind === 'query') state.stats.queries += 1;
    if (endpointKind === 'mget') state.stats.mgetResponses += 1;
    if (!options.alreadyObserved) persistObservedBody(body);
    let patched = patchBodySync(body);
    const resolved = await resolveMissingForBody(patched.body);
    if (resolved.size) {
      resolved.forEach((url, id) => {
        const item = state.items.get(id);
        if (item) cacheDownload(id, url, item.mimeType || '', mediaKind(item.mimeType));
      });
      patched = patchBodySync(patched.body);
    }
    if (patched.changed) {
      state.stats.patchedResponses += 1;
      state.stats.patchedItems += patched.patchedItems;
      // The task store is an immutable record of Tensor's raw response. The
      // item/download projections were already refreshed by cacheDownload().
      emitItemsChanged('patched');
      log(`Patched ${patched.patchedItems} item(s) from ${source}.`);
    }
    return patched;
  }

  function removeDownloadsForItem(id) {
    const cleanId = String(id || '');
    for (const [key, entry] of [...state.downloads]) {
      if (String(entry?.id || '') !== cleanId || !isEntryForCurrentAccount(entry)) continue;
      state.downloads.delete(key);
      database.remove('downloads', key);
    }
  }

  async function cleanupExpiredTasksOnLoad(force = false) {
    if ((!state.settings.removeExpiredTasksOnLoad && !force) || !state.currentAccountId) return { tasks: 0, items: 0 };
    const now = Date.now();
    const expiredIds = new Set();
    for (const [id, task] of [...state.tasks]) {
      if (!isEntryForCurrentAccount(task) || !isTaskExpired(task, now)) continue;
      expiredIds.add(String(id));
      state.tasks.delete(id);
      database.remove('tasks', id);
    }
    let removedItems = 0;
    if (state.settings.removeExpiredTaskItemsOnLoad) {
      for (const [id, item] of [...state.items]) {
        if (!isEntryForCurrentAccount(item)) continue;
        const itemExpired = isTaskExpired(item, now) || expiredIds.has(String(item.taskId || ''));
        if (!itemExpired) continue;
        // Library links are independent, durable records. Keep their card and
        // current library URL even after the generation task expires.
        const library = libraryEntryForImage(id);
        if (library) {
          const detached = { ...item, ...library, taskExpired: true, taskId: '', taskExpireAtMs: null, updatedAt: now };
          state.items.set(id, detached);
          if (state.settings.cachingEnabled) database.put('items', detached);
          continue;
        }
        state.items.delete(id);
        database.remove('items', id);
        removeDownloadsForItem(id);
        removedItems += 1;
      }
    }
    state.stats.expiredTasksPruned += expiredIds.size;
    if (expiredIds.size || removedItems) emitItemsChanged('expired-task-cleanup');
    return { tasks: expiredIds.size, items: removedItems };
  }

  async function resolveStoredItemsOnLoad(options = {}) {
    const manual = options.manual === true;
    if (!manual && options.ignoreResolveOnLoad !== true && !state.settings.resolveOnLoad) return 0;
    if (!manual && !state.settings.resolveMissingUrls) return 0;
    if (!state.currentAccountId) return 0;
    if (!fiBridgeOwnsSharedRoutes() && !fiBridgeCanDelegateResolution()) {
      if (manual) throw new Error('No elected resolver is available. Enable FI Bridge delegation or select Lite as the shared request owner and reload Tensor.');
      return 0;
    }
    const limit = Math.max(0, Number(options.limit ?? state.settings.onLoadResolveLimit ?? 0));
    if (!limit) return 0;
    const candidates = [...state.items.values()]
      .filter(item => isEntryForCurrentAccount(item) && !isTaskExpired(item) && needsDownloadRefresh(item))
      .sort((a, b) => itemDisplayDate(b) - itemDisplayDate(a) || String(itemId(b)).localeCompare(String(itemId(a)), undefined, { numeric: true }))
      .slice(0, limit);
    if (!candidates.length) return 0;
    let resolvedCount = 0;
    for (let offset = 0; offset < candidates.length; offset += FI_BRIDGE_RESOLVE_MAX_ITEMS) {
      const batchItems = candidates.slice(offset, offset + FI_BRIDGE_RESOLVE_MAX_ITEMS);
      const merged = await resolveCandidateUrls(batchItems.map(item => ({ id: itemId(item), mimeType: item.mimeType || item.libraryMimeType || '' })), {
        reason: String(options.reason || (manual ? 'manual-resolve-all' : 'stored-auto')),
        force: manual
      });
      merged.forEach((url, id) => {
        const item = state.items.get(id);
        if (item && cacheDownload(id, url, item.mimeType || '', mediaKind(item.mimeType))) resolvedCount += 1;
      });
    }
    state.stats.onLoadResolved += resolvedCount;
    if (resolvedCount) emitItemsChanged('onload-resolve');
    return resolvedCount;
  }

  function scheduleAutomaticStoredResolution(reason = 'automatic') {
    if (!state.settings.resolveMissingUrls || !state.currentAccountId) return false;
    clearTimeout(state.autoResolveTimer);
    state.autoResolveTimer = setTimeout(() => {
      state.autoResolveTimer = null;
      if (state.autoResolveInFlight) return;
      state.autoResolveInFlight = resolveStoredItemsOnLoad({
        ignoreResolveOnLoad: true,
        limit: Math.max(1, Number(state.settings.maxResolvePerResponse || 30)),
        reason
      }).catch(error => {
        state.bridge.delegateFailures = Number(state.bridge.delegateFailures || 0) + 1;
        traceError('resolver', 'Scheduled URL resolution failed', error, { reason });
        return 0;
      }).finally(() => { state.autoResolveInFlight = null; });
    }, 80);
    return true;
  }

  function rewritePayload(body) {
    if (!state.settings.rewriteQuerySize || body == null) return { changed: false, body };
    const size = state.settings.querySize;
    if (typeof body === 'string') {
      try {
        const parsed = JSON.parse(body);
        const changed = Number(parsed.size) !== size || (parsed.limit !== undefined && Number(parsed.limit) !== size)
          || (parsed.pageSize !== undefined && Number(parsed.pageSize) !== size);
        if (!changed) return { changed: false, body };
        parsed.size = size;
        if (parsed.limit !== undefined) parsed.limit = size;
        if (parsed.pageSize !== undefined) parsed.pageSize = size;
        return { changed: true, body: JSON.stringify(parsed) };
      } catch { return { changed: false, body }; }
    }
    if (typeof FormData !== 'undefined' && body instanceof FormData) {
      let changed = false;
      if (body.get('size') !== String(size)) { body.set('size', String(size)); changed = true; }
      if (body.has('limit') && body.get('limit') !== String(size)) { body.set('limit', String(size)); changed = true; }
      if (body.has('pageSize') && body.get('pageSize') !== String(size)) { body.set('pageSize', String(size)); changed = true; }
      return { changed, body };
    }
    if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {
      let changed = false;
      if (body.get('size') !== String(size)) { body.set('size', String(size)); changed = true; }
      if (body.has('limit') && body.get('limit') !== String(size)) { body.set('limit', String(size)); changed = true; }
      if (body.has('pageSize') && body.get('pageSize') !== String(size)) { body.set('pageSize', String(size)); changed = true; }
      return { changed, body };
    }
    return { changed: false, body };
  }

  async function rewriteFetchArgs(args) {
    const input = args[0];
    const init = args[1] && typeof args[1] === 'object' ? { ...args[1] } : {};
    const url = normalizeUrl(input);
    const method = String(init.method || input?.method || 'GET').toUpperCase();
    if (!isTaskQueryEndpoint(url) || method === 'GET' || method === 'HEAD') return args;
    let body = Object.prototype.hasOwnProperty.call(init, 'body') ? init.body : undefined;
    let requestBody = false;
    if (body === undefined && input && typeof input.clone === 'function') {
      try { body = await input.clone().text(); requestBody = true; } catch {}
    }
    const rewritten = rewritePayload(body);
    if (!rewritten.changed) return args;
    if (requestBody) {
      try {
        const RequestCtor = PAGE.Request || Request;
        return [new RequestCtor(input, { ...init, body: rewritten.body })];
      } catch {}
    }
    return [input, { ...init, body: rewritten.body }];
  }

  async function readFetchRequestBody(args) {
    const init = args[1] && typeof args[1] === 'object' ? args[1] : {};
    if (Object.prototype.hasOwnProperty.call(init, 'body')) return init.body;
    const input = args[0];
    if (input && typeof input.clone === 'function') {
      try { return await input.clone().text(); } catch {}
    }
    return null;
  }

  function patchedResponse(original, body) {
    try {
      const HeadersCtor = PAGE.Headers || Headers;
      const headers = new HeadersCtor(original.headers);
      headers.set('content-type', 'application/json; charset=utf-8');
      headers.delete('content-length');
      const ResponseCtor = PAGE.Response || Response;
      const response = new ResponseCtor(JSON.stringify(body), {
        status: original.status,
        statusText: original.statusText,
        headers
      });
      for (const [key, value] of [['url', original.url], ['redirected', original.redirected], ['type', original.type]]) {
        try { Object.defineProperty(response, key, { value, configurable: true }); } catch {}
      }
      return response;
    } catch (error) {
      warn('Could not construct the patched fetch response.', error);
      return original;
    }
  }

  function observeDownloadResponse(response, url) {
    try {
      response.clone().json().then(payload => cacheDownloadPayload(payload, downloadEndpointKind(url))).catch(() => {});
    } catch {}
  }

  function installFetchInterceptor() {
    if (state.fetchInstalled || !nativeFetch) return;
    state.fetchInstalled = true;
    PAGE.fetch = async function (...originalArgs) {
      const initialUrl = normalizeUrl(originalArgs[0]);
      // Only a relevant Tensor request waits for the small bounded IDB hydrate;
      // unrelated page traffic stays on the native zero-overhead path.
      const initialKind = tensorEndpointKind(initialUrl);
      if (initialKind && !fiBridgeOwnsSharedRoutes()) return nativeFetch(...originalArgs);
      if (initialKind) await database.open();
      if (initialKind && !fiBridgeOwnsSharedRoutes()) return nativeFetch(...originalArgs);
      if (!state.settings.interceptEnabled) return nativeFetch(...originalArgs);
      const requestHeaders = originalArgs[1]?.headers || originalArgs[0]?.headers;
      const requestMethod = String(originalArgs[1]?.method || originalArgs[0]?.method || 'GET').toUpperCase();
      const requestBody = (initialKind === 'library' || isTaskApiEndpoint(initialUrl))
        ? await readFetchRequestBody(originalArgs)
        : null;
      captureRequest(initialUrl, requestHeaders);
      if (initialKind) {
        await reconcileRequestIdentity(initialUrl, requestHeaders);
      }
      const args = await rewriteFetchArgs(originalArgs);
      const url = normalizeUrl(args[0]);
      let response;
      try { response = await nativeFetch(...args); }
      catch (error) {
        if (initialKind) traceError('intercept', 'Intercepted Tensor fetch failed', error, { endpointKind: initialKind, method: requestMethod });
        throw error;
      }
      if (isDownloadEndpoint(url)) {
        observeDownloadResponse(response, url);
        return response;
      }
      if (isLibraryEndpoint(url)) {
        if (response?.ok) {
          let payload = null;
          try { payload = await response.clone().json(); }
          catch (error) { traceError('library', 'Library response JSON could not be parsed', error, { method: requestMethod }); }
          processLibraryPayload(url, requestBody, payload, requestMethod);
        }
        return response;
      }
      if (!isTaskApiEndpoint(url) || !response?.ok) return response;
      try {
        const body = await response.clone().json();
        const endpointKind = tensorEndpointKind(url);
        if (!state.settings.awaitFetchBackfill) {
          persistObservedBody(body);
          const sync = patchBodySync(body);
          patchBodyAsync(body, `fetch-${endpointKind}-warm`, { alreadyObserved: true, endpointKind }).catch(error => traceError('intercept', 'Warm fetch backfill failed', error, { endpointKind }));
          return sync.changed ? patchedResponse(response, sync.body) : response;
        }
        const result = await patchBodyAsync(body, `fetch-${endpointKind}`, { endpointKind });
        return result.changed ? patchedResponse(response, result.body) : response;
      } catch (error) {
        state.stats.failures += 1;
        traceError('intercept', 'Fetch task patch failed', error, { endpointKind: tensorEndpointKind(url) });
        return response;
      }
    };
  }

  function installXhrGetters(xhr, meta, nativeGetText, nativeGetResponse) {
    if (meta.gettersInstalled || !isTaskApiEndpoint(meta.url)) return;
    meta.gettersInstalled = true;

    const readNativeBody = () => {
      const type = String(xhr.responseType || '').toLowerCase();
      if (type === 'json' && nativeGetResponse) return nativeGetResponse.call(xhr);
      const raw = nativeGetText ? nativeGetText.call(xhr) : null;
      return typeof raw === 'string' && raw ? JSON.parse(raw) : null;
    };

    const snapshot = () => {
      if (xhr.readyState !== 4 || xhr.status < 200 || xhr.status >= 300) return null;
      if (meta.snapshot) return meta.snapshot;
      try {
        const body = readNativeBody();
        if (!body) return null;
        persistObservedBody(body);
        const sync = patchBodySync(body);
        meta.snapshot = { body: sync.body, serialized: JSON.stringify(sync.body), changed: sync.changed };
        if (!meta.backfillStarted) {
          meta.backfillStarted = true;
          const endpointKind = tensorEndpointKind(meta.url);
          patchBodyAsync(body, `xhr-${endpointKind}`, { alreadyObserved: true, endpointKind }).then(result => {
            meta.snapshot = { body: result.body, serialized: JSON.stringify(result.body), changed: result.changed };
          }).catch(error => traceError('intercept', 'XHR response backfill failed', error, { endpointKind }));
        }
        return meta.snapshot;
      } catch (error) { traceError('intercept', 'XHR task response parsing failed', error, { endpointKind: tensorEndpointKind(meta.url) }); return null; }
    };

    try {
      if (nativeGetText) {
        Object.defineProperty(xhr, 'responseText', {
          configurable: true,
          get() {
            const hit = snapshot();
            return hit?.changed ? hit.serialized : nativeGetText.call(xhr);
          }
        });
      }
      if (nativeGetResponse) {
        Object.defineProperty(xhr, 'response', {
          configurable: true,
          get() {
            const hit = snapshot();
            const type = String(xhr.responseType || '').toLowerCase();
            if (hit?.changed && type === 'json') return hit.body;
            if (hit?.changed && (type === '' || type === 'text')) return hit.serialized;
            return nativeGetResponse.call(xhr);
          }
        });
      }
    } catch (error) {
      traceError('intercept', 'XHR live getter installation was rejected by the page realm', error, { endpointKind: tensorEndpointKind(meta.url) });
    }
  }

  function readXhrPayload(xhr, nativeGetText, nativeGetResponse) {
    try {
      const type = String(xhr.responseType || '').toLowerCase();
      if (type === 'json' && nativeGetResponse) return nativeGetResponse.call(xhr);
      const text = nativeGetText ? nativeGetText.call(xhr) : '';
      return text ? JSON.parse(text) : null;
    } catch { return null; }
  }

  function installXhrInterceptor() {
    if (state.xhrInstalled || !PAGE.XMLHttpRequest?.prototype) return;
    state.xhrInstalled = true;
    const proto = PAGE.XMLHttpRequest.prototype;
    const nativeOpen = proto.open;
    const nativeSend = proto.send;
    const nativeAbort = proto.abort;
    const nativeSetHeader = proto.setRequestHeader;
    const responseTextDescriptor = Object.getOwnPropertyDescriptor(proto, 'responseText');
    const responseDescriptor = Object.getOwnPropertyDescriptor(proto, 'response');
    const nativeGetText = responseTextDescriptor?.get || null;
    const nativeGetResponse = responseDescriptor?.get || null;

    proto.open = function (method, url) {
      try { if (this.__fiLite) this.__fiLite.cancelled = true; } catch {}
      this.__fiLite = {
        method: String(method || 'GET').toUpperCase(),
        url: normalizeUrl(url),
        async: arguments.length < 3 || arguments[2] !== false,
        headers: {},
        body: null,
        snapshot: null,
        gettersInstalled: false,
        backfillStarted: false,
        cancelled: false,
        sendQueued: false,
        sendStarted: false
      };
      return nativeOpen.apply(this, arguments);
    };

    if (typeof nativeAbort === 'function') {
      proto.abort = function () {
        try { if (this.__fiLite) this.__fiLite.cancelled = true; } catch {}
        return nativeAbort.apply(this, arguments);
      };
    }

    proto.setRequestHeader = function (name, value) {
      try { if (this.__fiLite) this.__fiLite.headers[String(name || '').toLowerCase()] = String(value ?? ''); } catch {}
      return nativeSetHeader.apply(this, arguments);
    };

    const sendPrepared = (xhr, meta, body) => {
      if (meta.cancelled || xhr.__fiLite !== meta || meta.sendStarted) return undefined;
      meta.sendStarted = true;
      if (isRelevantTensorEndpoint(meta.url) && !fiBridgeOwnsSharedRoutes()) return nativeSend.call(xhr, body);
      if (!state.settings.interceptEnabled) return nativeSend.call(xhr, body);
      captureRequest(meta.url, meta.headers);
      let outgoingBody = body;
      if (isTaskQueryEndpoint(meta.url) && meta.method !== 'GET' && meta.method !== 'HEAD') {
        const rewritten = rewritePayload(body);
        if (rewritten.changed) outgoingBody = rewritten.body;
      }
      if (isTaskApiEndpoint(meta.url)) installXhrGetters(xhr, meta, nativeGetText, nativeGetResponse);
      meta.body = outgoingBody;
      try {
        xhr.addEventListener('load', () => {
          if (xhr.status < 200 || xhr.status >= 300) return;
          const payload = readXhrPayload(xhr, nativeGetText, nativeGetResponse);
          if (!payload && !isLibraryEndpoint(meta.url)) return;
          if (isDownloadEndpoint(meta.url)) {
            cacheDownloadPayload(payload, downloadEndpointKind(meta.url));
          } else if (isLibraryEndpoint(meta.url)) {
            processLibraryPayload(meta.url, meta.body, payload, meta.method);
          } else if (isTaskApiEndpoint(meta.url) && !meta.backfillStarted) {
            meta.backfillStarted = true;
            const endpointKind = tensorEndpointKind(meta.url);
            patchBodyAsync(payload, `xhr-${endpointKind}-load`, { endpointKind }).then(result => {
              meta.snapshot = { body: result.body, serialized: JSON.stringify(result.body), changed: result.changed };
            }).catch(error => traceError('intercept', 'XHR load backfill failed', error, { endpointKind }));
          }
        }, { once: true });
      } catch {}
      return nativeSend.call(xhr, outgoingBody);
    };

    proto.send = function (body) {
      const xhr = this;
      const meta = xhr.__fiLite || {
        method: 'GET', url: '', headers: {}, async: true,
        cancelled: false, sendQueued: false, sendStarted: false
      };
      const relevant = isRelevantTensorEndpoint(meta.url);
      if (relevant && !fiBridgeOwnsSharedRoutes()) {
        meta.sendStarted = true;
        return nativeSend.call(xhr, body);
      }
      if (relevant && state.dbReady && !state.settings.interceptEnabled) {
        meta.sendStarted = true;
        return nativeSend.call(xhr, body);
      }
      const hasExplicitIdentity = isUsableTensorToken(bearerFromHeaders(meta.headers));
      if (relevant && meta.async === false && (!state.dbReady || !hasExplicitIdentity)) {
        // Synchronous XHR cannot wait for IDB or cookie reconciliation. Forward
        // it untouched rather than risking defaults or a stale-account cache.
        meta.sendStarted = true;
        return nativeSend.call(xhr, body);
      }
      if (relevant && (!state.dbReady || !hasExplicitIdentity)) {
        if (meta.async === false) {
          meta.sendStarted = true;
          return nativeSend.call(xhr, body);
        }
        if (meta.sendQueued) return undefined;
        meta.sendQueued = true;
        Promise.resolve().then(async () => {
          if (!state.dbReady) await database.open().catch(() => null);
          if (state.settings.interceptEnabled && !hasExplicitIdentity) {
            await reconcileRequestIdentity(meta.url, meta.headers);
          }
        }).then(() => {
          if (meta.cancelled || xhr.__fiLite !== meta || xhr.readyState !== 1) return;
          try { sendPrepared(xhr, meta, body); }
          catch (error) {
            state.stats.failures += 1;
            traceError('intercept', 'Deferred XHR send failed', error, { endpointKind: tensorEndpointKind(meta.url) });
          }
        });
        return undefined;
      }
      return sendPrepared(xhr, meta, body);
    };
  }

  function compareVersions(a, b) {
    const parse = value => String(value || '0').replace(/^v/i, '').split(/[.+-]/).map(part => Number(part) || 0);
    const left = parse(a);
    const right = parse(b);
    for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
      const diff = (left[index] || 0) - (right[index] || 0);
      if (diff) return diff > 0 ? 1 : -1;
    }
    return 0;
  }

  function safeUpdateUrl(value) {
    try {
      const url = new URL(String(value || ''), CONFIG_URL);
      if (url.protocol !== 'https:') return '';
      return url.href;
    } catch { return ''; }
  }

  function liteChannelFromConfig(config) {
    return config?.lite_script || config?.lite || config?.scripts?.lite || config?.scripts?.['fi-bypass-lite'] || null;
  }

  function publishedRemoteRow(row) {
    if (!row || typeof row !== 'object' || row.enabled === false) return false;
    const status = String(row.status || '').trim().toLowerCase();
    if (['hidden','draft','disabled','archived','deleted'].includes(status)) return false;
    const now = Date.now();
    const startsAt = Date.parse(row.starts_at || row.startsAt || row.publish_at || row.publishAt || '');
    const endsAt = Date.parse(row.ends_at || row.endsAt || row.expires_at || row.expiresAt || '');
    return !(Number.isFinite(startsAt) && startsAt > now) && !(Number.isFinite(endsAt) && endsAt <= now);
  }

  function remoteRowTargetsLite(row) {
    if (row?.lite === true || row?.is_lite === true || row?.isLite === true) return true;
    const fields = [row?.script, row?.script_id, row?.scriptId, row?.channel, row?.target, row?.target_script, row?.targetScript, row?.targets, row?.target_scripts, row?.targetScripts];
    const tokens = fields.flatMap(value => Array.isArray(value) ? value : [value]).flatMap(value => String(value || '').toLowerCase().split(/[\s,|/]+/)).filter(Boolean);
    if (tokens.some(value => ['lite','fi-lite','fi-bypass-lite','fi_bypass_lite','userscript-lite','userscript_lite'].includes(value))) return true;
    const publisherHint = String(row?.id || '') + ' ' + String(row?.title || '') + ' ' + String(row?.name || '');
    return /(?:fi[\s_-]*bypass|userscript)[\s_-]*lite/.test(publisherHint.toLowerCase());
  }

  function liteScopedRows(config, channel, name) {
    const direct = [
      ...(Array.isArray(config?.[`lite_${name}`]) ? config[`lite_${name}`] : []),
      ...(Array.isArray(channel?.[name]) ? channel[name] : [])
    ];
    const targeted = (Array.isArray(config?.[name]) ? config[name] : []).filter(remoteRowTargetsLite);
    const seen = new Set();
    return direct.concat(targeted).filter(row => {
      if (!publishedRemoteRow(row)) return false;
      const key = String(row.id || `${row.version || ''}|${row.title || ''}|${row.date || row.released || ''}`);
      if (seen.has(key)) return false;
      seen.add(key);
      return true;
    });
  }

  function remotePlainText(value, limit = 4000) {
    const source = String(value || '').replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, ' ').replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ' ').replace(/<[^>]+>/g, ' ').replace(/&nbsp;/gi, ' ').replace(/&amp;/gi, '&').replace(/&lt;/gi, '<').replace(/&gt;/gi, '>').replace(/&quot;/gi, '"').replace(/&#39;/gi, "'").replace(/\s+/g, ' ').trim();
    return source.length > limit ? `${source.slice(0, limit - 1)}…` : source;
  }

  function normalizedLiteAnnouncements(config, channel) {
    const priorityValue = value => ({ critical: 5, urgent: 4, high: 3, normal: 2, info: 1, low: 0 }[String(value || '').toLowerCase()] ?? 1);
    return liteScopedRows(config, channel, 'announcements').map((row, index) => {
      const message = remotePlainText(row.content?.text || row.message?.text || row.content?.markdown || row.message?.markdown || row.text || row.description || row.content?.html || row.message?.html || (typeof row.message === 'string' ? row.message : '') || (typeof row.content === 'string' ? row.content : ''));
      const title = remotePlainText(row.title || row.name || 'FI-Bypass Lite announcement', 180);
      const id = remotePlainText(row.id || `${row.version || 'notice'}-${row.date || row.released || index}-${title}`, 240);
      return {
        id, title, message,
        severity: ['critical','warning','success','info'].includes(String(row.severity || row.priority || row.type || '').toLowerCase()) ? String(row.severity || row.priority || row.type).toLowerCase() : 'info',
        priority: priorityValue(row.priority || row.severity),
        date: remotePlainText(row.date || row.released || row.published_at || row.publishedAt || '', 80),
        author: remotePlainText(row.author || 'TheFreeOne Guy', 120),
        url: safeUpdateUrl(row.url || row.open_url || row.openUrl || row.download_url || ''),
        urlLabel: remotePlainText(row.url_label || row.urlLabel || row.links?.[0]?.label || 'Open link', 80)
      };
    }).filter(row => row.id && row.title && row.message).sort((a, b) => b.priority - a.priority || String(b.date).localeCompare(String(a.date))).slice(0, 50);
  }

  function unreadLiteAnnouncements() {
    const read = new Set(Array.isArray(state.announcementState?.readIds) ? state.announcementState.readIds : []);
    return state.announcements.filter(row => !read.has(row.id));
  }

  function applyRemoteContentState(config) {
    const liteChannel = liteChannelFromConfig(config);
    const liteUpdates = liteScopedRows(config, liteChannel, 'updates').sort((a, b) => compareVersions(b?.version, a?.version));
    const channelVersion = String(liteChannel?.version || config?.lite_version || config?.script?.lite_version || '').trim();
    const newestRow = liteUpdates[0] || null;
    const newestRowVersion = String(newestRow?.version || '').trim();
    const releaseRow = newestRowVersion && (!channelVersion || compareVersions(newestRowVersion, channelVersion) >= 0) ? newestRow : null;
    const remoteVersion = String(releaseRow?.version || channelVersion || newestRowVersion || '').trim();
    state.update = remoteVersion ? {
      remoteVersion,
      available: compareVersions(remoteVersion, SCRIPT_VERSION) > 0,
      required: !!(releaseRow?.required || releaseRow?.required_update || liteChannel?.required_update),
      channelAvailable: true,
      title: remotePlainText(releaseRow?.title || liteChannel?.display_name || SCRIPT_NAME, 180),
      notes: remotePlainText(releaseRow?.message?.text || releaseRow?.message?.markdown || releaseRow?.message?.html || (typeof releaseRow?.message === 'string' ? releaseRow.message : '') || releaseRow?.release_notes || liteChannel?.release_notes || '', 4000),
      downloadUrl: safeUpdateUrl(releaseRow?.download_url || liteChannel?.download_url || liteChannel?.repository || ''),
      checkedAt: Date.now()
    } : { remoteVersion: SCRIPT_VERSION, available: false, required: false, channelAvailable: false, downloadUrl: '', checkedAt: Date.now() };
    state.announcements = state.settings.remoteAnnouncementsEnabled ? normalizedLiteAnnouncements(config, liteChannel) : [];
    return state.update;
  }

  function refreshRemoteContentUi() {
    if (state.ui?.panel && state.activeTab === 'settings') renderSettings();
    if (state.ui?.panel && state.activeTab === 'announcements') renderAnnouncements();
    updateFabBadge();
    updateAnnouncementBadge();
    showLatestLiteAnnouncementNotice();
  }

  function markLiteAnnouncementsRead(ids) {
    const current = new Set(Array.isArray(state.announcementState?.readIds) ? state.announcementState.readIds : []);
    (Array.isArray(ids) ? ids : [ids]).map(String).filter(Boolean).forEach(id => current.add(id));
    state.announcementState = { readIds: [...current].slice(-100), updatedAt: Date.now() };
    state.announcementStateUpdatedAt = state.announcementState.updatedAt;
    database.put('kv', { key: ANNOUNCEMENT_STATE_KEY, value: clone(state.announcementState), updatedAt: state.announcementStateUpdatedAt });
    updateFabBadge();
    updateAnnouncementBadge();
  }

  function parseResponseHeaders(raw) {
    const result = {};
    String(raw || '').split(/\r?\n/).forEach(line => {
      const index = line.indexOf(':');
      if (index > 0) result[line.slice(0, index).trim().toLowerCase()] = line.slice(index + 1).trim();
    });
    return result;
  }

  function requestRemoteConfig(headers) {
    const gmRequest = typeof GM !== 'undefined' && typeof GM.xmlHttpRequest === 'function'
      ? GM.xmlHttpRequest.bind(GM)
      : (typeof GM_xmlhttpRequest === 'function' ? GM_xmlhttpRequest : null);
    if (gmRequest) {
      return new Promise(resolve => {
        try {
          gmRequest({
            method: 'GET', url: CONFIG_URL, headers, timeout: 12_000,
            onload(response) {
              const headerMap = parseResponseHeaders(response.responseHeaders);
              resolve({
                status: Number(response.status || 0),
                etag: headerMap.etag || null,
                lastModified: headerMap['last-modified'] || null,
                text: String(response.responseText || '')
              });
            },
            onerror: () => { traceError('config', 'Remote config request failed', new Error('network failure')); resolve(null); },
            ontimeout: () => { traceError('config', 'Remote config request timed out', new Error('timeout')); resolve(null); },
            onabort: () => { diagnostic('warn', 'config', 'Remote config request was aborted'); resolve(null); }
          });
        } catch (error) { traceError('config', 'Remote config request could not start', error); resolve(null); }
      });
    }
    if (!nativeFetch) return Promise.resolve(null);
    return nativeFetch(CONFIG_URL, { headers, cache: 'no-store' }).then(async response => ({
      status: response.status,
      etag: response.headers.get('etag'),
      lastModified: response.headers.get('last-modified'),
      text: await response.text()
    })).catch(error => { traceError('config', 'Remote config fetch failed', error); return null; });
  }

  async function checkRemoteConfig(force = false) {
    await database.open();
    if (!state.settings.remoteUpdateEnabled && !state.settings.remoteAnnouncementsEnabled && !force) return state.update;
    const meta = state.configMeta || {};
    if (!force && state.config && Date.now() - Number(meta.lastCheckedAt || 0) < state.settings.remoteConfigTtlMs) {
      const cachedUpdate = applyRemoteContentState(state.config);
      refreshRemoteContentUi();
      return cachedUpdate;
    }
    const requestHeaders = {};
    if (meta.etag) requestHeaders['If-None-Match'] = meta.etag;
    if (meta.lastModified) requestHeaders['If-Modified-Since'] = meta.lastModified;
    let response = await requestRemoteConfig(requestHeaders);
    let retriedWithoutValidators = false;
    if (response?.status === 304 && !state.config) {
      retriedWithoutValidators = true;
      response = await requestRemoteConfig({});
    }
    const checkedAt = Date.now();
    const resultMeta = retriedWithoutValidators ? { ...meta, etag: null, lastModified: null } : meta;
    if (!response) {
      state.configMeta = { ...resultMeta, lastCheckedAt: checkedAt, lastStatus: 0 };
    } else if (response.status === 304 && state.config) {
      state.configMeta = { ...resultMeta, lastCheckedAt: checkedAt, lastStatus: 304 };
    } else if (response.status >= 200 && response.status < 300) {
      try {
        const parsed = JSON.parse(response.text);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('Remote config root must be an object.');
        state.config = parsed;
        state.configUpdatedAt = checkedAt;
        state.configMeta = {
          etag: response.etag || null,
          lastModified: response.lastModified || null,
          lastCheckedAt: checkedAt,
          lastOkAt: checkedAt,
          lastStatus: response.status
        };
        await database.put('kv', { key: CONFIG_KEY, value: parsed, updatedAt: checkedAt });
      } catch (error) {
        state.configMeta = { ...resultMeta, lastCheckedAt: checkedAt, lastStatus: response.status };
        traceError('config', 'Remote config JSON was invalid', error, { status: response.status });
      }
    } else {
      state.configMeta = { ...resultMeta, lastCheckedAt: checkedAt, lastStatus: response.status };
      traceError('config', 'Remote config returned an unsuccessful status', new Error(`HTTP ${response.status}`), { status: response.status });
    }
    state.configMetaUpdatedAt = checkedAt;
    await database.put('kv', { key: CONFIG_META_KEY, value: state.configMeta, updatedAt: checkedAt });
    const update = applyRemoteContentState(state.config);
    refreshRemoteContentUi();
    return update;
  }

  function escapeHtml(value) {
    return String(value ?? '').replace(/[&<>"']/g, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[char]);
  }

  function diagnosticsExportText() {
    const max = numberInRange(state.settings.diagnosticsMaxEntries, 200, 25, 500);
    const payload = {
      schema: 'fi-bypass-lite-diagnostics-v1',
      script: { name: SCRIPT_NAME, version: SCRIPT_VERSION },
      generatedAt: new Date().toISOString(),
      stats: redactDiagnosticValue(state.stats),
      entries: state.diagnostics.slice(-max).map(entry => redactDiagnosticValue(entry))
    };
    return JSON.stringify(payload, null, 2);
  }

  async function copyDiagnostics() {
    const text = diagnosticsExportText();
    try { await navigator.clipboard.writeText(text); return true; }
    catch {
      try {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        textarea.style.position = 'fixed';
        textarea.style.opacity = '0';
        document.body.appendChild(textarea);
        textarea.select();
        const copied = document.execCommand('copy');
        textarea.remove();
        return copied;
      } catch (error) {
        traceError('diagnostics', 'Copying diagnostics failed', error);
        return false;
      }
    }
  }

  function downloadDiagnostics() {
    try {
      const blob = new Blob([diagnosticsExportText()], { type: 'application/json;charset=utf-8' });
      const url = URL.createObjectURL(blob);
      const anchor = document.createElement('a');
      anchor.href = url;
      anchor.download = `FI-Bypass-Lite-errors-${new Date().toISOString().replace(/[:.]/g, '-')}.json`;
      anchor.style.display = 'none';
      document.body.appendChild(anchor);
      anchor.click();
      anchor.remove();
      setTimeout(() => URL.revokeObjectURL(url), 1000);
      return true;
    } catch (error) {
      traceError('diagnostics', 'Downloading diagnostics failed', error);
      return false;
    }
  }

  function clearDiagnostics() {
    state.diagnostics.length = 0;
    updateErrorBadge();
    if (state.activeTab === 'errors') renderErrors();
  }

  function updateErrorBadge() {
    const errors = state.diagnostics.filter(entry => entry.level === 'error');
    const count = errors.length;
    const badge = state.ui?.panel?.querySelector?.('[data-error-count]');
    if (badge) badge.textContent = String(count || '');
    const icon = state.ui?.panel?.querySelector?.('[data-error-alert]');
    if (icon) {
      icon.hidden = count === 0;
      icon.dataset.count = String(count);
      icon.title = count ? `${count} Lite error${count === 1 ? '' : 's'} · ${errors.at(-1)?.message || 'Open diagnostics'}` : 'No Lite errors';
      icon.setAttribute('aria-label', count ? `Open ${count} Lite error message${count === 1 ? '' : 's'}` : 'No Lite errors');
      const iconCount = icon.querySelector('[data-error-icon-count]');
      if (iconCount) iconCount.textContent = String(count);
    }
  }

  function injectStyle() {
    if (document.getElementById('fi-lite-style')) return;
    const style = document.createElement('style');
    style.id = 'fi-lite-style';
    style.textContent = `
.fi-l-alert{position:relative;color:#fda4af!important;border-color:rgba(251,113,133,.55)!important}.fi-l-alert span{position:absolute;right:-4px;top:-5px;min-width:14px;height:14px;padding:0 2px;display:grid;place-items:center;border-radius:999px;background:#fb7185;color:#fff;font:800 8px system-ui}.fi-l-alert[hidden]{display:none}
#fi-lite-fab{position:fixed;right:18px;bottom:22px;z-index:2147483645;width:48px;height:48px;border-radius:50%;border:1px solid rgba(34,211,238,.55);background:linear-gradient(145deg,#082f49,#312e81);color:#ecfeff;box-shadow:0 10px 32px rgba(0,0,0,.48);font:800 13px system-ui;cursor:pointer;display:grid;place-items:center}
#fi-lite-fab:hover{transform:translateY(-2px)}#fi-lite-fab[data-update="1"]:after{content:"";position:absolute;right:1px;top:1px;width:10px;height:10px;border-radius:50%;background:#fb7185;box-shadow:0 0 10px #fb7185}
#fi-lite-panel{position:fixed;right:18px;bottom:82px;z-index:2147483646;width:min(430px,calc(100vw - 20px));max-height:min(650px,calc(100vh - 100px));display:flex;flex-direction:column;background:#060b16;color:#e2e8f0;border:1px solid rgba(34,211,238,.28);border-radius:16px;box-shadow:0 22px 70px rgba(0,0,0,.62);font:12px/1.45 system-ui,sans-serif;overflow:hidden;opacity:0;transform:translateY(8px) scale(.98);pointer-events:none;transition:.14s ease}
#fi-lite-panel[data-open="1"]{opacity:1;transform:none;pointer-events:auto}.fi-l-head{display:flex;align-items:center;gap:10px;padding:12px 14px;background:linear-gradient(90deg,rgba(8,145,178,.14),rgba(67,56,202,.12));border-bottom:1px solid rgba(148,163,184,.13)}.fi-l-title{flex:1}.fi-l-title b{display:block;color:#67e8f9;font-size:13px}.fi-l-title small{color:#64748b}.fi-l-icon{border:1px solid #334155;background:#0f172a;color:#cbd5e1;border-radius:8px;width:30px;height:30px;cursor:pointer}.fi-l-tabs{display:flex;padding:8px 10px 0;gap:7px}.fi-l-tab{flex:1;padding:8px;border:1px solid #1e293b;border-radius:9px 9px 0 0;background:#0b1220;color:#64748b;font-weight:700;cursor:pointer}.fi-l-tab[data-active="1"]{color:#67e8f9;border-color:rgba(34,211,238,.42);background:rgba(8,145,178,.1)}.fi-l-tab-count{display:inline-grid;place-items:center;min-width:14px;height:14px;margin-left:3px;padding:0 3px;border-radius:999px;background:#fb7185;color:#fff;font:800 8px system-ui}.fi-l-tab-count:empty{display:none}.fi-l-body{overflow:auto;padding:10px;overscroll-behavior:contain}.fi-l-summary{display:flex;justify-content:space-between;align-items:center;padding:7px 8px;color:#64748b}.fi-l-card{display:flex;gap:10px;padding:10px;margin-bottom:7px;border:1px solid #182238;border-radius:11px;background:linear-gradient(135deg,#0b1220,#070b14)}.fi-l-thumb{width:64px;height:64px;flex:0 0 64px;border-radius:9px;object-fit:cover;background:#111827;border:1px solid #1e293b}.fi-l-media-placeholder{display:grid;place-items:center;color:#475569;font-size:20px}.fi-l-main{min-width:0;flex:1}.fi-l-id{font:700 10px ui-monospace,monospace;color:#a5b4fc}.fi-l-url{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#64748b;font-size:10px;margin:4px 0}.fi-l-actions{display:flex;gap:5px;flex-wrap:wrap}.fi-l-btn{border:1px solid #334155;background:#111827;color:#cbd5e1;border-radius:7px;padding:5px 8px;font:700 10px system-ui;cursor:pointer}.fi-l-btn:hover{border-color:#22d3ee;color:#67e8f9}.fi-l-empty{text-align:center;color:#475569;padding:36px 15px}.fi-l-section{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:#64748b;margin:4px 2px 8px}.fi-l-setting{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:center;padding:9px 10px;margin-bottom:6px;border:1px solid #172033;border-radius:10px;background:#0a101d}.fi-l-setting b{display:block;color:#cbd5e1}.fi-l-setting small{display:block;color:#526078}.fi-l-setting input[type="number"]{width:88px}.fi-l-setting input,.fi-l-setting textarea{accent-color:#22d3ee;background:#060b16;color:#e2e8f0;border:1px solid #334155;border-radius:7px;padding:6px}.fi-l-setting textarea{grid-column:1/-1;width:100%;min-height:92px;box-sizing:border-box;font:10px ui-monospace,monospace}.fi-l-update{padding:10px;margin-bottom:8px;border:1px solid #334155;border-radius:10px;background:#0b1220;color:#94a3b8}.fi-l-update[data-ready="1"]{border-color:rgba(251,113,133,.45);color:#fecdd3}.fi-l-toolbar{display:flex;gap:6px;flex-wrap:wrap;margin-top:9px}.fi-l-announcements{display:grid;gap:8px}.fi-l-announcement{padding:11px;border:1px solid #263653;border-left:4px solid #22d3ee;border-radius:11px;background:linear-gradient(135deg,#0b1220,#070b14)}.fi-l-announcement[data-severity="critical"]{border-left-color:#fb7185}.fi-l-announcement[data-severity="warning"]{border-left-color:#fbbf24}.fi-l-announcement[data-severity="success"]{border-left-color:#34d399}.fi-l-announcement-head{display:flex;justify-content:space-between;gap:8px}.fi-l-announcement-head b{color:#dbeafe}.fi-l-announcement-head small,.fi-l-announcement-meta{color:#64748b}.fi-l-announcement p{margin:7px 0;color:#a7b5ca;white-space:pre-wrap;word-break:break-word}.fi-l-remote-toast{position:fixed;right:18px;bottom:82px;z-index:2147483647;width:min(380px,calc(100vw - 28px));box-sizing:border-box;padding:13px;border:1px solid rgba(34,211,238,.5);border-left:4px solid #22d3ee;border-radius:14px;background:linear-gradient(145deg,#08111f,#0f172a);color:#dbeafe;box-shadow:0 20px 70px rgba(0,0,0,.7);font:12px/1.45 system-ui}.fi-l-remote-toast[data-severity="critical"]{border-left-color:#fb7185}.fi-l-remote-toast[data-severity="warning"]{border-left-color:#fbbf24}.fi-l-remote-toast[data-severity="success"]{border-left-color:#34d399}.fi-l-remote-toast b{display:block;color:#67e8f9;margin-bottom:4px}.fi-l-remote-toast p{margin:0;color:#a7b5ca}.fi-l-remote-toast .fi-l-toolbar{justify-content:flex-end}@media(max-width:560px){#fi-lite-fab{right:14px;bottom:18px}#fi-lite-panel{left:0;right:0;bottom:0;width:100%;max-height:86vh;border-radius:18px 18px 0 0}.fi-l-remote-toast{right:10px;bottom:76px;width:calc(100vw - 20px)}}
#fi-lite-panel{width:min(560px,calc(100vw - 20px));background:radial-gradient(circle at 100% 0,rgba(79,70,229,.13),transparent 32%),#060b16}.fi-l-head>div:first-child{width:34px;height:34px;display:grid;place-items:center;border-radius:10px;background:linear-gradient(145deg,#0891b2,#4f46e5);box-shadow:0 0 20px rgba(34,211,238,.18);font-size:17px}.fi-l-summary{border:1px solid #18243a;border-radius:10px;background:rgba(15,23,42,.7);margin-bottom:8px}.fi-l-controls{display:grid;grid-template-columns:minmax(130px,1fr) auto auto;gap:6px;margin-bottom:9px}.fi-l-search,.fi-l-select{box-sizing:border-box;min-width:0;border:1px solid #263653;border-radius:8px;background:#08101e;color:#dbeafe;padding:7px 8px;font:600 10px system-ui}.fi-l-items{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.fi-l-items[data-layout="list"]{grid-template-columns:1fr}.fi-l-items .fi-l-card{margin:0;min-width:0;position:relative;flex-direction:column;cursor:pointer}.fi-l-items .fi-l-card:focus-visible{outline:2px solid #22d3ee;outline-offset:2px}.fi-l-items[data-layout="list"] .fi-l-card{flex-direction:row}.fi-l-items .fi-l-thumb{width:100%;height:116px;flex-basis:auto}.fi-l-items[data-layout="list"] .fi-l-thumb{width:74px;height:74px;flex:0 0 74px}.fi-l-grade{position:absolute;top:7px;left:7px;display:inline-flex;align-items:center;gap:4px;padding:3px 7px;border:1px solid currentColor;border-radius:999px;background:rgba(2,6,23,.86);font:900 10px system-ui;box-shadow:0 3px 12px rgba(0,0,0,.42)}.fi-l-meta{display:flex;gap:5px;flex-wrap:wrap;margin:5px 0}.fi-l-chip{border:1px solid #27354e;border-radius:999px;padding:2px 6px;color:#8291aa;font:700 9px system-ui}.fi-l-card[data-grade="A"]{border-color:rgba(52,211,153,.3)}.fi-l-card[data-grade="B"]{border-color:rgba(34,211,238,.3)}.fi-l-card[data-grade="C"]{border-color:rgba(251,191,36,.3)}.fi-l-card[data-grade="D"]{border-color:rgba(251,113,133,.32)}.fi-l-btn:disabled{opacity:.35;cursor:not-allowed}.fi-l-btn[data-active="1"]{border-color:#22d3ee;color:#67e8f9;background:rgba(8,145,178,.14)}.fi-l-setting select{background:#060b16;color:#e2e8f0;border:1px solid #334155;border-radius:7px;padding:6px}.fi-l-runtime{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px;margin-top:8px}.fi-l-runtime span{padding:6px;border:1px solid #1c2940;border-radius:8px;text-align:center;color:#8291aa}.fi-l-runtime b{display:block;color:#67e8f9}.fi-l-status{color:#64748b;font:9px ui-monospace,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fi-l-errors{display:grid;gap:7px}.fi-l-error{border:1px solid #26334a;border-left:3px solid #64748b;border-radius:9px;background:#080f1c;padding:8px}.fi-l-error[data-level="error"]{border-left-color:#fb7185}.fi-l-error[data-level="warn"]{border-left-color:#fbbf24}.fi-l-error-head{display:flex;justify-content:space-between;gap:8px;color:#94a3b8;font:700 9px ui-monospace,monospace}.fi-l-error-msg{margin:5px 0;color:#dbeafe;word-break:break-word}.fi-l-error pre{margin:4px 0 0;max-height:120px;overflow:auto;white-space:pre-wrap;color:#64748b;font:9px/1.4 ui-monospace,monospace}.fi-l-secret{width:min(230px,45vw);box-sizing:border-box}.fi-l-preview{position:fixed;inset:0;z-index:2147483647;display:none;place-items:center;padding:18px;background:rgba(2,6,23,.9);backdrop-filter:blur(8px)}.fi-l-preview[data-open="1"]{display:grid}.fi-l-preview-card{width:min(1100px,96vw);max-height:94vh;display:grid;grid-template-rows:auto minmax(0,1fr) auto;overflow:hidden;border:1px solid rgba(34,211,238,.36);border-radius:16px;background:#050a13;color:#e2e8f0;box-shadow:0 30px 100px #000;font:12px system-ui}.fi-l-preview-head,.fi-l-preview-foot{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid #1e293b}.fi-l-preview-head b{flex:1;color:#67e8f9}.fi-l-preview-foot{border:0;border-top:1px solid #1e293b;flex-wrap:wrap}.fi-l-preview-stage{min-height:200px;display:grid;place-items:center;overflow:auto;background:#02040a}.fi-l-preview-stage img,.fi-l-preview-stage video{display:block;max-width:100%;max-height:72vh;object-fit:contain}.fi-l-preview-meta{flex:1;min-width:180px;color:#94a3b8;word-break:break-word}@media(max-width:560px){.fi-l-items{grid-template-columns:1fr}.fi-l-controls{grid-template-columns:1fr auto}.fi-l-controls .fi-l-search{grid-column:1/-1}}
    `;
    (document.head || document.documentElement).appendChild(style);
  }

  function createUi() {
    if (state.ui || !document.body) return;
    injectStyle();
    const fab = document.createElement('button');
    fab.id = 'fi-lite-fab';
    fab.type = 'button';
    fab.title = 'Open FI-Bypass Lite';
    fab.setAttribute('aria-label', 'Open FI-Bypass Lite');
    fab.textContent = 'FI';

    const panel = document.createElement('section');
    panel.id = 'fi-lite-panel';
    panel.setAttribute('aria-label', 'FI-Bypass Lite');
    panel.innerHTML = `
      <header class="fi-l-head"><div aria-hidden="true">◈</div><div class="fi-l-title"><b>${SCRIPT_NAME}</b><small>Tensor core bypass · v${SCRIPT_VERSION}</small></div><button class="fi-l-icon fi-l-alert" data-action="open-errors" data-error-alert hidden><span data-error-icon-count></span>!</button><button class="fi-l-icon" data-action="refresh" title="Refresh items">↻</button><button class="fi-l-icon" data-action="close" title="Close">×</button></header>
      <nav class="fi-l-tabs"><button class="fi-l-tab" data-tab="items">Items</button><button class="fi-l-tab" data-tab="announcements">News <span class="fi-l-tab-count" data-announcement-count>${unreadLiteAnnouncements().length || ''}</span></button><button class="fi-l-tab" data-tab="errors">Errors <span data-error-count>${state.diagnostics.filter(entry => entry.level === 'error').length || ''}</span></button><button class="fi-l-tab" data-tab="settings">Settings</button></nav>
      <div class="fi-l-body" id="fi-lite-body"></div>
    `;
    document.body.append(fab, panel);
    state.ui = { fab, panel, body: panel.querySelector('#fi-lite-body') };
    updateErrorBadge();
    fab.addEventListener('click', lifecycle.onClick);
    panel.addEventListener('click', lifecycle.onClick);
    panel.addEventListener('change', onSettingChange);
    panel.addEventListener('input', onItemsControlInput);
    panel.addEventListener('change', onItemsControlInput);
    panel.addEventListener('keydown', event => {
      const card = event.target?.closest?.('.fi-l-card[data-item-id]');
      if (card && (event.key === 'Enter' || event.key === ' ')) {
        event.preventDefault();
        openPreview(card.dataset.itemId, card);
      }
    });
    document.addEventListener('keydown', event => {
      const preview = state.ui?.preview;
      if (event.key === 'Escape' && preview?.dataset.open === '1') closePreview();
      else if (event.key === 'Tab' && preview?.dataset.open === '1') {
        const focusable = [...preview.querySelectorAll('button:not(:disabled),a[href],video[controls]')];
        if (!focusable.length) return;
        const first = focusable[0];
        const last = focusable[focusable.length - 1];
        if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }
        else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }
      }
    });
    renderActiveTab();
    updateFabBadge();
    updateAnnouncementBadge();
    showLatestLiteAnnouncementNotice();
  }

  function setPanelOpen(open) {
    if (!state.ui) return;
    state.ui.panel.dataset.open = open ? '1' : '0';
    state.ui.fab.setAttribute('aria-expanded', open ? 'true' : 'false');
    if (open) renderActiveTab();
  }

  function updateFabBadge() {
    if (state.ui?.fab) state.ui.fab.dataset.update = (state.update?.available || unreadLiteAnnouncements().length) ? '1' : '0';
  }

  function updateAnnouncementBadge() {
    const badge = state.ui?.panel?.querySelector?.('[data-announcement-count]');
    if (badge) badge.textContent = String(unreadLiteAnnouncements().length || '');
  }

  function dismissAnnouncementToast({ markRead = false } = {}) {
    const toast = state.announcementToast;
    if (!toast) return;
    clearTimeout(toast.__fiTimer);
    if (markRead && toast.dataset.announcementId) markLiteAnnouncementsRead(toast.dataset.announcementId);
    try { toast.remove(); } catch {}
    if (state.announcementToast === toast) state.announcementToast = null;
  }

  function showLatestLiteAnnouncementNotice() {
    if (!state.settings.remoteAnnouncementsEnabled || !state.settings.remoteAnnouncementNoticesEnabled || document.hidden || !document.body) return;
    const notice = unreadLiteAnnouncements().find(row => !state.announcementNotified.has(row.id));
    if (!notice) return;
    dismissAnnouncementToast();
    const toast = document.createElement('aside');
    toast.className = 'fi-l-remote-toast';
    toast.dataset.severity = notice.severity;
    toast.dataset.announcementId = notice.id;
    toast.setAttribute('role', 'status');
    toast.setAttribute('aria-label', 'FI-Bypass Lite announcement');
    toast.innerHTML = `<b>${escapeHtml(notice.title)}</b><p>${escapeHtml(notice.message)}</p><div class="fi-l-toolbar"><button class="fi-l-btn" data-action="announcement-dismiss" data-announcement-id="${escapeHtml(notice.id)}">Dismiss</button><button class="fi-l-btn" data-action="announcement-view" data-announcement-id="${escapeHtml(notice.id)}">View news</button></div>`;
    toast.addEventListener('click', lifecycle.onClick);
    document.body.appendChild(toast);
    state.announcementToast = toast;
    state.announcementNotified.add(notice.id);
    if (state.announcementNotified.size > 100) state.announcementNotified.delete(state.announcementNotified.values().next().value);
    toast.__fiTimer = setTimeout(() => dismissAnnouncementToast(), 12_000);
  }

  function itemHealth(item) {
    const id = itemId(item);
    const library = libraryEntryForImage(id);
    const url = candidateUrl(item, 0) || '';
    const expiry = signedUrlExpiry(url);
    const remainingMs = expiry == null ? null : expiry - Date.now();
    if (isTaskExpired(item) && !library) return { grade: 'D', label: 'Task expired', color: '#fb7185', source: 'Expired task', url, expiry, remainingMs };
    if (library && url) return { grade: 'A', label: 'Stored in Tensor Library', color: '#34d399', source: 'Tensor Library', url, expiry, remainingMs };
    if (url && (remainingMs == null || remainingMs > 10 * 60_000)) return { grade: 'A', label: 'Ready', color: '#34d399', source: 'Download cache', url, expiry, remainingMs };
    if (url && (remainingMs == null || remainingMs > 2 * 60_000)) return { grade: 'B', label: 'Ready soon-expiring', color: '#22d3ee', source: 'Download cache', url, expiry, remainingMs };
    if (url) return { grade: 'C', label: 'Refresh recommended', color: '#fbbf24', source: 'Signed URL', url, expiry, remainingMs };
    return { grade: 'D', label: 'Needs resolution', color: '#fb7185', source: 'Captured metadata', url: '', expiry: null, remainingMs: null };
  }

  function itemDateValue(value) {
    if (typeof value === 'number' && Number.isFinite(value)) return value > 0 && value < 10_000_000_000 ? value * 1000 : value;
    const numeric = Number(value);
    if (Number.isFinite(numeric) && numeric > 0) return numeric < 10_000_000_000 ? numeric * 1000 : numeric;
    const parsed = Date.parse(String(value || ''));
    return Number.isFinite(parsed) ? parsed : 0;
  }

  function itemDisplayDate(item) {
    for (const value of [item?.taskCreatedAt, item?.createdAt, item?.generatedAt, item?.firstSeenAt, item?.libraryCreatedAt, item?.linkedAt]) {
      const timestamp = itemDateValue(value);
      if (timestamp > 0) return timestamp;
    }
    return Number(item?.updatedAt || 0);
  }

  function visibleItems() {
    const query = String(state.itemSearch || '').trim().toLowerCase();
    return [...state.items.values()]
      .filter(item => isEntryForCurrentAccount(item) && (isFreshCacheEntry(item) || libraryEntryForImage(itemId(item))))
      .filter(item => {
        const health = itemHealth(item);
        if (state.itemFilter === 'library' && !item.savedToLibrary) return false;
        if (state.itemFilter === 'ready' && !health.url) return false;
        if (state.itemFilter === 'needs-url' && health.url) return false;
        if (state.itemFilter === 'video' && mediaKind(item.mimeType || item.libraryMimeType) !== 'video') return false;
        if (state.itemFilter === 'expired' && !isTaskExpired(item)) return false;
        if (query) {
          const haystack = `${itemId(item)} ${item.taskId || ''} ${item.downloadFileName || item.fileName || item.libraryFileName || ''}`.toLowerCase();
          if (!haystack.includes(query)) return false;
        }
        return true;
      })
      .sort((a, b) => itemDisplayDate(b) - itemDisplayDate(a) || String(itemId(b)).localeCompare(String(itemId(a)), undefined, { numeric: true }))
      .slice(0, Math.min(state.visibleCount, state.settings.maxVisibleItems));
  }

  function renderActiveTab() {
    if (!state.ui) return;
    state.ui.panel.querySelectorAll('[data-tab]').forEach(button => {
      button.dataset.active = button.dataset.tab === state.activeTab ? '1' : '0';
    });
    if (state.activeTab === 'settings') renderSettings();
    else if (state.activeTab === 'announcements') renderAnnouncements();
    else if (state.activeTab === 'errors') renderErrors();
    else renderItems();
  }

  function renderAnnouncements() {
    const body = state.ui?.body;
    if (!body) return;
    const rows = state.announcements;
    const update = state.update;
    const releaseText = !update?.channelAvailable
      ? 'No dedicated FI-Bypass Lite release is published in main.json yet.'
      : update.available
        ? `FI-Bypass Lite ${escapeHtml(update.remoteVersion)} is available${update.required ? ' and marked required' : ''}.`
        : `FI-Bypass Lite ${escapeHtml(update.remoteVersion)} is the current published release.`;
    body.innerHTML = `
      <div class="fi-l-summary"><b>FI Lite News</b><span>Published through syncore main.json · text only</span></div>
      <div class="fi-l-update" data-ready="${update?.available ? '1' : '0'}"><b>${releaseText}</b>${update?.notes ? `<p>${escapeHtml(update.notes)}</p>` : ''}<small>Remote content is parsed as plain text. No announcement HTML or JavaScript is executed.</small><div class="fi-l-toolbar"><button class="fi-l-btn" data-action="check-update">Refresh</button>${update?.available && update?.downloadUrl ? '<button class="fi-l-btn" data-action="open-update">Open update</button>' : ''}</div></div>
      <div class="fi-l-announcements">${rows.length ? rows.map(row => `<article class="fi-l-announcement" data-severity="${escapeHtml(row.severity)}"><div class="fi-l-announcement-head"><b>${escapeHtml(row.title)}</b><small>${escapeHtml(row.date)}</small></div><p>${escapeHtml(row.message)}</p><div class="fi-l-announcement-meta">${escapeHtml(row.author)}</div>${row.url ? `<div class="fi-l-toolbar"><button class="fi-l-btn" data-action="announcement-open-link" data-announcement-id="${escapeHtml(row.id)}">${escapeHtml(row.urlLabel)}</button></div>` : ''}</article>`).join('') : '<div class="fi-l-empty">No published Lite announcements yet.</div>'}</div>
    `;
    if (rows.length) markLiteAnnouncementsRead(rows.map(row => row.id));
  }

  function renderErrors() {
    const body = state.ui?.body;
    if (!body) return;
    const entries = state.diagnostics.slice().reverse();
    body.innerHTML = `
      <div class="fi-l-summary"><b>Bounded diagnostic trace</b><span>${entries.length} / ${state.settings.diagnosticsMaxEntries} entries · credentials and signed queries redacted</span></div>
      <div class="fi-l-toolbar" style="margin-bottom:9px"><button class="fi-l-btn" data-action="copy-errors">Copy redacted JSON</button><button class="fi-l-btn" data-action="export-errors">Download JSON</button><button class="fi-l-btn" data-action="clear-errors">Clear</button></div>
      <div class="fi-l-errors">${entries.length ? entries.map(entry => `
        <article class="fi-l-error" data-level="${escapeHtml(entry.level)}">
          <div class="fi-l-error-head"><span>${escapeHtml(entry.category)} · ${escapeHtml(entry.level)}</span><time>${escapeHtml(new Date(entry.at).toLocaleTimeString())}</time></div>
          <div class="fi-l-error-msg">${escapeHtml(entry.message)}</div>
          ${entry.context || entry.error ? `<pre>${escapeHtml(JSON.stringify({ ...(entry.context ? { context: entry.context } : {}), ...(entry.error ? { error: entry.error } : {}) }, null, 2))}</pre>` : ''}
        </article>`).join('') : '<div class="fi-l-empty">No diagnostic entries yet.</div>'}</div>`;
  }

  function ensurePreviewDialog() {
    if (state.ui?.preview || !document.body) return state.ui?.preview || null;
    const dialog = document.createElement('div');
    dialog.className = 'fi-l-preview';
    dialog.setAttribute('role', 'dialog');
    dialog.setAttribute('aria-modal', 'true');
    dialog.setAttribute('aria-label', 'Task media preview');
    dialog.innerHTML = '<div class="fi-l-preview-card"><header class="fi-l-preview-head"><b data-preview-title>Media preview</b><button class="fi-l-icon" type="button" data-action="close-preview" aria-label="Close preview">×</button></header><div class="fi-l-preview-stage" data-preview-stage></div><footer class="fi-l-preview-foot"><div class="fi-l-preview-meta" data-preview-meta></div><button class="fi-l-btn" data-action="preview-open">Open original</button><button class="fi-l-btn" data-action="preview-copy">Copy URL</button><button class="fi-l-btn" data-action="preview-download">Download</button></footer></div>';
    dialog.addEventListener('click', lifecycle.onClick);
    dialog.addEventListener('click', event => { if (event.target === dialog) closePreview(); });
    document.body.appendChild(dialog);
    state.ui.preview = dialog;
    return dialog;
  }

  function openPreview(id, returnFocus = null) {
    const { item, url } = itemForAction(id);
    if (!item) return false;
    if (!url) {
      resolveOne(itemId(item), item.mimeType || item.libraryMimeType || '').then(resolved => {
        if (resolved) openPreview(id, returnFocus);
        else diagnostic('warn', 'preview', 'Preview media URL is unavailable', { itemId: itemId(item) });
      }).catch(error => traceError('preview', 'Preview URL resolution failed', error, { itemId: itemId(item) }));
      return true;
    }
    const dialog = ensurePreviewDialog();
    if (!dialog) return false;
    const kind = mediaKind(item.mimeType || item.libraryMimeType);
    const stage = dialog.querySelector('[data-preview-stage]');
    stage.textContent = '';
    const media = document.createElement(kind === 'video' ? 'video' : 'img');
    media.src = url;
    media.referrerPolicy = 'no-referrer';
    if (kind === 'video') { media.controls = true; media.playsInline = true; media.preload = 'metadata'; }
    else media.alt = `Tensor task item ${itemId(item)}`;
    stage.appendChild(media);
    dialog.dataset.itemId = itemId(item);
    dialog.querySelector('[data-preview-title]').textContent = `${kind === 'video' ? 'Video' : 'Image'} · ${item.downloadFileName || item.fileName || itemId(item)}`;
    const dimensions = item.width && item.height ? `${item.width}×${item.height}` : 'dimensions unknown';
    dialog.querySelector('[data-preview-meta]').textContent = `Item ${itemId(item)} · task ${item.taskId || 'detached'} · ${item.mimeType || item.libraryMimeType || kind} · ${dimensions} · ${item.taskStatus || 'cached'}`;
    state.previewReturnFocus = returnFocus || document.activeElement;
    dialog.dataset.open = '1';
    dialog.querySelector('[data-action="close-preview"]')?.focus();
    return true;
  }

  function closePreview() {
    const dialog = state.ui?.preview;
    if (!dialog) return;
    dialog.dataset.open = '0';
    const video = dialog.querySelector('video');
    try { video?.pause(); } catch {}
    dialog.querySelector('[data-preview-stage]').textContent = '';
    try { state.previewReturnFocus?.focus?.(); } catch {}
    state.previewReturnFocus = null;
  }

  function renderItems() {
    const body = state.ui?.body;
    if (!body) return;
    body.textContent = '';
    const items = visibleItems();
    const owned = [...state.items.values()].filter(item => isEntryForCurrentAccount(item));
    const gradeCounts = { A: 0, B: 0, C: 0, D: 0 };
    owned.forEach(item => { gradeCounts[itemHealth(item).grade] += 1; });
    const summary = document.createElement('div');
    summary.className = 'fi-l-summary';
    summary.innerHTML = `<b>Tensor bypass vault</b><span>${items.length} shown · ${owned.length} captured · <i style="color:#34d399">A ${gradeCounts.A}</i> · <i style="color:#22d3ee">B ${gradeCounts.B}</i> · <i style="color:#fbbf24">C ${gradeCounts.C}</i> · <i style="color:#fb7185">D ${gradeCounts.D}</i></span>`;
    body.appendChild(summary);
    const controls = document.createElement('div');
    controls.className = 'fi-l-controls';
    controls.innerHTML = `
      <input class="fi-l-search" data-item-search type="search" value="${escapeHtml(state.itemSearch)}" placeholder="Search image, task, or file…">
      <select class="fi-l-select" data-item-filter>
        ${[['all','All items'],['library','Library linked'],['ready','Ready'],['needs-url','Needs URL'],['video','Videos'],['expired','Expired']].map(([value,label]) => `<option value="${value}" ${state.itemFilter === value ? 'selected' : ''}>${label}</option>`).join('')}
      </select>
      <span><button class="fi-l-btn" data-action="set-layout" data-layout="grid" data-active="${state.settings.itemsLayout === 'grid' ? '1' : '0'}">Grid</button> <button class="fi-l-btn" data-action="set-layout" data-layout="list" data-active="${state.settings.itemsLayout === 'list' ? '1' : '0'}">List</button></span>`;
    body.appendChild(controls);
    const toolbar = document.createElement('div');
    toolbar.className = 'fi-l-toolbar';
    toolbar.style.margin = '0 0 9px';
    const ownsSharedRoutes = fiBridgeOwnsSharedRoutes();
    const delegatesToPro = fiBridgeCanDelegateResolution();
    const resolverAvailable = ownsSharedRoutes || delegatesToPro;
    const bridgeStatus = fiBridgeStatus();
    const actualOwner = String(bridgeStatus.networkOwner || '');
    const ownershipMismatch = bridgeStatus.enabled && !!actualOwner && actualOwner !== bridgeStatus.resolvedPrimary;
    const resolverStatus = ownershipMismatch ? `Ownership mismatch: ${bridgeStatus.resolvedPrimary} selected / ${actualOwner} active · reload required` : ownsSharedRoutes ? 'Lite owns URLs' : delegatesToPro ? 'Pro owns URLs · delegated resolver ready' : 'Pro owns URLs · resolver bridge unavailable';
    toolbar.innerHTML = `<button class="fi-l-btn" data-action="reload-page" title="Reload Tensor exactly like the browser reload button so tasks and media links are fetched again">↻ Reload Tensor page</button><button class="fi-l-btn" data-action="resolve-all" ${resolverAvailable ? '' : 'disabled title="Enable FI Bridge delegation or select Lite as owner, then reload Tensor"'}>Resolve missing</button><button class="fi-l-btn" data-action="cleanup-expired">Clean expired tasks</button><span class="fi-l-status">${resolverStatus} · mget ${state.stats.mgetResponses} · library ${state.stats.libraryResponses} · onload ${state.stats.onLoadResolved}</span>`;
    body.appendChild(toolbar);
    if (ownershipMismatch) {
      const warning = document.createElement('div');
      warning.className = 'fi-l-update';
      warning.dataset.ready = '1';
      warning.innerHTML = `<b>Bridge ownership is not applied to this loaded page</b><br><small>${escapeHtml(bridgeStatus.resolvedPrimary)} is selected, but ${escapeHtml(actualOwner)} still owns the installed Fetch/XHR wrappers. Reload Tensor before resolving or caching more tasks.</small><div class="fi-l-toolbar"><button class="fi-l-btn" data-action="reload-page">Reload Tensor now</button></div>`;
      body.appendChild(warning);
    }
    if (!items.length) {
      const empty = document.createElement('div');
      empty.className = 'fi-l-empty';
      empty.innerHTML = 'No items match this view.<br><small>Open Tensor Tasks or Library so Lite can capture query/mget/list responses.</small>';
      body.appendChild(empty);
      return;
    }
    const grid = document.createElement('div');
    grid.className = 'fi-l-items';
    grid.dataset.layout = state.settings.itemsLayout;
    items.forEach(item => {
      const id = String(item.id || item.imageId || '');
      const health = itemHealth(item);
      const url = health.url;
      const card = document.createElement('article');
      card.className = 'fi-l-card';
      card.dataset.grade = health.grade;
      card.dataset.action = 'preview-item';
      card.dataset.itemId = id;
      card.tabIndex = 0;
      card.setAttribute('role', 'button');
      card.setAttribute('aria-label', `Preview task media ${id}`);
      if (state.settings.cardThumbnails && url && mediaKind(item.mimeType || item.libraryMimeType) === 'video') {
        const video = document.createElement('video');
        video.className = 'fi-l-thumb';
        video.preload = 'metadata';
        video.muted = true;
        video.playsInline = true;
        video.tabIndex = -1;
        video.src = url;
        card.appendChild(video);
      } else if (state.settings.cardThumbnails && url) {
        const image = document.createElement('img');
        image.className = 'fi-l-thumb';
        image.loading = 'lazy';
        image.decoding = 'async';
        image.referrerPolicy = 'no-referrer';
        image.src = url;
        image.alt = '';
        card.appendChild(image);
      } else {
        const placeholder = document.createElement('div');
        placeholder.className = 'fi-l-thumb fi-l-media-placeholder';
        placeholder.textContent = mediaKind(item.mimeType) === 'video' ? '▶' : '◇';
        card.appendChild(placeholder);
      }
      const grade = document.createElement('span');
      grade.className = 'fi-l-grade';
      grade.style.color = health.color;
      grade.textContent = `${health.grade} · ${health.label}`;
      card.appendChild(grade);
      const main = document.createElement('div');
      main.className = 'fi-l-main';
      const expiryText = health.expiry ? new Date(health.expiry).toLocaleTimeString() : 'no signed expiry';
      main.innerHTML = `<div class="fi-l-id">${escapeHtml(id)}</div><div class="fi-l-meta"><span class="fi-l-chip">${escapeHtml(health.source)}</span><span class="fi-l-chip">${escapeHtml(item.taskId || 'detached')}</span><span class="fi-l-chip">${escapeHtml(expiryText)}</span></div><div class="fi-l-url" title="${escapeHtml(url)}">${escapeHtml(url || 'Download URL is not cached yet')}</div>`;
      const actions = document.createElement('div');
      actions.className = 'fi-l-actions';
      [['open', 'Open'], ['copy', 'Copy'], ['download', 'Download'], ['resolve-item', 'Resolve'], ['remove-item', 'Remove']].forEach(([action, label]) => {
        const button = document.createElement('button');
        button.className = 'fi-l-btn';
        button.type = 'button';
        button.dataset.action = action;
        button.dataset.itemId = id;
        button.textContent = label;
        button.disabled = action === 'resolve-item' ? !resolverAvailable : (!url && action !== 'remove-item');
        if (action === 'resolve-item' && !resolverAvailable) button.title = 'Enable FI Bridge delegation or select Lite as owner, then reload Tensor.';
        actions.appendChild(button);
      });
      main.appendChild(actions);
      card.appendChild(main);
      grid.appendChild(card);
    });
    body.appendChild(grid);
    if (state.visibleCount < Math.min(state.items.size, state.settings.maxVisibleItems)) {
      const more = document.createElement('button');
      more.className = 'fi-l-btn';
      more.dataset.action = 'more';
      more.textContent = 'Load more';
      body.appendChild(more);
    }
  }

  function settingRow(key, label, note, type = 'checkbox', limits = {}) {
    const value = state.settings[key];
    let input = '';
    if (type === 'checkbox') input = `<input type="checkbox" data-setting="${key}" ${value ? 'checked' : ''}>`;
    else if (type === 'select') input = `<select data-setting="${key}">${(limits.options || []).map(([optionValue, optionLabel]) => `<option value="${escapeHtml(optionValue)}" ${value === optionValue ? 'selected' : ''}>${escapeHtml(optionLabel)}</option>`).join('')}</select>`;
    else input = `<input type="number" data-setting="${key}" value="${Number(value)}" min="${limits.min ?? 0}" max="${limits.max ?? 999999}" step="${limits.step ?? 1}">`;
    return `<label class="fi-l-setting"><span><b>${escapeHtml(label)}</b><small>${escapeHtml(note)}</small></span>${input}</label>`;
  }

  function textSettingRow(key, label, note, options = {}) {
    const value = String(state.settings[key] || '');
    return `<label class="fi-l-setting"><span><b>${escapeHtml(label)}</b><small>${escapeHtml(note)}</small></span><input class="fi-l-secret" type="${options.secret ? 'password' : 'text'}" data-setting="${key}" value="${escapeHtml(value)}" autocomplete="off" spellcheck="false" placeholder="${escapeHtml(options.placeholder || '')}"></label>`;
  }

  function liteAccountRows() {
    let rows = {};
    try { rows = JSON.parse(PAGE.localStorage?.getItem('freeBypassUserAccounts') || '{}') || {}; } catch {}
    return Object.entries(rows).filter(([token]) => /^eyJ[^.]*\.[^.]+\.[^.]+$/.test(String(token))).slice(0, 30).map(([token, info], index) => ({
      index,
      token,
      userId: String(info?.userId || tokenOwnerFingerprint(token) || ''),
      nickname: String(info?.nickname || `Account ${index + 1}`).slice(0, 80),
      avatar: String(info?.avatar || '').slice(0, 2400),
      active: token === state.lastToken,
    }));
  }

  function switchLiteAccount(index) {
    const account = liteAccountRows()[Number(index)];
    if (!account?.token || account.active) return false;
    try {
      const payload = decodeTensorTokenPayload(account.token);
      const exp = Number(payload?.exp || 0) * 1000;
      if (exp && exp <= Date.now()) throw new Error('This Tensor token expired. Re-add the account first.');
      const expires = new Date(Date.now() + 30 * 86400000).toUTCString();
      document.cookie = `ta_token_prod=${account.token}; path=/; domain=.tensor.art; expires=${expires}; Secure; SameSite=Lax`;
      PAGE.localStorage?.setItem('freeBypassPreviewToken', account.token);
      setTimeout(() => location.reload(), 350);
      return true;
    } catch (error) {
      PAGE.alert(`${SCRIPT_NAME}: ${error?.message || error}`);
      return false;
    }
  }

  function addLiteAccount() {
    const raw = PAGE.prompt(`${SCRIPT_NAME}\n\nPaste the Tensor JWT token for the account you want to add. It stays in Tensor local storage and is never sent to FI Host.`);
    const token = String(raw || '').replace(/^Bearer\s+/i, '').trim();
    if (!token) return false;
    try {
      const payload = decodeTensorTokenPayload(token);
      if (!payload || !/^eyJ[^.]*\.[^.]+\.[^.]+$/.test(token)) throw new Error('The value is not a valid JWT token.');
      if (Number(payload.exp || 0) * 1000 <= Date.now()) throw new Error('The token is expired.');
      let accounts = {};
      try { accounts = JSON.parse(PAGE.localStorage?.getItem('freeBypassUserAccounts') || '{}') || {}; } catch {}
      const userId = String(payload.userId || payload.uid || payload.sub || tokenOwnerFingerprint(token) || '');
      accounts[token] = { ...(accounts[token] || {}), userId, nickname: String(payload.nickname || payload.username || `Account ${userId.slice(-6) || Object.keys(accounts).length + 1}`), timestamp: Date.now() };
      PAGE.localStorage?.setItem('freeBypassUserAccounts', JSON.stringify(accounts));
      renderSettings();
      return true;
    } catch (error) {
      PAGE.alert(`${SCRIPT_NAME}: ${error?.message || error}`);
      return false;
    }
  }

  function renderSettings() {
    const body = state.ui?.body;
    if (!body) return;
    const update = state.update;
    const updateText = update && update.channelAvailable === false
      ? 'Remote config is reachable, but it does not publish a Lite release channel yet.'
      : update?.available
      ? `Update ${escapeHtml(update.remoteVersion)} is available${update.required ? ' (required)' : ''}.`
      : (update ? `Latest remote version: ${escapeHtml(update.remoteVersion)}.` : 'Remote version has not been checked yet.');
    const bridgeStatus = fiBridgeStatus();
    const bridgeActualOwner = String(bridgeStatus.networkOwner || '');
    const bridgeOwnershipMismatch = bridgeStatus.enabled && !!bridgeActualOwner && bridgeActualOwner !== bridgeStatus.resolvedPrimary;
    const hostState = state.host;
    const accounts = liteAccountRows();
    body.innerHTML = `
      <div class="fi-l-update" data-ready="${update?.available ? '1' : '0'}"><b>${updateText}</b><br><small>Only version/update metadata is read. Lite never executes remote HTML or JavaScript.</small></div>
      <div class="fi-l-section">Core interception</div>
      ${settingRow('interceptEnabled', 'Fetch + XHR interception', 'Patch Tensor task-query responses and observe download responses.')}
      ${settingRow('rewriteQuerySize', 'Rewrite query page size', 'Match the main bypass request logic.')}
      ${settingRow('querySize', 'Query page size', 'Applied to size, limit and pageSize fields.', 'number', { min: 1, max: 100 })}
      ${settingRow('resolveMissingUrls', 'Resolve missing URLs', 'Automatically resolve newly observed or bridge-synced missing Items through the elected owner. Manual Resolve always forces a fresh owner request.')}
      ${settingRow('downloadTransport', 'Download resolver transport', 'Auto uses page fetch first and retries 405/CORS failures through GM request.', 'select', { options: [['auto','Auto (405/CORS fallback)'],['page-fetch','Page fetch only'],['gm-request','GM request only']] })}
      ${settingRow('reuseCapturedDownloadHeaders', 'Reuse captured endpoint signatures (expert)', 'Off by default. The Pro-compatible resolver uses only configured headers; enable this only to replay a fresh signature observed on the exact image/video endpoint.')}
      ${settingRow('awaitFetchBackfill', 'Await fetch backfill', 'Return fresh bypass URLs in the same fetch response; disabling reduces query delay.')}
      ${settingRow('resolveOnLoad', 'Resolve active tasks on load', 'Refresh missing signed URLs for unexpired cached task items.')}
      ${settingRow('removeExpiredTasksOnLoad', 'Clean expired tasks on load', 'Use each task expireAt value instead of retaining dead generation records.')}
      ${settingRow('removeExpiredTaskItemsOnLoad', 'Remove expired task items', 'Delete expired item/download projections; Library links remain immune.')}
      ${settingRow('cachingEnabled', 'Persist caches', 'Keep items and signed URLs in IndexedDB between page loads.')}
      <div class="fi-l-section">FI Host direct connection</div>
      <div class="fi-l-update" data-ready="${hostState.connected ? '1' : '0'}"><b>${hostState.connected ? 'Connected to FI Host' : state.settings.fiHostEnabled ? 'FI Host is not connected' : 'FI Host connection is disabled'}</b><br><small>${escapeHtml(hostState.connected ? `Shared Items are active · ${hostState.stored} stored · ${hostState.reused} reused` : hostState.error || 'Enable the bridge, paste the Lite pairing copied from FI Host, then test the connection.')}</small></div>
      ${settingRow('fiHostEnabled', 'Enable direct FI Host connection', 'Connect Lite without the FI extension system. FI Host must also enable the Lite userscript bridge.')}
      ${textSettingRow('fiHostPairing', 'FI Host Lite pairing JSON', 'Copy “Lite pairing” from FI Host → Settings → Connection. The API key remains local and is always redacted from diagnostics.', { secret: true, placeholder: '{"kind":"fi-host-userscript-pairing",…}' })}
      ${settingRow('fiHostAutoStore', 'Automatically store resolved media', 'Create/reuse the shared FI Item record and materialize remote bytes after Lite resolves an Item.')}
      ${settingRow('fiHostUseLocalUrls', 'Use localhost URLs while connected', 'Local URLs are projected only while Host is online. Offline and delivery paths retain Tensor Library/resolved URLs.')}
      ${settingRow('fiHostRewriteSiteMedia', 'Use localhost media in the Tensor page', 'Opt in to replace matching mounted Tensor image/video/audio sources, posters, srcset and preview-list values while Lite owns the bridge and Host is online.')}
      <div class="fi-l-update" data-ready="0"><b>Performance warning</b><br><small>This option scans new or changed site DOM media. Work is bounded and pauses in hidden tabs, but pages with many rapidly changing media nodes may use more CPU and memory. Leave it off if you only need localhost links inside Lite.</small></div>
      ${settingRow('fiHostSyncSettings', 'Apply Host settings live', 'Accept only the safe bridge/account-switch allowlist. Tokens, webhooks and resolver headers never synchronize.')}
      <div class="fi-l-update" data-ready="0"><b>Encrypted Tensor credential vault (explicit opt-in)</b><br><small>Account tokens are sent only when you enable the backup below. Optional Tensor cookies are sent at most once per day, may omit HttpOnly cookies that this userscript cannot read, and increase credential exposure if this Windows account is compromised. FI Host protects stored values with the desktop secret protector and never includes raw values in lists, logs, command history, or diagnostics.</small></div>
      ${settingRow('tensorCredentialVaultSyncEnabled', 'Back up Tensor accounts to FI Host', 'Send saved Lite Tensor account tokens and bounded profile/analytics metadata to the encrypted local FI Host vault.')}
      ${settingRow('tensorCookieVaultSyncEnabled', 'Back up readable Tensor cookies daily', 'Requires encrypted account backup. Sends only Tensor/TensorHub cookies available to Lite, at most once per day, for advanced FI Lab requests.')}
      <div class="fi-l-toolbar"><button class="fi-l-btn" data-action="host-test">Test FI Host</button><button class="fi-l-btn" data-action="host-refresh-items" ${fiBridgeOwnsSharedRoutes() ? '' : 'disabled'}>Check shared Items</button></div>
      <div class="fi-l-section">FI Bridge (Lite ↔ Pro)</div>
      <div class="fi-l-update"><b>One request owner, bounded peer data</b><br><small>Bridge is opt-in. It shares sanitized task/item snapshots on this Tensor origin; it never exposes raw IndexedDB handles, bot tokens, webhooks, authentication headers, or signed credentials. Pro wrappers installed earlier may remain in the call chain, but they pass shared routes through whenever the network owner below is Lite.</small><div class="fi-l-runtime" style="margin-top:8px"><span><b>${bridgeStatus.enabled ? 'ON' : 'OFF'}</b>bridge</span><span><b>${escapeHtml(bridgeStatus.resolvedPrimary)}</b>primary</span><span><b>${escapeHtml(bridgeStatus.networkOwner || 'none')}</b>network</span><span><b>${bridgeStatus.peers.pro ? 'yes' : 'no'}</b>Pro seen</span></div></div>
      ${bridgeOwnershipMismatch ? `<div class="fi-l-update" data-ready="1"><b>Ownership reload required</b><br><small>${escapeHtml(bridgeStatus.resolvedPrimary)} is selected, but ${escapeHtml(bridgeActualOwner)} owns this loaded page. Until reload, shared task/query, mget, Library, cache, and resolver work cannot safely move between scripts.</small><div class="fi-l-toolbar"><button class="fi-l-btn" data-action="reload-page">Apply ownership and reload Tensor</button></div></div>` : ''}
      ${settingRow('fiBridgeEnabled', 'Enable FI Bridge', 'Enable primary/secondary election and sanitized cross-script snapshot reads.')}
      ${settingRow('fiBridgePrimary', 'Shared Tensor request owner', 'Auto selects Lite for task, Item, Library and resolver endpoints. Pro keeps its UI and non-overlapping features. Reload Tensor after changing ownership.', 'select', { options: [['auto','Auto (Lite owns shared routes)'],['pro','Pro'],['lite','Lite']] })}
      ${settingRow('fiBridgeSyncItems', 'Share tasks and items', 'Import peer generation records into the secondary local view.')}
      ${settingRow('fiBridgeSyncSettings', 'Share safe settings', 'Only explicitly allowlisted non-secret compatible settings may cross the bridge.')}
      ${settingRow('fiBridgeAutoSyncOnLoad', 'Sync from primary on load', 'Read the selected primary after normal Lite startup and account detection.')}
      <div class="fi-l-toolbar"><button class="fi-l-btn" data-action="bridge-inspect">Inspect Pro snapshot</button><button class="fi-l-btn" data-action="bridge-sync">Sync from Pro now</button></div>
      <div class="fi-l-section">Tensor account switcher</div>
      ${settingRow('accountSwitcherEnabled', 'Enable Lite account switching', 'Uses the freeBypassUserAccounts Tensor-origin store. Tokens remain browser-only unless encrypted FI Host backup is explicitly enabled above.')}
      ${state.settings.accountSwitcherEnabled ? `<div class="fi-l-update"><b>${accounts.length} saved Tensor account(s)</b><div class="fi-l-toolbar" style="margin-top:8px"><button class="fi-l-btn" data-action="account-add">Add token</button>${accounts.map(account => `<button class="fi-l-btn" data-action="account-switch" data-account-index="${account.index}" ${account.active ? 'disabled' : ''}>${escapeHtml(account.active ? `✓ ${account.nickname}` : account.nickname)}</button>`).join('')}</div></div>` : ''}
      <div class="fi-l-section">Library Link Assign</div>
      ${settingRow('libraryLinkAssign', 'Intercept Tensor Library', 'Link entry/create to generationImageId, refresh entry/list and unlink entry/delete.')}
      ${settingRow('preferLibraryUrls', 'Prefer Library URLs', 'Use a linked Library signed URL before a temporary task download URL.')}
      ${settingRow('libraryAssignToTaskStore', 'Assign Library URL to task store', 'Project the association into matching cached task items while preserving their original URL for unlink.')}
      ${settingRow('librarySkipDownloadRefresh', 'Skip download refresh when Library is ready', 'Do not call image/video download endpoints when a usable linked Library URL exists.')}
      ${settingRow('libraryRefreshFromList', 'Refresh links from Library list', 'Update known associations when entry/list returns newer signed or thumbnail URLs.')}
      ${settingRow('libraryUseThumbnailFallback', 'Allow Library thumbnail fallback', 'Use thumbnailUrl only when the Library signedUrl is missing or unusable.')}
      <div class="fi-l-section">Items display</div>
      ${settingRow('itemsLayout', 'Items presentation', 'Choose the compact card grid or detailed list.', 'select', { options: [['grid','Grid'],['list','List']] })}
      ${settingRow('cardThumbnails', 'Card thumbnails', 'Show lazy-loaded image previews and video frames on every resolvable Lite Item card. Enabling this also resolves missing visible Item URLs.')}
      <div class="fi-l-update"><b>Thumbnail performance warning</b><br><small>Image thumbnails and video metadata create extra media requests, decoding work, memory use, and potentially larger FI Host/Tensor traffic. Keep this disabled for the lightest Items view.</small></div>
      <div class="fi-l-section">Limits</div>
      ${settingRow('cacheDays', 'Cache age (days)', 'Upper lifetime for records without signed expiry.', 'number', { min: 1, max: 90 })}
      ${settingRow('maxResolvePerResponse', 'Resolve limit per response', 'Caps endpoint work when a query contains many missing media items.', 'number', { min: 1, max: 200 })}
      ${settingRow('maxStoredItems', 'Stored items', 'IndexedDB and in-memory item ceiling.', 'number', { min: 50, max: 4000 })}
      ${settingRow('maxStoredLibraryLinks', 'Stored Library links', 'Dedicated, task-cleanup-immune Library association ceiling.', 'number', { min: 50, max: 5000 })}
      ${settingRow('maxVisibleItems', 'Visible items', 'Maximum cards rendered in the Lite window.', 'number', { min: 20, max: 800 })}
      ${settingRow('onLoadResolveLimit', 'On-load resolve limit', 'Maximum active cached items refreshed at startup.', 'number', { min: 0, max: 1000 })}
      <div class="fi-l-section">Automatic task delivery</div>
      <div class="fi-l-update"><b>Private and opt-in</b><br><small>Channels are disabled by default. Enabling a configured channel authorizes automatic sends without a confirmation dialog. Tokens, chat IDs and webhook URLs are never written to console traces or diagnostic exports.</small></div>
      ${settingRow('deliverySuccessEnabled', 'Deliver completed tasks', 'Send once when a task first enters a successful terminal state.')}
      ${settingRow('deliveryFailureEnabled', 'Deliver failed tasks', 'Send once when a task first enters a failed or cancelled terminal state.')}
      ${settingRow('deliveryIncludeMedia', 'Attach resolved media', 'Resolve and include the first image/video URL when available.')}
      ${settingRow('deliveryIncludeCaption', 'Include task caption', 'Disable for media-only Telegram/Discord sends when media is available.')}
      ${settingRow('deliveryMaxCaption', 'Caption length', 'Bound title, cost, status, time and prompt details.', 'number', { min: 100, max: 1800 })}
      ${settingRow('telegramDeliveryEnabled', 'Enable Telegram delivery', 'Requires a bot token and chat ID below; no per-send confirmation.')}
      ${textSettingRow('telegramBotToken', 'Telegram bot token', 'Stored locally in Lite settings and always redacted from diagnostics.', { secret: true, placeholder: '123456:bot-token' })}
      ${textSettingRow('telegramChatId', 'Telegram chat ID', 'Private chat, group, or channel identifier.', { secret: true, placeholder: '-100…' })}
      ${textSettingRow('telegramApiBase', 'Telegram API base URL', 'Locked to the official api.telegram.org host so imported settings cannot redirect your bot token.', { placeholder: 'https://api.telegram.org' })}
      <div class="fi-l-update" data-telegram-access="${escapeHtml(state.telegramAccessStatus?.phase || 'idle')}"><b>Automatic Telegram chat setup</b><br><small>${escapeHtml(state.telegramAccessStatus?.message || 'Enter a bot token, click Initialize, then send /access to that bot.')}</small><div class="fi-l-toolbar" style="margin-top:8px"><button class="fi-l-btn" data-action="telegram-access-init">${['starting','waiting'].includes(state.telegramAccessStatus?.phase) ? 'Cancel /access wait' : 'Initialize with /access'}</button></div></div>
      ${settingRow('discordDeliveryEnabled', 'Enable Discord delivery', 'Requires a valid Discord webhook URL; no per-send confirmation.')}
      ${textSettingRow('discordWebhookUrl', 'Discord webhook URL', 'Accepted official Discord webhook hosts only; always redacted from diagnostics.', { secret: true, placeholder: 'https://discord.com/api/webhooks/…' })}
      <div class="fi-l-section">Updates and diagnostics</div>
      ${settingRow('remoteUpdateEnabled', 'Lite update checks', 'Read only the dedicated Lite release channel from syncore main.json after page load.')}
      ${settingRow('remoteAnnouncementsEnabled', 'Lite announcements', 'Receive only published Lite-scoped announcements. Pro/global announcements are ignored unless explicitly targeted to Lite.')}
      ${settingRow('remoteAnnouncementNoticesEnabled', 'Announcement pop-up notice', 'Show one small notice for each unread Lite announcement. Disable this to keep news available only in the News tab.')}
      ${settingRow('remoteConfigDelayMs', 'Update delay (ms)', 'Delay remote work so Tensor boot stays light.', 'number', { min: 0, max: 120000, step: 500 })}
      ${settingRow('debugLogs', 'Debug logs', 'Log Lite interception details without printing tokens.')}
      ${settingRow('diagnosticsEnabled', 'Bounded diagnostics', 'Keep redacted resolver, interceptor, IndexedDB, config, Library and delivery traces in memory.')}
      ${settingRow('diagnosticsConsole', 'Console diagnostics', 'Show warnings/errors in DevTools; credentials and signed URL queries are redacted.')}
      ${settingRow('diagnosticsMaxEntries', 'Diagnostic entry limit', 'Old entries are discarded immediately to keep Lite bounded.', 'number', { min: 25, max: 500 })}
      <label class="fi-l-setting"><span><b>Resolver request headers (JSON)</b><small>Defaults mirror the Pro POST contract, including package sign/timestamp. Authorization is never stored here.</small></span><textarea data-setting="requestHeaders">${escapeHtml(JSON.stringify(state.settings.requestHeaders, null, 2))}</textarea></label>
      <div class="fi-l-toolbar"><button class="fi-l-btn" data-action="check-update">Check update now</button>${update?.available && update?.downloadUrl ? '<button class="fi-l-btn" data-action="open-update">Open update</button>' : ''}<button class="fi-l-btn" data-action="clear-cache">Clear Lite cache</button></div>
      <div class="fi-l-update" style="margin-top:9px"><b>Runtime</b><div class="fi-l-runtime"><span><b>${state.stats.queries}</b>queries</span><span><b>${state.stats.mgetResponses}</b>mget</span><span><b>${state.stats.libraryResponses}</b>library</span><span><b>${state.stats.patchedItems}</b>patched</span><span><b>${state.stats.resolvedUrls}</b>URLs</span><span><b>${state.stats.download405Fallbacks}</b>405 fallbacks</span><span><b>${state.stats.gmDownloadRequests}</b>GM resolves</span><span><b>${state.stats.libraryTaskAssignments}</b>task links</span><span><b>${state.stats.deliverySent}</b>delivered</span><span><b>${state.stats.deliveryFailures}</b>delivery errors</span><span><b>${state.stats.diagnosticErrors}</b>errors</span><span><b>${state.stats.failures}</b>failures</span></div></div>
    `;
  }

  function onItemsControlInput(event) {
    const search = event.target?.closest?.('[data-item-search]');
    if (search) {
      state.itemSearch = search.value || '';
      clearTimeout(state.ui?.searchTimer);
      if (state.ui) state.ui.searchTimer = setTimeout(() => renderItems(), 160);
      return;
    }
    const filter = event.target?.closest?.('[data-item-filter]');
    if (filter) {
      state.itemFilter = filter.value || 'all';
      state.visibleCount = 40;
      renderItems();
    }
  }

  function onSettingChange(event) {
    const input = event.target?.closest?.('[data-setting]');
    if (!input) return;
    const key = input.dataset.setting;
    if (!(key in DEFAULT_SETTINGS)) return;
    if (input.type === 'checkbox') state.settings[key] = !!input.checked;
    else if (key === 'requestHeaders') {
      try {
        state.settings.requestHeaders = JSON.parse(input.value || '{}');
        input.style.borderColor = '#334155';
      } catch {
        input.style.borderColor = '#fb7185';
        return;
      }
    } else if (['telegramBotToken', 'telegramChatId', 'telegramApiBase', 'discordWebhookUrl', 'fiHostPairing'].includes(key)) {
      state.settings[key] = String(input.value || '').trim();
    } else if (input.tagName === 'SELECT') state.settings[key] = input.value;
    else state.settings[key] = Number(input.value);
    if (key === 'fiBridgeEnabled' || key === 'fiBridgePrimary') {
      fiBridgeWriteBootPreference(state.settings.fiBridgeEnabled, state.settings.fiBridgePrimary);
      const reclaimedByLite = fiBridgeReconcileNetworkOwner('settings-change');
      diagnostic('info', 'bridge', reclaimedByLite ? 'Bridge preference changed; Lite claimed shared routes live' : 'Bridge boot preference changed; reload required for interceptor ownership', { enabled: state.settings.fiBridgeEnabled, primary: state.settings.fiBridgePrimary });
      if (!fiBridgeOwnsSharedRoutes()) {
        state.host.pending.clear();
        clearTimeout(state.host.flushTimer);
        state.host.flushTimer = 0;
      }
      fiHostSyncSiteMediaRuntime({ restore: !fiBridgeOwnsSharedRoutes() });
      emitItemsChanged('bridge-ownership-change');
    }
    if (['fiHostEnabled', 'fiHostPairing'].includes(key)) {
      state.host.connected = false;
      state.host.inventory.clear();
      fiHostStartPolling();
    }
    if (['fiHostUseLocalUrls', 'fiHostRewriteSiteMedia'].includes(key)) fiHostRebuildSiteMediaIndex();
    if (key === 'tensorCredentialVaultSyncEnabled' && !state.settings.tensorCredentialVaultSyncEnabled) state.settings.tensorCookieVaultSyncEnabled = false;
    // Persist and sanitize before starting async side effects. In particular,
    // thumbnail resolution can rerender the UI while this input is detached.
    saveSettings();
    if (key === 'resolveMissingUrls' && state.settings.resolveMissingUrls) scheduleAutomaticStoredResolution('setting-enabled');
    if (key === 'cardThumbnails') {
      emitItemsChanged('card-thumbnails-setting');
      if (state.settings.cardThumbnails) {
        resolveStoredItemsOnLoad({ manual: true, limit: state.settings.maxVisibleItems, reason: 'card-thumbnails-enabled' })
          .catch(error => traceError('preview', 'Card thumbnail URL resolution failed', error));
      }
    }
    if (['tensorCredentialVaultSyncEnabled', 'tensorCookieVaultSyncEnabled'].includes(key) && state.settings.tensorCredentialVaultSyncEnabled && state.host.connected) {
      fiHostSyncTensorVault({ force:true, forceCookies:state.settings.tensorCookieVaultSyncEnabled === true })
        .catch(error => traceError('host', 'Encrypted Tensor account sync failed', error));
    }
    if (key === 'remoteAnnouncementsEnabled' || key === 'remoteAnnouncementNoticesEnabled') {
      applyRemoteContentState(state.config);
      if (!state.settings.remoteAnnouncementsEnabled || !state.settings.remoteAnnouncementNoticesEnabled) dismissAnnouncementToast();
      updateFabBadge();
      updateAnnouncementBadge();
      if (state.settings.remoteAnnouncementsEnabled && state.settings.remoteAnnouncementNoticesEnabled) showLatestLiteAnnouncementNotice();
    }
  }

  function itemForAction(id) {
    const item = state.items.get(String(id || ''));
    return { item, url: item ? candidateUrl(item, 0) : '' };
  }

  function openExternal(url) {
    if (!url) return;
    try {
      if (typeof GM_openInTab === 'function') return GM_openInTab(url, { active: true, insert: true, setParent: true });
    } catch {}
    try {
      if (typeof GM !== 'undefined' && typeof GM.openInTab === 'function') {
        return GM.openInTab(url, { active: true, insert: true, setParent: true });
      }
    } catch {}
    try { return PAGE.open(url, '_blank', 'noopener'); } catch {}
  }

  function reloadTensorPage() {
    fiHostRestoreSiteMedia();
    try {
      const target = PAGE.location || location;
      if (typeof target?.reload === 'function') {
        target.reload();
        return true;
      }
    } catch {}
    try { location.href = location.href; return true; } catch { return false; }
  }

  function downloadUrl(url, item) {
    if (!url) return;
    const rawName = item?.downloadFileName || `FI-${item?.id || item?.imageId || 'media'}`;
    const fileName = String(rawName).replace(/[\\/:*?"<>|]+/g, '_').slice(0, 180) || 'FI-media';
    const fallback = () => openExternal(url);
    try {
      if (typeof GM_download === 'function') {
        GM_download({ url, name: fileName, saveAs: false, onerror: fallback, ontimeout: fallback });
        return;
      }
      if (typeof GM !== 'undefined' && typeof GM.download === 'function') {
        Promise.resolve(GM.download({ url, name: fileName, saveAs: false })).catch(fallback);
        return;
      }
    } catch {}
    const anchor = document.createElement('a');
    anchor.href = url;
    anchor.download = fileName;
    anchor.rel = 'noopener noreferrer';
    anchor.style.display = 'none';
    document.body.appendChild(anchor);
    anchor.click();
    anchor.remove();
  }

  function clearLiteCache() {
    fiHostRestoreSiteMedia();
    fiHostSiteMediaRuntime.exact.clear();
    fiHostSiteMediaRuntime.identities.clear();
    state.tasks.clear();
    state.items.clear();
    state.downloads.clear();
    state.libraryLinks.clear();
    state.libraryEntries.clear();
    Promise.all([database.clear('tasks'), database.clear('items'), database.clear('downloads'), database.clear('library')]).then(() => emitItemsChanged('clear'));
  }

  const lifecycle = {
    onCreate() {
      // The bridge election must see the document-start preference before any
      // async IndexedDB hydration or Pro marker can make the Items UI appear
      // owned while its fetch/XHR capture is still inactive.
      fiBridgeApplyBootPreference();
      database.open().catch(() => {});
      document.addEventListener('error', event => fiHostHandleLocalMediaError(event), true);
      const bridge = fiBridgeConfig();
      if (bridge.enabled && bridge.primary === 'auto') fiBridgeScheduleAutoElection();
      else fiBridgeActivateNetworkOwner();
      try {
        const registerMenu = typeof GM_registerMenuCommand === 'function'
          ? GM_registerMenuCommand
          : (typeof GM !== 'undefined' && typeof GM.registerMenuCommand === 'function'
            ? GM.registerMenuCommand.bind(GM)
            : null);
        if (registerMenu) {
          registerMenu('Open FI-Bypass Lite', () => { createUi(); setPanelOpen(true); });
          registerMenu('Check FI-Bypass Lite update', () => checkRemoteConfig(true));
        }
      } catch {}
      document.addEventListener('visibilitychange', () => {
        if (!document.hidden && state.settings.fiHostEnabled) {
          if (fiHostBridgeReady && fiHostBridgeSocket?.readyState === 1) fiHostBridgeSocket.send(JSON.stringify({ type:'userscript-heartbeat', at:Date.now(), page:String(location.href || '').slice(0,500), stored:state.host.stored, failed:state.host.failed }));
          else fiHostRefresh().catch(() => {});
        }
        if (!document.hidden) showLatestLiteAnnouncementNotice();
      });
      PAGE.addEventListener('pagehide', () => fiHostStopWebSocket('page closed'), { once:true });
      exposeApi();
    },

    onLoad() {
      if (!state.ui) createUi();
      if (state.loadRan) return;
      if (document.readyState !== 'complete') {
        if (!state.loadWaitInstalled) {
          state.loadWaitInstalled = true;
          PAGE.addEventListener('load', lifecycle.onLoad, { once: true });
        }
        return;
      }
      state.loadRan = true;
      database.open().then(async () => {
        await getToken().catch(() => '');
        fiHostStartPolling();
        await cleanupExpiredTasksOnLoad().catch(error => traceError('idb', 'Expired task cleanup failed', error));
        await resolveStoredItemsOnLoad().catch(error => traceError('resolver', 'On-load URL refresh failed', error));
        if (state.settings.cardThumbnails) {
          await resolveStoredItemsOnLoad({ manual: true, limit: state.settings.maxVisibleItems, reason: 'card-thumbnails-onload' })
            .catch(error => traceError('preview', 'Card thumbnail URL resolution failed on load', error));
        }
        await fiBridgeAutoSyncFromPeer();
        if (state.settings.remoteUpdateEnabled || state.settings.remoteAnnouncementsEnabled) {
          clearTimeout(state.remoteTimer);
          state.remoteTimer = setTimeout(() => checkRemoteConfig(false).catch(error => traceError('config', 'Deferred update check failed', error)), state.settings.remoteConfigDelayMs);
        }
      });
    },

    async onClick(event) {
      const target = event.target?.closest?.('button,[data-action],[data-tab]');
      if (!target) return;
      if (target === state.ui?.fab) {
        setPanelOpen(state.ui.panel.dataset.open !== '1');
        return;
      }
      if (target.dataset.tab) {
        state.activeTab = target.dataset.tab;
        renderActiveTab();
        return;
      }
      const action = target.dataset.action;
      if (action === 'close') setPanelOpen(false);
      else if (action === 'close-preview') closePreview();
      else if (action === 'open-errors') {
        state.activeTab = 'errors';
        setPanelOpen(true);
        renderActiveTab();
      }
      else if (action === 'copy-errors') await copyDiagnostics();
      else if (action === 'export-errors') downloadDiagnostics();
      else if (action === 'clear-errors') clearDiagnostics();
      else if (action === 'announcement-dismiss') dismissAnnouncementToast({ markRead: true });
      else if (action === 'announcement-view') {
        if (target.dataset.announcementId) markLiteAnnouncementsRead(target.dataset.announcementId);
        dismissAnnouncementToast();
        createUi();
        state.activeTab = 'announcements';
        setPanelOpen(true);
      } else if (action === 'announcement-open-link') {
        const row = state.announcements.find(entry => entry.id === target.dataset.announcementId);
        if (row?.url) openExternal(row.url);
      }
      else if (action === 'preview-open' || action === 'preview-copy' || action === 'preview-download') {
        const id = state.ui?.preview?.dataset.itemId || '';
        const { item, url } = itemForAction(id);
        if (action === 'preview-open') openExternal(url);
        else if (action === 'preview-download') downloadUrl(url, item);
        else if (url) {
          try { await navigator.clipboard.writeText(url); }
          catch { diagnostic('warn', 'preview', 'Clipboard access was denied for the preview URL'); }
        }
      }
      else if (action === 'refresh') renderActiveTab();
      else if (action === 'reload-page') reloadTensorPage();
      else if (action === 'preview-item' && target.dataset.itemId) openPreview(target.dataset.itemId, target);
      else if (action === 'more') { state.visibleCount += 40; renderItems(); }
      else if (action === 'set-layout') {
        state.settings.itemsLayout = target.dataset.layout === 'list' ? 'list' : 'grid';
        saveSettings();
        renderItems();
      } else if (action === 'resolve-all') {
        target.disabled = true;
        let resolveError = null;
        const resolvedCount = await resolveStoredItemsOnLoad({ manual: true, reason: 'manual-resolve-all' }).catch(error => {
          resolveError = error;
          traceError('resolver', 'Manual resolve-all failed', error);
          return 0;
        });
        target.disabled = false;
        renderItems();
        if (!resolvedCount) PAGE.alert(`${SCRIPT_NAME}: ${resolveError?.message || 'No missing Item URL could be resolved. Check the elected Bridge owner and Tensor account.'}`);
      } else if (action === 'cleanup-expired') {
        target.disabled = true;
        await cleanupExpiredTasksOnLoad(true).catch(error => { traceError('idb', 'Manual expired-task cleanup failed', error); return { tasks: 0, items: 0 }; });
        target.disabled = false;
        renderItems();
      }
      else if (action === 'check-update') {
        target.disabled = true;
        await checkRemoteConfig(true).catch(error => traceError('config', 'Manual update check failed', error));
        target.disabled = false;
      } else if (action === 'bridge-inspect') {
        target.disabled = true;
        try {
          const snapshot = await fiBridgeReadProSnapshot();
          PAGE.alert(`${SCRIPT_NAME} FI Bridge\n\nPro snapshot: ${snapshot.counts.tasks} task(s), ${snapshot.counts.items} item(s).\nOnly sanitized, bounded data was read.`);
        } catch (error) {
          traceError('bridge', 'Manual Pro snapshot read failed', error);
          PAGE.alert(`${SCRIPT_NAME}: ${error?.message || error}`);
        } finally { target.disabled = false; }
      } else if (action === 'bridge-sync') {
        target.disabled = true;
        try {
          const result = await fiBridgeSyncFromPro({ force: true });
          PAGE.alert(`${SCRIPT_NAME} FI Bridge imported ${result.importedTasks} task(s) and ${result.importedItems} item(s).`);
        } catch (error) {
          traceError('bridge', 'Manual Pro bridge sync failed', error);
          PAGE.alert(`${SCRIPT_NAME}: ${error?.message || error}`);
        } finally {
          target.disabled = false;
          if (state.activeTab === 'settings') renderSettings();
        }
      } else if (action === 'host-test') {
        target.disabled = true;
        const config = await fiHostRefresh({ manual: true });
        target.disabled = false;
        PAGE.alert(config?.enabled ? `${SCRIPT_NAME}: FI Host is connected. Shared Items and automatic media storage are ready.` : `${SCRIPT_NAME}: ${state.host.error || 'FI Host did not enable this client.'}`);
        renderSettings();
      } else if (action === 'host-refresh-items') {
        target.disabled = true;
        const items = [...state.items.values()].filter(isEntryForCurrentAccount).slice(0, 120);
        await Promise.all(items.map(item => fiHostLookupItem(itemId(item), { refresh: true }).catch(() => null)));
        target.disabled = false;
        renderSettings();
      } else if (action === 'account-add') {
        addLiteAccount();
      } else if (action === 'account-switch') {
        switchLiteAccount(target.dataset.accountIndex);
      } else if (action === 'telegram-access-init') {
        await initializeTelegramAccess();
      } else if (action === 'open-update' && state.update?.downloadUrl) openExternal(state.update.downloadUrl);
      else if (action === 'clear-cache') {
        if (PAGE.confirm(`${SCRIPT_NAME}: clear cached tasks, items and signed URLs?`)) clearLiteCache();
      } else if (target.dataset.itemId) {
        const { item, url } = itemForAction(target.dataset.itemId);
        if (action === 'open' && url) openExternal(url);
        else if (action === 'copy' && url) {
          try { await navigator.clipboard.writeText(url); }
          catch {
            const textarea = document.createElement('textarea');
            textarea.value = url;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            textarea.remove();
          }
        } else if (action === 'download') downloadUrl(url, item);
        else if (action === 'resolve-item') {
          target.disabled = true;
          let resolveError = null;
          const resolvedUrl = await resolveOne(target.dataset.itemId, item?.mimeType || '', { force: true, reason: 'manual-item' }).catch(error => {
            resolveError = error;
            traceError('resolver', 'Single-item resolve failed', error, { itemId: target.dataset.itemId });
            return null;
          });
          target.disabled = false;
          renderItems();
          if (!resolvedUrl) PAGE.alert(`${SCRIPT_NAME}: ${resolveError?.message || 'This Item URL could not be resolved by the elected owner.'}`);
        }
        else if (action === 'remove-item') {
          const id = String(target.dataset.itemId);
          state.items.delete(id);
          database.remove('items', id);
          removeDownloadsForItem(id);
          renderItems();
        }
      }
    }
  };

  function emitItemsChanged(reason) {
    try {
      const EventCtor = PAGE.CustomEvent || CustomEvent;
      PAGE.dispatchEvent(new EventCtor('fi-bypass-lite-items-changed', {
        detail: { reason, items: state.items.size, urls: state.downloads.size }
      }));
    } catch {}
    if (state.ui?.panel?.dataset.open === '1' && state.activeTab === 'items') renderItems();
  }

  async function resolveOne(id, mimeType = '', options = {}) {
    if (!isTensorDownloadableId(id)) return null;
    const cleanId = String(id).trim();
    const item = state.items.get(cleanId);
    if (options.force !== true) {
      const projected = item ? candidateUrl(item, 0) : '';
      if (projected) return projected;
      const cached = cachedDownload(cleanId, mimeType);
      if (cached) return cached;
    }
    const resolved = await resolveCandidateUrls([{ id: cleanId, mimeType }], { reason: String(options.reason || 'single-item'), force: options.force === true });
    const url = resolved.get(cleanId) || '';
    if (url && item) cacheDownload(cleanId, url, mimeType || item.mimeType || '', mediaKind(mimeType || item.mimeType || ''));
    return url || null;
  }

  function publicSettingsSnapshot() {
    const settings = clone(state.settings);
    ['telegramBotToken', 'telegramChatId', 'discordWebhookUrl', 'fiHostPairing'].forEach(key => {
      settings[key] = settings[key] ? '[stored]' : '';
    });
    return settings;
  }

  function exposeApi() {
    const bridgeApi = Object.freeze({
      apiVersion: '1.0',
      status: fiBridgeStatus,
      readPeer: (options = {}) => fiBridgeReadProSnapshot(options),
      syncFromPeer: (options = {}) => fiBridgeSyncFromPro(options),
      getPeerItems: async (limit = 500) => clone((await fiBridgeReadProSnapshot({ limit })).items),
      getPeerTasks: async (limit = 500) => clone((await fiBridgeReadProSnapshot({ limit })).tasks),
      getPeerSettings: async () => clone((await fiBridgeReadProSnapshot({ limit: 1 })).settings),
      setEnabled(enabled, primary = state.settings.fiBridgePrimary) {
        state.settings.fiBridgeEnabled = !!enabled;
        state.settings.fiBridgePrimary = ['auto','pro','lite'].includes(String(primary || '').toLowerCase()) ? String(primary).toLowerCase() : 'auto';
        fiBridgeWriteBootPreference(state.settings.fiBridgeEnabled, state.settings.fiBridgePrimary);
        saveSettings();
        fiBridgeReconcileNetworkOwner('public-bridge-enabled');
        fiHostRebuildSiteMediaIndex();
        emitItemsChanged('bridge-ownership-change');
        return fiBridgeStatus();
      },
      setPrimary(primary) {
        const normalized = String(primary || 'auto').toLowerCase();
        if (!['auto','pro','lite'].includes(normalized)) throw new Error('FI Bridge primary must be auto, pro, or lite.');
        state.settings.fiBridgePrimary = normalized;
        fiBridgeWriteBootPreference(state.settings.fiBridgeEnabled, normalized);
        saveSettings();
        fiBridgeReconcileNetworkOwner('public-bridge-primary');
        fiHostRebuildSiteMediaIndex();
        emitItemsChanged('bridge-ownership-change');
        return fiBridgeStatus();
      }
    });
    const api = Object.freeze({
      version: SCRIPT_VERSION,
      endpoints: Object.freeze({ queryPath: TASK_QUERY_PATH, mgetPath: MGET_TASK_PATH, taskPath: DIRECT_TASK_PATH, tasksPath: TASKS_PATH, libraryPrefix: LIBRARY_ENTRY_PREFIX, imageDownload: API_URL_IMAGE, videoDownload: API_URL_VIDEO, config: CONFIG_URL }),
      open() { createUi(); setPanelOpen(true); },
      close() { setPanelOpen(false); },
      getItems() { return clone([...state.items.values()].filter(item => isEntryForCurrentAccount(item) && (isFreshCacheEntry(item) || libraryEntryForImage(itemId(item))))); },
      getTasks() { return clone([...state.tasks.values()].filter(task => isEntryForCurrentAccount(task))); },
      getLibraryLinks() { return clone([...state.libraryLinks.values()].filter(link => isEntryForCurrentAccount(link))); },
      getSettings() { return publicSettingsSnapshot(); },
      setSetting(key, value) {
        if (!(key in DEFAULT_SETTINGS)) throw new Error(`Unknown Lite setting: ${key}`);
        state.settings[key] = value;
        if (key === 'fiBridgeEnabled' || key === 'fiBridgePrimary') fiBridgeWriteBootPreference(state.settings.fiBridgeEnabled, state.settings.fiBridgePrimary);
        saveSettings();
        if (key === 'fiBridgeEnabled' || key === 'fiBridgePrimary') fiBridgeReconcileNetworkOwner('public-setting-change');
        if (key === 'fiHostEnabled' || key === 'fiHostPairing') fiHostStartPolling();
        if (['fiHostUseLocalUrls', 'fiHostRewriteSiteMedia', 'fiBridgeEnabled', 'fiBridgePrimary'].includes(key)) {
          fiHostRebuildSiteMediaIndex();
          emitItemsChanged('projection-setting-change');
        }
        if (key === 'resolveMissingUrls' && state.settings.resolveMissingUrls) scheduleAutomaticStoredResolution('public-setting-enabled');
        if (key === 'cardThumbnails') {
          emitItemsChanged('public-card-thumbnails-setting');
          if (state.settings.cardThumbnails) {
            resolveStoredItemsOnLoad({ manual: true, limit: state.settings.maxVisibleItems, reason: 'public-card-thumbnails-enabled' })
              .catch(error => traceError('preview', 'Card thumbnail URL resolution failed', error));
          }
        }
        return ['telegramBotToken', 'telegramChatId', 'discordWebhookUrl', 'fiHostPairing'].includes(key)
          ? (state.settings[key] ? '[stored]' : '')
          : clone(state.settings[key]);
      },
      resolve: resolveOne,
      refresh: () => resolveStoredItemsOnLoad({ manual: true, reason: 'public-refresh' }),
      cleanupExpired: () => cleanupExpiredTasksOnLoad(true),
      checkUpdate: () => checkRemoteConfig(true),
      getAnnouncements() {
        const unread = new Set(unreadLiteAnnouncements().map(row => row.id));
        return clone(state.announcements.map(row => ({ ...row, unread: unread.has(row.id) })));
      },
      markAnnouncementsRead(ids = state.announcements.map(row => row.id)) {
        markLiteAnnouncementsRead(ids);
        return unreadLiteAnnouncements().length;
      },
      getDiagnostics() { return clone(state.diagnostics); },
      exportDiagnostics: diagnosticsExportText,
      clearDiagnostics,
      preview(id) { createUi(); return openPreview(id); },
      deliverTask(task, outcome = taskTerminalOutcome(task)) {
        if (!outcome) return Promise.resolve([]);
        return deliverTaskTransition(clone(task), outcome);
      },
      bridge: bridgeApi,
      host: Object.freeze({
        status: () => Object.freeze({ connected: state.host.connected, enabled: state.host.enabled, checkedAt: state.host.checkedAt, lastSeenAt: state.host.lastSeenAt, origin: state.host.origin, runtimeInstanceId: state.host.runtimeInstanceId, error: state.host.error, stored: state.host.stored, reused: state.host.reused, failed: state.host.failed }),
        refresh: () => fiHostRefresh({ manual: true }),
        lookupItem: id => fiHostLookupItem(id, { refresh: true }),
        materializeItem: id => {
          const item = state.items.get(String(id || ''));
          if (!item) throw new Error('Lite Item was not found.');
          return fiHostMaterializeItem(item);
        },
        rewriteSiteNow: () => { fiHostRebuildSiteMediaIndex(); return fiHostQueueSiteMediaRoot(document.documentElement || document.body || document); },
        siteMediaStatus: () => Object.freeze({ enabled: fiHostSiteMediaActive(), owner: fiBridgeOwnsSharedRoutes(), indexedUrls: fiHostSiteMediaRuntime.exact.size, rewrittenAttributes: state.stats.siteMediaRewrites })
      }),
      clearCache: clearLiteCache,
      stats: () => ({
        ...state.stats,
        items: [...state.items.values()].filter(item => isEntryForCurrentAccount(item) && (isFreshCacheEntry(item) || libraryEntryForImage(itemId(item)))).length,
        urls: [...state.downloads.values()].filter(item => isEntryForCurrentAccount(item) && isFreshCacheEntry(item)).length,
        tasks: [...state.tasks.values()].filter(item => isEntryForCurrentAccount(item)).length,
        libraryLinks: [...state.libraryLinks.values()].filter(item => isEntryForCurrentAccount(item)).length,
        dbReady: state.dbReady
      })
    });
    try { Object.defineProperty(PAGE, 'FIBypassLite', { value: api, configurable: true }); }
    catch { PAGE.FIBypassLite = api; }
  }

  lifecycle.onCreate();
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', lifecycle.onLoad, { once: true });
  else setTimeout(lifecycle.onLoad, 0);
  if (document.readyState !== 'complete') {
    state.loadWaitInstalled = true;
    PAGE.addEventListener('load', lifecycle.onLoad, { once: true });
  }
})();