Facebook Login Wall Remover

Optimizes the guest browsing experience on Facebook desktop by removing login barriers and enhancing feed navigation, content expansion, and post data export tools.

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

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

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

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

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

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

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

Advertisement:

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

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

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

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

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

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

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

Advertisement:

// ==UserScript==
// @name               Facebook Login Wall Remover
// @name:en            Facebook Login Wall Remover
// @name:zh-TW         Facebook 登入牆移除器
// @name:ja            Facebook ログインウォールリムーバー
// @namespace          https://greasyfork.org/en/users/1467948-stonedkhajiit
// @version            1.0.0
// @author             StonedKhajiit
// @description        Optimizes the guest browsing experience on Facebook desktop by removing login barriers and enhancing feed navigation, content expansion, and post data export tools.
// @description:en     Optimizes the guest browsing experience on Facebook desktop by removing login barriers and enhancing feed navigation, content expansion, and post data export tools.
// @description:zh-TW  最佳化 Facebook 電腦版的訪客瀏覽體驗。移除登入阻擋與 Cookie 提示,並提供貼文導覽、內容自動展開與資料批次匯出工具。
// @description:ja     Facebookデスクトップ版のゲスト閲覧体験を最適化します。ログイン表示やクッキー同意画面の非表示化、投稿ナビゲーション、コンテンツの自動展開、投稿データのバッチエクスポート機能を提供します。
// @license            MIT
// @icon               https://www.google.com/s2/favicons?sz=64&domain=facebook.com
// @match              *://*.facebook.com/*
// @exclude            *://m.facebook.com/*
// @exclude            *://mobile.facebook.com/*
// @require            https://cdn.jsdelivr.net/npm/@zumer/[email protected]/dist/snapdom.js#sha256=5fe8acfa7aeeb3c02d7f850836b3b228de5b9ada6165951b24813987e8e692b3
// @grant              GM_addStyle
// @grant              GM_addValueChangeListener
// @grant              GM_deleteValue
// @grant              GM_getValue
// @grant              GM_listValues
// @grant              GM_openInTab
// @grant              GM_registerMenuCommand
// @grant              GM_removeValueChangeListener
// @grant              GM_setClipboard
// @grant              GM_setValue
// @grant              GM_unregisterMenuCommand
// @grant              GM_xmlhttpRequest
// @grant              unsafeWindow
// @grant              window.close
// @run-at             document-start
// @noframes
// ==/UserScript==

(function() {
	"use strict";
	var s$3 = new Set();
	var _css = async (t) => {
		if (s$3.has(t)) return;
		s$3.add(t);
		((c) => {
			if (typeof GM_addStyle === "function") GM_addStyle(c);
			else (document.head || document.documentElement).appendChild(document.createElement("style")).append(c);
		})(t);
	};
	var __defProp = Object.defineProperty;
	var __exportAll = (all, no_symbols) => {
		let target = {};
		for (var name in all) __defProp(target, name, {
			get: all[name],
			enumerable: true
		});
		if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
		return target;
	};
	_css(":root{--z-index-floating-nav:9990;--z-index-transparency:9990;--z-index-timeline:9995;--z-index-toolbar:9998;--z-index-hover-trigger:9999;--z-index-hover-hint:10000;--z-index-toast:99999;--z-index-modal-backdrop:99998;--z-index-modal-foreground:99999;--z-index-id-badge:99999}div[data-nosnippet]{display:none!important}div[role=banner]:has(a[href*=\"/reg/\"]){display:none!important}.generic_dialog.pop_dialog.generic_dialog_modal:has(input[name=login]){display:none!important}.gm-tools-wrapper{z-index:5;-webkit-backdrop-filter:blur(8px);opacity:0;pointer-events:none;background-color:#ffffffe6;border:1px solid #00000014;border-radius:20px;align-items:center;padding:4px 6px;transition:opacity .2s ease-out,transform .2s ease-out;display:flex;position:absolute;top:12px;right:12px;transform:translateY(-5px);box-shadow:0 4px 12px #0000001a}.gm-tools-wrapper--outer-right{border-radius:20px;flex-direction:column;margin-left:12px;padding:6px 4px;left:100%;right:auto;transform:translate(-5px)}.gm-tools-wrapper--outer-right:before{content:\"\";z-index:-1;pointer-events:auto;background-color:#0000;position:absolute;inset:-40px -20px -40px -40px}.__fb-dark-mode .gm-tools-wrapper{background-color:#242526e6;border-color:#ffffff14;box-shadow:0 4px 12px #0000004d}div[role=article]:hover .gm-tools-wrapper{opacity:1;pointer-events:auto;transform:translateY(0)}div[role=article]:hover .gm-tools-wrapper--outer-right{transform:translate(0)}.gm-tools-wrapper.gm-in-dialog{box-shadow:none;background-color:#0000;border:none;margin-right:16px;padding:0;position:static;opacity:1!important;pointer-events:auto!important;flex-direction:row!important;transform:none!important}.gm-tool-button{--positive-background:#e7f3ff;--negative-background:#fdedee;--hover-overlay:#0000000d;--secondary-text:#65676b;--media-inner-border:#ced0d4;margin-left:8px}.gm-tools-wrapper--outer-right .gm-tool-button{margin-top:8px;margin-left:0!important}.gm-tools-wrapper.gm-in-dialog .gm-tool-button{margin-top:0!important;margin-left:8px!important}@keyframes gm-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gm-spin{transform-origin:50%;animation:.8s linear infinite gm-spin}.gm-icon-wrapper{vertical-align:middle;justify-content:center;align-items:center;display:inline-flex}.gm-icon-wrapper svg{display:block}.gm-transparency-container{z-index:var(--z-index-transparency);flex-direction:column;gap:10px;transition:opacity .3s;display:none;position:fixed;bottom:20px;left:20px}.gm-transparency-container[data-opacity=true]{opacity:.5}.gm-transparency-container[data-opacity=true]:hover{opacity:1}.gm-transparency-btn{cursor:pointer;background-color:#fff;border:1px solid #ddd;border-radius:50%;justify-content:center;align-items:center;width:40px;height:40px;font-size:18px;transition:transform .1s;display:flex;box-shadow:0 2px 5px #00000026}.gm-transparency-btn:hover{background-color:#f0f2f5}.gm-transparency-btn:active{transform:scale(.95)}.gm-post-number{color:#65676b;z-index:1;background-color:#e4e6eb;border-radius:4px;padding:2px 6px;font-size:12px;font-weight:700;position:absolute;top:-10px;left:-10px}.gm-post-highlight{border-radius:8px;z-index:10!important;outline:3px solid #1877f2!important;box-shadow:0 0 15px #1877f280!important}.gm-post-highlight[data-heat=\"1\"]{outline-color:#b2dfdb!important;box-shadow:0 0 15px #b2dfdb80!important}.gm-post-highlight[data-heat=\"2\"]{outline-color:#80cbc4!important;box-shadow:0 0 15px #80cbc480!important}.gm-post-highlight[data-heat=\"3\"]{outline-color:#26a69a!important;box-shadow:0 0 15px #26a69a80!important}.gm-post-highlight[data-heat=\"4\"]{outline-color:#66bb6a!important;box-shadow:0 0 15px #66bb6a80!important}.gm-post-highlight[data-heat=\"5\"]{outline-color:#d4e157!important;box-shadow:0 0 15px #d4e15780!important}.gm-post-highlight[data-heat=\"6\"]{outline-color:#ffee58!important;box-shadow:0 0 15px #ffee5880!important}.gm-post-highlight[data-heat=\"7\"]{outline-color:#ffca28!important;box-shadow:0 0 15px #ffca2880!important}.gm-post-highlight[data-heat=\"8\"]{outline-color:#fb8c00!important;box-shadow:0 0 15px #fb8c0080!important}.gm-post-highlight[data-heat=\"9\"]{outline-color:#f44336!important;box-shadow:0 0 15px #f4433680!important}.gm-floating-nav{z-index:var(--z-index-floating-nav);flex-direction:column;gap:12px;transition:opacity .3s;display:flex;position:fixed;bottom:20px;right:50px}.gm-floating-nav[data-opacity=true]{opacity:.1}.gm-floating-nav[data-opacity=true]:hover{opacity:1}.gm-floating-nav button{-webkit-backdrop-filter:blur(12px);cursor:pointer;color:#65676b;background-color:#ffffffd9;border:none;border-radius:50%;justify-content:center;align-items:center;width:44px;height:44px;transition:all .2s cubic-bezier(.175,.885,.32,1.275);display:flex;position:relative;box-shadow:0 4px 12px #00000026}.gm-floating-nav button:hover{background-color:#fff;transform:scale(1.1);box-shadow:0 6px 16px #0003}.gm-floating-nav button:active{transform:scale(.95)}.gm-floating-nav svg{fill:currentColor;width:22px;height:22px}#gm-timeline-container{z-index:var(--z-index-timeline);-webkit-backdrop-filter:none;width:fit-content;max-width:32px;box-shadow:none;background:0 0;border:1px solid #0000;border-radius:16px 0 0 16px;flex-direction:column;align-items:flex-end;gap:4px;padding:16px 0;transition:max-width .3s cubic-bezier(.25,.46,.45,.94),right .3s cubic-bezier(.25,.46,.45,.94),background-color .2s,box-shadow .2s,-webkit-backdrop-filter .2s,backdrop-filter .2s;display:flex;position:fixed;top:60px;bottom:20px;right:0;overflow:hidden}@supports ((-moz-appearance:none)){#gm-timeline-container{right:var(--scrollbar-width,16px)}}#gm-timeline-container:hover{-webkit-backdrop-filter:blur(12px);background:#fffffff2;border:1px solid #00000014;max-width:260px;box-shadow:0 4px 24px #00000026;right:0!important}.gm-timeline-header{flex-shrink:0;justify-content:flex-end;width:100%;padding-bottom:4px;padding-right:4px;display:flex}.gm-timeline-scroll-area{scrollbar-width:none;overscroll-behavior:contain;flex-direction:column;flex-grow:1;align-items:flex-end;width:100%;padding:4px 0;display:flex;overflow:hidden auto}.gm-timeline-scroll-area::-webkit-scrollbar{display:none}.gm-timeline-row{cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;flex-shrink:0;justify-content:flex-end;align-items:center;width:100%;height:20px;padding-left:16px;padding-right:12px;display:flex}.gm-timeline-info{opacity:0;pointer-events:none;justify-content:flex-end;align-items:center;gap:8px;margin-right:12px;transition:opacity .2s,transform .2s;display:flex;transform:translate(10px)}#gm-timeline-container:hover .gm-timeline-info{opacity:1;transition-delay:50ms;transform:translate(0)}.gm-timeline-sort-btn{cursor:pointer;opacity:.6;-webkit-user-select:none;user-select:none;color:#65676b;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:28px;height:28px;margin-top:4px;margin-bottom:0;font-size:16px;transition:transform .2s;display:flex}.gm-timeline-sort-btn:hover{opacity:1;background-color:#0000000d;transform:scale(1.1)}.gm-label-time{color:#65676b;letter-spacing:.3px;font-size:11px;font-weight:400}.gm-label-idx{color:#90949c;text-align:right;font-variant-numeric:tabular-nums;min-width:28px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:12px;font-weight:400}.gm-label-idx.milestone-text{color:#050505;font-size:12px;font-weight:700}.gm-timeline-dot{background-color:#b0b3b8;border-radius:50%;flex-shrink:0;width:8px;height:8px;transition:transform .2s cubic-bezier(.175,.885,.32,1.275),background-color .2s}.gm-timeline-row:hover .gm-timeline-dot{transform:scale(1.5)}.gm-timeline-row:hover .gm-label-idx{color:#1877f2;font-weight:700}.gm-timeline-row:hover .gm-timeline-info{opacity:1;transform:translate(0)}.gm-timeline-row.active .gm-label-idx{color:#1877f2;font-weight:700}.gm-timeline-dot[data-heat=\"1\"]{background-color:#b2dfdb!important}.gm-timeline-dot[data-heat=\"2\"]{background-color:#80cbc4!important}.gm-timeline-dot[data-heat=\"3\"]{background-color:#26a69a!important}.gm-timeline-dot[data-heat=\"4\"]{background-color:#66bb6a!important}.gm-timeline-dot[data-heat=\"5\"]{background-color:#d4e157!important}.gm-timeline-dot[data-heat=\"6\"]{background-color:#ffee58!important}.gm-timeline-dot[data-heat=\"7\"]{background-color:#ffca28!important}.gm-timeline-dot[data-heat=\"8\"]{background-color:#fb8c00!important}.gm-timeline-dot[data-heat=\"9\"]{box-shadow:0 0 4px #f4433680;background-color:#f44336!important}.gm-timeline-row.active .gm-timeline-dot{border:2px solid #fff;transform:scale(1.4);box-shadow:0 0 0 2px #1877f2,0 2px 6px #0000004d!important}.gm-toolbar{-webkit-backdrop-filter:blur(12px);width:100%;z-index:var(--z-index-toolbar);box-sizing:border-box;background-color:#ffffffd9;border-bottom:1px solid #0000000d;justify-content:space-between;align-items:center;gap:16px;padding:4px 16px;transition:transform .3s ease-in-out;display:flex;position:fixed;top:0;left:0;box-shadow:0 4px 12px #0000000f}.gm-button-group{align-items:center;gap:6px;display:flex}.gm-button-group button{cursor:pointer;color:#65676b;background-color:#0000;border:none;border-radius:50%;justify-content:center;align-items:center;width:30px;height:30px;padding:0;transition:all .2s;display:flex}.gm-button-group button:hover{background-color:#0000000d;transform:translateY(-1px)}.gm-button-group button:active{background-color:#0000001a;transform:scale(.96)}.gm-button-group button svg{fill:#65676b;pointer-events:none;width:18px;height:18px}.gm-button-group button.gm-pinned{background-color:#e7f3ff}.gm-search-core-wrapper{flex-grow:1;justify-content:center;display:flex}.gm-search-component-wrapper{background-color:#f0f2f5;border:1px solid #ced0d4;border-radius:15px;flex-grow:1;align-items:center;max-width:600px;height:30px;padding:0;transition:border-color .2s,box-shadow .2s,background-color .2s;display:flex}.gm-search-component-wrapper.gm-focused{background-color:#fff;border-color:#1877f2;box-shadow:0 0 0 2px #1877f233}.gm-search-component-wrapper>select,.gm-search-input-container>input{background:0 0;border:none;outline:none;height:100%;padding-top:0;padding-bottom:0}.gm-search-component-wrapper>select{color:#65676b;border-right:1px solid #ced0d4;margin-right:8px;padding-left:12px;padding-right:8px;font-weight:500}.gm-search-input-container{flex-grow:1;align-items:center;height:100%;display:flex;position:relative}.gm-search-input-container>input{width:100%;padding-right:70px}.gm-search-clear-button{cursor:pointer;color:#65676b;background:0 0;border:none;justify-content:center;align-items:center;width:18px;height:18px;padding:0;font-size:13px;display:none;position:absolute;top:50%;right:34px;transform:translateY(-50%)}.gm-search-button-integrated{cursor:pointer;background:0 0;border:none;border-radius:0 15px 15px 0;justify-content:center;align-items:center;width:34px;height:100%;padding:0;display:flex;position:absolute;right:0}.gm-search-button-integrated svg{fill:#1877f2;width:16px;height:16px}.gm-hover-hint{width:40px;height:4px;z-index:var(--z-index-hover-hint);opacity:0;pointer-events:none;background-color:#00000040;border-radius:2px;transition:opacity .2s ease-in-out,transform .3s cubic-bezier(.175,.885,.32,1.275);position:fixed;top:0;left:50%;transform:translate(-50%,-12px)}.gm-hover-hint.gm-visible{opacity:1;transform:translate(-50%,8px)}.gm-hover-trigger{width:100%;height:10px;z-index:var(--z-index-hover-trigger);position:fixed;top:0;left:0}.gm-toast{color:#fff;z-index:var(--z-index-toast);opacity:0;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);white-space:pre-wrap;border-radius:8px;padding:12px 20px;font-size:14px;font-weight:700;transition:transform .3s,opacity .3s;position:fixed;top:20px;left:50%;transform:translate(-50%,-100px);box-shadow:0 4px 10px #0003}.gm-toast-visible{opacity:1;transform:translate(-50%)}.gm-toast-success{background-color:#1877f2d9}.gm-toast-failure{background-color:#dc3545d9}.gm-toast-info{background-color:#323232e6}.gm-toast a{color:#fff;font-weight:600;text-decoration:underline;transition:opacity .2s}.gm-toast a:hover{opacity:.8}.gm-settings-backdrop{-webkit-backdrop-filter:blur(4px);z-index:var(--z-index-modal-backdrop);opacity:0;overscroll-behavior:contain;background-color:#0006;transition:opacity .3s;position:fixed;inset:0}.gm-settings-backdrop.open{opacity:1}.gm-settings-modal{z-index:var(--z-index-modal-foreground);opacity:0;overscroll-behavior:contain;background-color:#fff;border-radius:12px;flex-direction:column;min-width:800px;max-width:90vw;height:85vh;max-height:85vh;transition:all .3s cubic-bezier(.34,1.56,.64,1);display:flex;position:fixed;top:50%;left:50%;overflow:hidden;transform:translate(-50%,-50%)scale(.95);box-shadow:0 8px 30px #0000001f}.gm-settings-modal.open{opacity:1;transform:translate(-50%,-50%)scale(1)}.gm-settings-modal.wide{min-width:1050px;height:90vh;max-height:90vh}.gm-settings-content::-webkit-scrollbar{width:8px}.gm-settings-content::-webkit-scrollbar-track{background:0 0}.gm-settings-content::-webkit-scrollbar-thumb{background-color:#ced0d4;border:2px solid #fff;border-radius:4px}.gm-settings-content::-webkit-scrollbar-thumb:hover{background-color:#b0b3b8}.gm-settings-header{border-bottom:1px solid #f0f2f5;flex-shrink:0;justify-content:space-between;align-items:center;padding:6px 16px;display:flex}.gm-settings-title{color:#050505;margin:0;font-size:20px;font-weight:700}.gm-settings-close-btn{color:#65676b;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:36px;height:36px;padding:4px;font-size:24px;transition:background-color .2s;display:flex}.gm-settings-close-btn:hover{color:#050505;background-color:#f0f2f5}.gm-settings-body{background-color:#f7f8fa;flex:1 1 0;min-height:0;padding:0;display:flex;position:relative;overflow:hidden}.gm-settings-sidebar{box-sizing:border-box;background-color:#fff;border-right:1px solid #ced0d4;flex-direction:column;flex-shrink:0;width:140px;height:100%;max-height:100%;padding:6px 0;display:flex;overflow-y:auto}.gm-settings-content{box-sizing:border-box;scrollbar-width:thin;scrollbar-color:#ced0d4 transparent;flex:1;height:100%;max-height:100%;padding:8px 12px;overflow-y:auto}.gm-tab-btn{text-align:left;cursor:pointer;color:#65676b;background:0 0;border:none;border-radius:6px;margin-bottom:1px;padding:6px 10px;font-size:14px;font-weight:500;transition:all .2s}.gm-tab-btn:hover{color:#050505;background-color:#f0f2f5}.gm-tab-btn.active{color:#1877f2;background-color:#e7f3ff;font-weight:600}.gm-panel{flex-direction:column;gap:4px;animation:.2s ease-out gm-fade-in;display:none}.gm-panel.active{display:flex}.gm-grid-hybrid{grid-template-columns:1fr 1fr;align-items:center;gap:4px 12px;display:grid}.gm-setting-row{box-sizing:border-box;justify-content:space-between;align-items:center;min-height:28px;margin-bottom:0;padding:2px 0;transition:opacity .2s;display:flex}.gm-setting-row.span-2{grid-column:span 2;width:100%}.gm-setting-row.full-width{width:100%}.gm-setting-label{color:#050505;margin-right:12px;font-size:13px;font-weight:500;line-height:1.3}.gm-switch{flex-shrink:0;width:36px;height:20px;display:inline-block;position:relative}.gm-switch input{opacity:0;width:0;height:0}.gm-slider{cursor:pointer;background-color:#ced0d4;border-radius:34px;transition:all .4s;position:absolute;inset:0}.gm-slider:before{content:\"\";background-color:#fff;border-radius:50%;width:16px;height:16px;transition:all .4s;position:absolute;bottom:2px;left:2px;box-shadow:0 1px 3px #0003}input:checked+.gm-slider{background-color:#1877f2}input:checked+.gm-slider:before{transform:translate(16px)}input:disabled+.gm-slider{opacity:.5;cursor:not-allowed}.gm-input-text{color:#050505;text-align:right;background:#f0f2f5;border:1px solid #ced0d4;border-radius:6px;outline:none;width:80px;padding:4px 8px;font-size:13px;transition:border-color .2s}.gm-input-text:focus{background:#fff;border-color:#1877f2}.gm-keybinder-btn{color:#050505;cursor:pointer;text-align:center;background:#fff;border:1px solid #ced0d4;border-radius:6px;min-width:80px;padding:6px 12px;font-size:13px;font-weight:500;transition:all .2s}.gm-keybinder-btn:hover{background:#f0f2f5;border-color:#1877f2}.gm-keybinder-btn.recording{color:#f44336;background:#fff5f5;border-color:#f44336;animation:1.5s infinite gm-pulse}@keyframes gm-pulse{0%{box-shadow:0 0 #f4433666}70%{box-shadow:0 0 0 6px #f4433600}to{box-shadow:0 0 #f4433600}}.gm-input-select{cursor:pointer;color:#050505;appearance:none;background:#f0f2f5 url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%2365676B%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E) right 8px top 50%/8px no-repeat;border:1px solid #ced0d4;border-radius:6px;outline:none;padding:4px 24px 4px 8px;font-size:13px}.gm-details{border:1px solid #f0f2f5;border-radius:6px;width:100%;margin-top:4px}.gm-summary{cursor:pointer;color:#65676b;-webkit-user-select:none;user-select:none;background-color:#f7f8fa;justify-content:space-between;align-items:center;padding:5px 8px;font-size:13px;font-weight:600;display:flex}.gm-summary:hover{color:#050505;background-color:#f0f2f5}.gm-summary:after{content:\"▼\";font-size:10px;transition:transform .2s}.gm-details[open] .gm-summary:after{transform:rotate(180deg)}.gm-details-content{background:#fff;border-top:1px solid #f0f2f5;flex-direction:column;gap:4px;padding:8px;display:flex}.gm-settings-footer{background:#fff;border-top:1px solid #f0f2f5;flex-shrink:0;justify-content:space-between;align-items:center;padding:6px 12px;display:flex}.gm-btn-save{color:#fff;cursor:pointer;background-color:#1877f2;border:none;border-radius:6px;padding:5px 16px;font-size:13px;font-weight:600;transition:background-color .2s}.gm-btn-save:hover{background-color:#166fe5}.gm-btn-reset{color:#dc2626;cursor:pointer;background-color:#0000;border:none;border-radius:6px;padding:5px 10px;font-size:13px;font-weight:500;transition:background .2s}.gm-btn-reset:hover{background-color:#fef2f2}@keyframes gm-fade-in{0%{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}input[type=range]{appearance:none;cursor:pointer;background:#ced0d4;border-radius:3px;outline:none;height:6px}input[type=range]::-webkit-slider-thumb{appearance:none;cursor:pointer;background:#1877f2;border:2px solid #fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0003}input[type=range]::-moz-range-thumb{cursor:pointer;background:#1877f2;border:2px solid #fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0003}input[type=range]::-moz-range-track{background:#ced0d4;border-radius:3px;height:6px}input[type=range]:disabled{opacity:.5;cursor:not-allowed}.gm-range-container{flex:1;align-items:center;margin-left:24px;display:flex}.gm-range-container input[type=range]{flex:1;width:100%;min-width:0}.gm-bookmark-text-container{transition:padding-right .15s ease-in-out;padding-right:8px!important}.gm-bookmarks-sidebar a:hover .gm-bookmark-text-container{padding-right:86px!important}.gm-bookmark-action-buttons{opacity:0;pointer-events:none;transition:opacity .15s ease-in-out}.gm-bookmarks-sidebar a:hover .gm-bookmark-action-buttons{opacity:1;pointer-events:auto}.gm-settings-bookmark-text-container{transition:padding-right .15s ease-in-out;padding-right:8px!important}.gm-settings-bookmark-card:hover .gm-settings-bookmark-text-container{padding-right:48px!important}.gm-settings-bookmark-action-buttons{opacity:0;pointer-events:none;transition:opacity .15s ease-in-out}.gm-settings-bookmark-card:hover .gm-settings-bookmark-action-buttons{opacity:1;pointer-events:auto}.gm-settings-card-open-btn{border-radius:4px;justify-content:center;align-items:center;width:20px;height:20px;transition:all .15s ease-in-out;display:inline-flex;text-decoration:none!important}.gm-settings-card-open-btn:hover{background-color:#1877f21a;transform:scale(1.1)}.gm-settings-card-open-btn:active{transform:scale(.9)}.gm-delete-confirm-btn{transition:all .15s ease-in-out}.gm-delete-confirm-btn:hover{transform:scale(1.08);background-color:#ffebeb!important}.gm-delete-confirm-btn:active{transform:scale(.92)}.gm-sidebar-close-btn{border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;transition:all .2s ease-in-out;display:flex}.gm-sidebar-close-btn:hover{background-color:#00000014;color:#050505!important}.gm-sidebar-close-btn:active{transform:scale(.9)}.gm-sidebar-manage-btn{border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;transition:all .2s ease-in-out;display:flex}.gm-sidebar-manage-btn:hover{background-color:#00000014;transform:rotate(30deg)}.gm-sidebar-manage-btn:active{transform:scale(.9)rotate(30deg)}.gm-sidebar-tab-btn{transition:all .2s ease-in-out}.gm-sidebar-tab-btn:hover{background-color:#00000008}.gm-sidebar-tab-btn:active{opacity:.8}.gm-sidebar-folder-btn{transition:all .15s ease-in-out}.gm-sidebar-folder-btn:hover{filter:brightness(.95);transform:translateY(-1px)}.gm-sidebar-folder-btn:active{transform:scale(.95)}.gm-sidebar-folder-delete-btn{border-radius:50%;justify-content:center;align-items:center;width:12px;height:12px;transition:all .15s ease-in-out;display:flex}.gm-sidebar-folder-delete-btn:hover{background-color:#ffffff4d;color:#fa383e!important}.gm-card-action-btn{box-sizing:border-box;border-radius:4px;justify-content:center;align-items:center;width:20px;height:20px;transition:all .15s ease-in-out;display:inline-flex;padding:0!important;font-size:11px!important;line-height:1!important}.gm-card-action-btn:hover{background-color:#0000000f;transform:scale(1.1)}.gm-card-action-btn:active{transform:scale(.9)}.gm-settings-export-btn{color:#050505;cursor:pointer;background-color:#fff;border:1px solid #ced0d4;border-radius:6px;padding:6px 12px;font-size:13px;font-weight:600;transition:all .2s ease-in-out}.gm-settings-export-btn:hover{background-color:#f0f2f5!important;border-color:#8a8d91!important}.gm-settings-export-btn:active{transform:scale(.96)}.gm-settings-clear-all-btn{color:#dc2626;cursor:pointer;background-color:#fff;border:1px solid #fca5a5;border-radius:6px;padding:6px 12px;font-size:13px;font-weight:600;transition:all .2s ease-in-out}.gm-settings-clear-all-btn:hover{background-color:#fef2f2!important;border-color:#dc2626!important}.gm-settings-clear-all-btn:active{transform:scale(.96)}.gm-tag-badge-remove-btn{border-radius:50%;justify-content:center;align-items:center;width:12px;height:12px;padding:0;transition:all .15s ease-in-out;display:inline-flex}.gm-tag-badge-remove-btn:hover{background-color:#fa383e;color:#fff!important}.gm-search-clear-btn{border-radius:50%;justify-content:center;align-items:center;width:16px;height:16px;transition:all .15s ease-in-out;display:flex}.gm-search-clear-btn:hover{background-color:#0000001a;color:#333!important}.gm-bookmark-timestamp{opacity:1;transition:opacity .15s ease-in-out}.gm-bookmarks-sidebar a:hover .gm-bookmark-timestamp,.gm-settings-bookmark-card:hover .gm-bookmark-timestamp{opacity:0;pointer-events:none}.gm-settings-page-card{background-color:#f9f9f9!important;border:1px solid #eee!important;border-radius:8px!important;justify-content:space-between!important;align-items:center!important;gap:16px!important;margin-bottom:5px!important;padding:5px 10px!important;transition:all .15s ease-in-out!important;display:flex!important;position:relative!important}.gm-settings-page-card:hover{background-color:#f0f2f5!important}.gm-settings-page-info{flex:1!important;min-width:0!important;padding-right:6px!important;transition:padding-right .15s ease-in-out!important}.gm-settings-page-card:hover .gm-settings-page-info{padding-right:220px!important}.gm-settings-page-actions{opacity:0!important;pointer-events:none!important;flex-shrink:0!important;align-items:center!important;gap:8px!important;transition:opacity .15s ease-in-out!important;display:flex!important;position:absolute!important;top:50%!important;right:12px!important;transform:translateY(-50%)!important}.gm-settings-page-card:hover .gm-settings-page-actions{opacity:1!important;pointer-events:auto!important}.gm-settings-page-actions button{transition:all .15s ease-in-out!important}.gm-settings-page-actions button:hover{background-color:#0000000d!important;border-color:#65676b!important;transform:translateY(-1px)!important}.gm-settings-page-actions button:active{transform:scale(.95)!important}.gm-sidebar-star-btn{border-radius:50%!important;justify-content:center!important;align-items:center!important;width:24px!important;height:24px!important;transition:all .15s ease-in-out!important;display:flex!important}.gm-sidebar-star-btn:hover{background-color:#00000014!important;transform:scale(1.1)!important}.gm-sidebar-star-btn:active{transform:scale(.9)!important}.gm-following-fab{background:var(--card-background-glass,#ffffffbf)!important;-webkit-backdrop-filter:blur(12px)!important;border:1px solid var(--media-inner-border,#00000014)!important;cursor:pointer!important;z-index:9999!important;-webkit-user-select:none!important;user-select:none!important;width:44px!important;height:44px!important;color:var(--primary-text,#050505)!important;border-radius:22px!important;justify-content:center!important;align-items:center!important;font-family:inherit!important;transition:all .3s cubic-bezier(.25,1,.5,1)!important;display:flex!important;position:fixed!important;bottom:24px!important;right:24px!important;overflow:hidden!important;box-shadow:0 4px 12px #00000026!important}.gm-following-fab:hover{background:var(--card-background-glass-hover,#ffffffd9)!important;width:175px!important;transform:translateY(-2px)!important;box-shadow:0 6px 20px #0003!important}.gm-following-fab:active{transform:translateY(0)scale(.95)!important}.gm-following-fab-icon{flex-shrink:0!important;justify-content:center!important;align-items:center!important;width:20px!important;height:20px!important;transition:transform .3s!important;display:flex!important}.gm-following-fab:hover .gm-following-fab-icon{transform:rotate(15deg)}.gm-following-fab-text{white-space:nowrap!important;opacity:0!important;width:0!important;margin-left:0!important;font-size:13px!important;font-weight:600!important;transition:opacity .2s,margin .2s,width .2s!important}.gm-following-fab:hover .gm-following-fab-text{opacity:1!important;width:auto!important;margin-left:8px!important}.gm-following-fab.gm-success{color:#fff!important;background:linear-gradient(135deg,#2e7d32,#1b5e20)!important;border-color:#0000!important;width:205px!important}.gm-following-fab.gm-success .gm-following-fab-icon svg{fill:#fff!important}.gm-following-fab.gm-success .gm-following-fab-text{opacity:1!important;color:#fff!important;width:auto!important;margin-left:8px!important}");
	var config = {
		LOG_PREFIX: `[FB Login Wall Remover]`,
		THROTTLE_DELAY: 250,
		PROCESSED_MARKER: "gmProcessed",
		WORKER_PARAM: "fpc_worker_task",
		TRACKING_PARAMS: [
			"utm_source",
			"utm_medium",
			"utm_campaign",
			"utm_term",
			"utm_content",
			"utm_id",
			"gclid",
			"gclsrc",
			"dclid",
			"gbraid",
			"wbraid",
			"srsltid",
			"_ga",
			"_gl",
			"fbclid",
			"ref",
			"ref_id",
			"ref_src",
			"ref_campaign",
			"ref_source",
			"ref_",
			"hc_ref",
			"hc_location",
			"acontext",
			"dti",
			"fref",
			"action_object_map",
			"action_ref_map",
			"action_type_map",
			"fb_action_ids",
			"fb_action_types",
			"__cft__",
			"__tn__",
			"__eep__",
			"h",
			"s",
			"t",
			"m_entstream_source",
			"hoisted_section_header_type",
			"store_visit_source",
			"entrypoint",
			"paipv",
			"rdid",
			"_rdc",
			"_rdr",
			"_ft_",
			"mibextid",
			"extid",
			"fbadid",
			"nb_placement",
			"nb_expid_meta",
			"nbt",
			"fb_content_id",
			"encrypted_payload",
			"channel_type",
			"adfrom",
			"nx_source",
			"_zucks_suid",
			"fb_comment_id",
			"fb_ref",
			"fb_source",
			"igsh",
			"xmt",
			"si",
			"feature",
			"_nc_cat",
			"_nc_sid",
			"ccb",
			"twclid",
			"mc_cid",
			"mc_eid",
			"hsenc",
			"_hsmi",
			"mkcid",
			"mkrid",
			"cjevent",
			"msclkid",
			"epik",
			"pp",
			"sc_cid",
			"snap_campaign_id",
			"tt_from",
			"tt_medium",
			"tt_content",
			"guccounter",
			"guce_referrer",
			"guce_referrer_sig",
			"_openstat",
			"li_fat_id",
			"trk"
		],
		SCROLL_RESTORER_CONFIG: {
			CORRECTION_DURATION: 250,
			CORRECTION_FREQUENCY: 16,
			WATCHER_FREQUENCY: 150,
			MODAL_GRACE_PERIOD: 300
		},
		AUTO_LOADER: {
			POLL_INTERVAL: 300,
			MAX_WAIT_TIME: 3500,
			MIN_COOLDOWN: 1e3,
			MAX_RETRIES: 3
		},
		ERROR_RECOVERY: {
			RELOAD_BUTTON_LABELS: [
				"Reload Page",
				"重新載入頁面",
				"ページを更新",
				"Volver a cargar página",
				"Ricarica la pagina",
				"Seite neu laden",
				"Actualiser la Page",
				"Обновить страницу",
				"Sayfayı Yenile",
				"페이지 새로 고침",
				"Tải lại trang",
				"โหลดเพจอีกครั้ง",
				"Muat Ulang Halaman",
				"पेज फिर से लोड करें",
				"Memuat Semula Halaman",
				"Recarregar página",
				"Ladda om sidan",
				"Pagina opnieuw laden",
				"Last inn siden på nytt",
				"إعادة تحميل الصفحة",
				"Odśwież stronę",
				"Genindlæs side",
				"Lataa sivu uudelleen",
				"Znovu stránku načíst",
				"Ανανέωση σελίδας",
				"重新加载页面",
				"Перезавантажити сторінку",
				"I-reload ang Page",
				"Reîncarcă pagina",
				"Oldal újratöltése",
				"טען/טעני מחדש את הדף"
			],
			MAX_RETRIES: 2,
			STORAGE_KEY: "fblwr_retry_state"
		},
		ADS_LIB: {
			KEY_TARGET_ID: "fblwr_ads_target_id",
			KEY_INT_ACTION: "fblwr_int_action",
			INITIAL_DELAY: 300,
			POLL_INTERVAL: 250,
			MAX_ATTEMPTS: 20
		},
		COAUTHOR_CONJUNCTIONS: [
			"is with",
			"is at",
			"was with",
			"were with",
			"was at",
			"were at",
			"other",
			"others",
			"more",
			"co-author",
			"co-authors",
			"collaborator",
			"collaborators",
			"和其",
			"與其",
			"以及其他",
			"其他",
			"還有其他",
			"共同投稿",
			"共同創作者",
			"協同發文",
			"協同發文者",
			"和另外",
			"與另外",
			"位旁人",
			"位其他",
			"個其他",
			"位其他創作者",
			"位其他成員",
			"と一緒に",
			"との共同投稿",
			"共同投稿",
			"共同投稿者",
			"コラボレーター",
			"その他",
			"のほか",
			"にいます",
			"にいました",
			"님과 함께",
			"외 ",
			"공동 작업자",
			"공동작업자",
			"콜라보레이터",
			"에 있습니다",
			"에 있었습니다",
			"está con",
			"estuvo con",
			"estuvieron con",
			"está en",
			"estuvo en",
			"personas más",
			"persona más",
			"otros",
			"colaborador",
			"colaboradores",
			"avec",
			"était avec",
			"étaient avec",
			"est à",
			"était à",
			"autres personnes",
			"autre personne",
			"autres",
			"co-auteur",
			"co-auteurs",
			"collaborateur",
			"collaborateurs",
			"ist mit",
			"war mit",
			"waren mit",
			"ist in",
			"war in",
			"weitere Personen",
			"weitere",
			"anderen",
			"andere",
			"Mitverfasser",
			"Mitersteller",
			"Kollaborateur",
			"cùng với",
			"đang ở",
			"người khác",
			"đồng tác giả",
			"đồng sáng tạo",
			"người nữa",
			"คนอื่นๆ",
			"คนอื่น",
			"ร่วมกับ",
			"e altri",
			"e altre",
			"con ",
			"presso ",
			"è con",
			"era con",
			"coautore",
			"coautori",
			"collaboratore",
			"collaboratori",
			"e outros",
			"e outras",
			"com ",
			"está com",
			"esteve com",
			"coautor",
			"coautores",
			"colaborador",
			"colaboradores",
			"dan lainnya",
			"dan lain-lain",
			"bersama ",
			"rekan kolaborasi",
			"kontributor",
			"ile birlikte",
			"ve diğerleri",
			"en anderen",
			"is met",
			"och andra",
			"är med",
			"вместе с",
			"и еще",
			"соавтор",
			"соавторы",
			"находится в",
			"وآخرين"
		],
		STATS_PATTERNS: {
			COMMENT_KEYWORDS: "comments?|則?留言|条(?:留言|评论)|评论|(?:件の)?コメント|댓글|ความคิดเห็น|(?:lượt\\s+)?bình luận|комментари\\w*|تعليق(?:ات)?|commentaires?|coment[áa]rios?|comentarios?|commenti|Kommentare?|komentar|yorum(?:lar)?|reacties?|kommentarer?",
			SHARE_KEYWORDS: "shares?|次?分享|(?:件の)?シェア|공유|แชร์|(?:lượt\\s+)?chia sẻ|подели\\w*|репост\\w*|مشارك(?:ة|ات)|partages?|veces compartido|compartidos?|compartilhamentos?|condivisioni|(?:Mal\\s+)?geteilt|Teilen|(?:kali\\s+)?dibagikan|bagikan|paylaşım(?:lar)?|(?:keer\\s+)?gedeeld|delning(?:ar)?",
			REACTION_ALL_KEYWORDS: [
				"All reactions",
				"所有心情",
				"すべてのリアクション",
				"Tất cả cảm xúc",
				"모든 반응",
				"Todas las reacciones",
				"Toutes les réactions",
				"Alle Reaktionen",
				"Tutte le reazioni",
				"Todas as reações",
				"Semua reaksi",
				"Tüm ifadeler",
				"Alle reacties",
				"Alla reaktioner",
				"Все реакции",
				"كل التفاعلات",
				"ความรู้สึกทั้งหมด"
			],
			REACTION_SIGNATURES: {
				like: /M7\.3014\s+3\.8662a\.6974/i,
				love: /M7\.9996\s+5\.9081c/i,
				care: /M9\.585\s+7\.7886a/i,
				haha: /M12\.5278\s+8\.1957c/i,
				wow: /ellipse\s+cx=['"]?11\.1978['"]?/i,
				sad: /M7\.9946\s+11\.2002c/i,
				angry: /M13\.3283\s+7\.0331a/i
			}
		},
		TEXT_EXPANDER: {
			SCOPE_SELECTOR: "div[role=\"article\"]",
			BUTTON_SELECTOR: "div[role=\"button\"]",
			PROCESSED_ATTR: "data-gm-expanded"
		},
		TIMELINE: {
			WIDTH_COLLAPSED: "24px",
			WIDTH_MAX_LIMIT: "260px",
			DOT_SIZE: "8px",
			ROW_HEIGHT: "20px"
		},
		LOGIN_STATE_MARKERS: {
			LOGGED_OUT: [
				{
					selector: "form#login_form",
					reason: "Primary login form element"
				},
				{
					selector: "input[name=\"pass\"]",
					reason: "Password input field"
				},
				{
					selector: "a[href*=\"/recover/initiate\"]",
					reason: "Forgot Account link"
				},
				{
					selector: "a[href*=\"/login/\"]",
					reason: "Login link"
				}
			],
			LOGGED_IN: [{
				selector: "input[type=\"search\"]",
				reason: "Search input field"
			}, {
				selector: "a[href=\"/friends/\"]",
				reason: "Friends tab"
			}]
		},
		SELECTORS: {
			GLOBAL: {
				POST_CONTAINER: "div[role=\"article\"]",
				MODAL_CONTAINER: "div.__fb-light-mode",
				DIALOG: "[role=\"dialog\"]",
				LOGIN_FORM: "form#login_form, form[id=\"login_popup_cta_form\"]",
				MEDIA_LINK: `a[href*="/photo"], a[href*="fbid="], a[href*="/videos/"], a[href*="/watch/"], a[href*="/reel/"]`,
				VIDEO_PAGE_TOOLBAR_ROOT: "div[role=\"banner\"], .xzkaem6",
				CLOSE_BUTTON: [
					"Close",
					"關閉",
					"閉じる",
					"Cerrar",
					"Fermer",
					"Schließen",
					"Fechar",
					"Chiudi",
					"Sluiten",
					"Закрыть",
					"Kapat",
					"Zamknij",
					"Tutup",
					"Đóng",
					"閉",
					"Zatvori",
					"Zavrieť",
					"Zavřít",
					"Bezárás",
					"Stäng",
					"Luk",
					"Lukk",
					"Sulje",
					"Κλείσιμο",
					"Închide",
					"إغلاق",
					"סגور"
				].map((label) => `[aria-label="${label}"][role="button"]`).join(", ") + ", div[role=\"button\"]:has(i[data-visualcompletion=\"css-img\"])"
			},
			NAVIGATOR: {
				HIGHLIGHT_CLASS: "gm-post-highlight",
				TIMELINE_LINK_CANDIDATES: "a[role=\"link\"]"
			},
			POST_TOOLS: {
				BUTTON_CLASS: "gm-tool-button",
				PROCESSED_MARKER: "gmToolsProcessed",
				FEED_POST_HEADER: "div[data-ad-rendering-role=\"profile_name\"] h2, div[data-ad-rendering-role=\"profile_name\"] h3",
				DIALOG_POST_HEADER: "h2, h3",
				CONTENT_BODY: "div[data-ad-rendering-role=\"story_message\"]",
				EXPAND_BTN: "div[role=\"button\"]",
				TEXT_BLOCKS: "div[dir=\"auto\"]"
			},
			EXTRACTOR: {
				FOLLOWING_CONTAINER: "[data-pagelet=\"ProfileAppSection_0\"]",
				FOLLOWING_ITEM: "div.x1iyjqo2.xv54qhq"
			},
			SCREENSHOT: { NAME_WRAPPER: ".x3nfvp2" }
		},
		CONSTANTS: {
			SPRITES: {
				COMMENT: -1171,
				SHARE: -1188,
				SHARE_ALT: -1071,
				TOLERANCE: 5,
				RELATIVE_OFFSET: 17
			},
			REGEX_PARTS: { UNIT_GROUP: "[KkMm萬億万\\u842c\\u5104\\u4e07]" },
			MEDIA_CONTROL_LABELS: [
				"放大",
				"縮小",
				"進入全螢幕模式",
				"上一張",
				"下一張",
				"關閉",
				"閉じる",
				"Zoom",
				"Fullscreen",
				"Previous",
				"Next",
				"Close",
				"拡大",
				"縮小",
				"全画面表示",
				"前へ",
				"次へ"
			],
			OBSERVER: {
				ROOT_MARGIN: "-45% 0px -45% 0px",
				THRESHOLD: .01
			},
			FOLLOW_BUTTON_LABELS: [
				"Follow",
				"追蹤",
				"关注",
				"フォローする",
				"팔로우",
				"Seguir",
				"Folgen",
				"Suivre",
				"Segui",
				"Подписаться",
				"متابعة"
			]
		},
		TIMEOUTS: {
			THROTTLE_DEFAULT: 250,
			THROTTLE_SCROLL: 100,
			THROTTLE_UI: 200,
			DEBOUNCE_SEARCH: 400,
			INITIAL_DELAY: 50,
			RETRY_INTERVAL: 200,
			MAX_RETRY_DURATION: 3e3,
			SCROLL_LOCK: 800
		},
		UI: {
			Z_INDEX: {
				FLOATING_NAV: 9990,
				TRANSPARENCY: 9990,
				TIMELINE: 9995,
				TOOLBAR: 9998,
				HOVER_TRIGGER: 9999,
				HOVER_HINT: 1e4,
				TOAST: 99999,
				MODAL_BACKDROP: 99998,
				MODAL_FOREGROUND: 99999,
				ID_BADGE: 99999
			},
			DIMENSIONS: {
				BADGE_MIN_WIDTH: "280px",
				BADGE_MAX_WIDTH: "320px",
				FLOATING_NAV_BOTTOM: "20px",
				FLOATING_NAV_RIGHT: "50px"
			},
			HEATMAP_THRESHOLDS: [
				.95,
				.85,
				.75,
				.65,
				.55,
				.45,
				.35,
				.2,
				.1
			],
			HEATMAP_WEIGHTS: {
				REACTION: 1,
				COMMENT: 2,
				SHARE: 3
			}
		},
		TIME_KEYWORDS: {
			JUST_NOW: /剛剛|just now|たった今|방금|เมื่อสักครู่|vừa xong|à l'instant|hace un momento|gerade eben|proprio ora|agora mesmo|baru saja|az önce|şimdi|przed chwilą/i,
			YESTERDAY: /昨天|yesterday|昨日|hier|ayer|gestern|ieri|ontem|어제|เมื่อวาน|hôm qua|dün|kemarin|kahapon|wczoraj|вчера|أمس/i,
			MINUTES: /^(\d+)\s*(分鐘|分钟|m\b|分|min\b|mins\b|분|Min\.?\b|мин|د|p\b|phút|นาที|dk\.?|dakika|mnt|menit|minuto|minutos|minuti|minute|minutes|Minute|Minuten|मि)/i,
			HOURS: /^(\d+)\s*(小時|小时|h\b|時間|hr|hrs|시간|Std\.?|ч|س|giờ|ชั่วโมง|ชม\.?|saat|sa\.?|jam|u\b|godz\.?|oras|hora|horas|ore|ora|Stunde|Stunden|घंटा|घंटे|घं)/i,
			DAYS: /^(\d+)\s*(天|d\b|日|일|j\b|g\b|T\.?\b|д|ngày|n\b|วัน|ว\.?|g\.?|giorno|giorni|jour|jours|día|días|dia|dias|Tag|Tage|gün|hari|araw|dni|दिन|दि)/i,
			WEEKS: /^(\d+)\s*(週|周|w\b|週間|week|weeks|주|sem\.?\b|W\.?\b|set\.?\b|нед\.?|أ|tuần|สัปดาห์|ส\.?|semana|semanas|semaine|semaines|settimana|settimane|Woche|Wochen|hafta|hf\.?\b|minggu|mg|linggo|wk|tyg\.?|सप्ताह|सप्)/i
		}
	};
	var utils_exports = __exportAll({
		AM_PATTERN: () => AM_PATTERN,
		BookmarkStorage: () => BookmarkStorage,
		PM_PATTERN: () => PM_PATTERN,
		cleanDomText: () => cleanDomText,
		cleanUrlParams: () => cleanUrlParams,
		convertToAbsoluteTimestamp: () => convertToAbsoluteTimestamp,
		createStyledElement: () => createStyledElement,
		debounce: () => debounce,
		delay: () => delay,
		extractPostIdFromUrl: () => extractPostIdFromUrl,
		getMonthsMap: () => getMonthsMap,
		isFeedPage: () => isFeedPage,
		isLoggedIn: () => isLoggedIn,
		isPeopleHomeUrl: () => isPeopleHomeUrl,
		isSeeMoreButton: () => isSeeMoreButton,
		isTimestampLink: () => isTimestampLink,
		isVisible: () => isVisible,
		scrollToElement: () => scrollToElement,
		smartOpen: () => smartOpen,
		smartTextExtract: () => smartTextExtract,
		throttle: () => throttle,
		updateAmPmPatternsRuntime: () => updateAmPmPatternsRuntime,
		updateTimeKeywordsRuntime: () => updateTimeKeywordsRuntime
	});
	function isLoggedIn() {
		const LOG = "[FB Login Wall Remover] [LoginCheck]";
		const banner = document.querySelector("div[role=\"banner\"]");
		if (!banner) {
			console.log(`${LOG} No banner element found (div[role="banner"]). Assuming logged-out.`);
			return false;
		}
		console.log(`${LOG} Banner element found.`);
		for (const marker of [
			{
				selector: "form#login_form",
				reason: "Primary login form element"
			},
			{
				selector: "input[name=\"pass\"]",
				reason: "Password input field"
			},
			{
				selector: "a[href*=\"/recover/initiate\"]",
				reason: "Forgot Account link"
			},
			{
				selector: "a[href*=\"/login/\"]",
				reason: "Login link"
			}
		]) if (banner.querySelector(marker.selector)) {
			console.log(`${LOG} LOGGED-OUT marker matched: "${marker.selector}" (${marker.reason}). Result: NOT logged in.`);
			return false;
		}
		for (const marker of [{
			selector: "input[type=\"search\"]",
			reason: "Search input field"
		}, {
			selector: "a[href=\"/friends/\"]",
			reason: "Friends tab"
		}]) if (banner.querySelector(marker.selector)) {
			console.log(`${LOG} LOGGED-IN marker matched: "${marker.selector}" (${marker.reason}). Result: LOGGED IN.`);
			return true;
		}
		console.log(`${LOG} No definitive markers matched. Assuming logged-out (safe default).`);
		return false;
	}
	function isFeedPage() {
		const { pathname } = window.location;
		if (/\/posts\//.test(pathname)) return false;
		if (/\/videos\//.test(pathname) && pathname.split("/").length > 2) return false;
		if (/\/photos?\//.test(pathname)) return false;
		if (pathname.includes("/permalink.php")) return false;
		if (pathname.includes("/story.php")) return false;
		if (pathname.includes("/media/set")) return false;
		if (pathname.includes("/photo.php")) return false;
		if (pathname.includes("/video.php")) return false;
		const pathSegments = pathname.split("/").filter(Boolean);
		if (pathSegments.length === 0) return true;
		if (pathSegments.length >= 2) {
			const subPage = pathSegments[1].toLowerCase();
			if ([
				"about",
				"reels",
				"photos",
				"videos",
				"friends",
				"followers",
				"following",
				"music",
				"map",
				"sports",
				"movies",
				"tv",
				"books",
				"reviews_given",
				"mentions",
				"likes",
				"likes_given",
				"places",
				"check_ins",
				"events",
				"groups",
				"manage",
				"offers",
				"shop",
				"services",
				"community",
				"publications"
			].includes(subPage) || subPage.startsWith("about_")) return false;
		}
		if (pathSegments[0] === "groups" && pathSegments.length >= 1) return true;
		return ![
			"watch",
			"marketplace",
			"gaming",
			"events",
			"messages",
			"notifications",
			"friends",
			"photo",
			"videos",
			"reel",
			"posts",
			"stories",
			"settings",
			"saved"
		].includes(pathSegments[0]);
	}
	function throttle(func, delay) {
		let timeoutId = null;
		return (...args) => {
			if (timeoutId === null) timeoutId = setTimeout(() => {
				if (typeof window === "undefined" || window.closed) {
					timeoutId = null;
					return;
				}
				try {
					func(...args);
				} catch (e) {
					if (e && typeof e.message === "string" && e.message.includes("Component not initialized")) {} else console.error("[FB Login Wall Remover] Error in throttled call:", e);
				}
				timeoutId = null;
			}, delay);
		};
	}
	function debounce(func, wait) {
		let timeout = null;
		return (...args) => {
			if (timeout !== null) clearTimeout(timeout);
			timeout = setTimeout(() => func(...args), wait);
		};
	}
	function createStyledElement(tag, styles = {}, properties = {}) {
		if (typeof document === "undefined" || !document.createElement) throw new Error("Component not initialized: document is not available");
		const element = document.createElement(tag);
		Object.assign(element.style, styles);
		const { on, children, ...rest } = properties;
		Object.assign(element, rest);
		if (on) for (const [eventName, handler] of Object.entries(on)) element.addEventListener(eventName, handler);
		if (children) {
			const childList = Array.isArray(children) ? children : [children];
			element.append(...childList.filter(Boolean));
		}
		return element;
	}
	var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
	function smartOpen(event, url) {
		event.preventDefault();
		if (event.button === 1 || event.ctrlKey || event.metaKey) if (typeof GM_openInTab !== "undefined") GM_openInTab(url, {
			active: false,
			insert: true
		});
		else window.open(url, "_blank");
		else window.open(url, "_blank");
	}
	function isVisible(el) {
		if (!el) return false;
		return el.offsetParent !== null && window.getComputedStyle(el).display !== "none";
	}
	function cleanUrlParams(urlObj) {
		if (!urlObj || !urlObj.searchParams) return false;
		const trackingParams = config.TRACKING_PARAMS;
		const keysToDelete = [];
		urlObj.searchParams.forEach((_, key) => {
			if (trackingParams.some((tp) => key === tp || key.startsWith(`${tp}[`))) keysToDelete.push(key);
		});
		keysToDelete.forEach((k) => urlObj.searchParams.delete(k));
		return keysToDelete.length > 0;
	}
	function scrollToElement(element, forceSmooth = null, alignmentOverride = null, app) {
		if (!element) return;
		const settings = app?.state?.settings || {};
		const alignment = alignmentOverride || settings.navigationScrollAlignment || "top";
		const alignCenter = alignment === "center";
		const alignBottom = alignment === "bottom";
		const behavior = (forceSmooth !== null ? forceSmooth : !!settings.enableSmoothScrolling) ? "smooth" : "auto";
		const rect = element.getBoundingClientRect();
		const currentScroll = window.scrollY || window.pageYOffset;
		let targetY;
		if (alignCenter) targetY = currentScroll + rect.top + rect.height / 2 - window.innerHeight / 2;
		else if (alignBottom) targetY = currentScroll + rect.bottom - window.innerHeight + 10;
		else {
			let offset = 10;
			if (app?.modules?.searchBar && typeof app.modules.searchBar.getOccupiedHeight === "function") offset += app.modules.searchBar.getOccupiedHeight();
			targetY = currentScroll + rect.top - offset;
		}
		window.scrollTo({
			top: targetY,
			behavior
		});
	}
	function smartTextExtract(root) {
		let text = "";
		if (!root) return text;
		const ensureNewlines = (count) => {
			if (text.length === 0) return;
			let current = 0;
			for (let i = text.length - 1; i >= 0; i--) if (text[i] === "\n") current++;
			else break;
			while (current < count) {
				text += "\n";
				current++;
			}
		};
		const isBlock = (node) => {
			const tag = node.tagName?.toUpperCase();
			return [
				"DIV",
				"P",
				"H1",
				"H2",
				"H3",
				"H4",
				"H5",
				"H6",
				"LI",
				"BLOCKQUOTE",
				"SECTION",
				"ARTICLE"
			].includes(tag);
		};
		const hasBlockChildren = (node) => {
			for (let i = 0; i < node.children.length; i++) if (isBlock(node.children[i])) return true;
			return false;
		};
		const traverse = (node) => {
			if (node.nodeType === Node.TEXT_NODE) text += node.textContent || "";
			else if (node.nodeType === Node.ELEMENT_NODE) {
				const element = node;
				if (element.getAttribute("aria-hidden") === "true" || element.style.display === "none") return;
				const isBlockElem = isBlock(element);
				const isContainer = isBlockElem && hasBlockChildren(element);
				if (isBlockElem) ensureNewlines(1);
				if (element.tagName === "BR") text += "\n";
				else element.childNodes.forEach(traverse);
				if (isBlockElem) if (isContainer) ensureNewlines(2);
				else ensureNewlines(1);
			}
		};
		traverse(root);
		return text.trim();
	}
	var PM_PATTERN = /pm|下午|午後|오후|\bCH\b|noche|tarde|p\.m\.|sore|malam|หลังเที่ยง/i;
	var AM_PATTERN = /am|上午|午前|오전|\bSA\b|mañana|a\.m\.|pagi|siang|ก่อนเที่ยง/i;
	var cachedMonthsMap = null;
	function getMonthsMap() {
		if (cachedMonthsMap) return cachedMonthsMap;
		const monthsMap = {};
		const locales = new Set([
			"en",
			"es",
			"fr",
			"de",
			"it",
			"pt",
			"ru",
			"th",
			"id",
			"tr",
			"sv",
			"nl",
			"ar",
			"ja",
			"ko",
			"zh-TW",
			"zh-CN",
			"vi",
			"pl",
			"hi"
		]);
		if (typeof document !== "undefined" && document.documentElement && document.documentElement.lang) locales.add(document.documentElement.lang.toLowerCase());
		if (typeof navigator !== "undefined") {
			if (navigator.language) locales.add(navigator.language.toLowerCase());
			if (navigator.languages) navigator.languages.forEach((l) => locales.add(l.toLowerCase()));
		}
		for (const locale of locales) try {
			const formatterLong = new Intl.DateTimeFormat(locale, { month: "long" });
			const formatterShort = new Intl.DateTimeFormat(locale, { month: "short" });
			for (let m = 0; m < 12; m++) {
				const tempDate = new Date(2020, m, 15);
				const nameLong = formatterLong.format(tempDate).toLowerCase();
				const nameShort = formatterShort.format(tempDate).toLowerCase();
				monthsMap[nameLong] = m + 1;
				monthsMap[nameLong.replace(/\.$/, "")] = m + 1;
				monthsMap[nameLong.replace(/\./g, "")] = m + 1;
				monthsMap[nameShort] = m + 1;
				monthsMap[nameShort.replace(/\.$/, "")] = m + 1;
				monthsMap[nameShort.replace(/\./g, "")] = m + 1;
				const monthPart = new Intl.DateTimeFormat(locale, {
					day: "numeric",
					month: "long"
				}).format(tempDate).toLowerCase().replace(/\d+/g, "").replace(/[.,/\\-\s]+/g, "").trim();
				if (monthPart) {
					monthsMap[monthPart] = m + 1;
					monthsMap[monthPart.replace(/\.$/, "")] = m + 1;
					monthsMap[monthPart.replace(/\./g, "")] = m + 1;
				}
				const monthShortPart = new Intl.DateTimeFormat(locale, {
					day: "numeric",
					month: "short"
				}).format(tempDate).toLowerCase().replace(/\d+/g, "").replace(/[.,/\\-\s]+/g, "").trim();
				if (monthShortPart) {
					monthsMap[monthShortPart] = m + 1;
					monthsMap[monthShortPart.replace(/\.$/, "")] = m + 1;
					monthsMap[monthShortPart.replace(/\./g, "")] = m + 1;
				}
			}
		} catch (e) {}
		cachedMonthsMap = monthsMap;
		return monthsMap;
	}
	function updateTimeKeywordsRuntime() {
		const docLang = typeof document !== "undefined" && document.documentElement && document.documentElement.lang || typeof navigator !== "undefined" && navigator.language || "en";
		const units = [
			"minute",
			"hour",
			"day",
			"week"
		];
		const styles = [
			"long",
			"short",
			"narrow"
		];
		const unitMap = {
			minute: "MINUTES",
			hour: "HOURS",
			day: "DAYS",
			week: "WEEKS"
		};
		const fallbackUnits = {
			minute: [
				"分鐘",
				"分钟",
				"m",
				"分",
				"min",
				"mins",
				"분",
				"min.",
				"мин",
				"د",
				"phút",
				"นาที",
				"saat",
				"menit",
				"minuto",
				"minuti",
				"minute",
				"minutes"
			],
			hour: [
				"小時",
				"小时",
				"h",
				"時間",
				"시간",
				"Std",
				"ч",
				"س",
				"giờ",
				"ชั่วโมง",
				"saat",
				"jam",
				"ore",
				"ora",
				"hora",
				"horas",
				"hour",
				"hours"
			],
			day: [
				"天",
				"d",
				"日",
				"일",
				"д",
				"ngày",
				"วัน",
				"giorno",
				"giorni",
				"jour",
				"jours",
				"día",
				"días",
				"dia",
				"dias",
				"Tag",
				"Tage",
				"gün",
				"hari"
			],
			week: [
				"週",
				"周",
				"w",
				"week",
				"weeks",
				"주",
				"sem",
				"нед",
				"tuần",
				"สัปดาห์",
				"semana",
				"semanas",
				"semaine",
				"semaines",
				"settimana",
				"settimane",
				"Woche",
				"Wochen",
				"hafta",
				"minggu"
			]
		};
		units.forEach((unit) => {
			const keywords = new Set();
			styles.forEach((style) => {
				try {
					const cleanUnit = new Intl.RelativeTimeFormat(docLang, { style }).format(-1, unit).toLowerCase().replace(/[-\d\s.,()[\]{}]+/g, "").trim();
					if (cleanUnit) keywords.add(cleanUnit);
				} catch (e) {}
			});
			const key = unitMap[unit];
			const combinedTerms = Array.from(new Set([...fallbackUnits[unit], ...keywords]));
			config.TIME_KEYWORDS[key] = new RegExp(`^(\\d+)\\s*(?:${combinedTerms.join("|")})`, "i");
		});
		try {
			const yesterdayText = new Intl.RelativeTimeFormat(docLang, { numeric: "auto" }).format(-1, "day").toLowerCase().trim();
			const combinedYesterday = Array.from(new Set([...[
				"昨天",
				"yesterday",
				"昨日",
				"hier",
				"ayer",
				"gestern",
				"ieri",
				"ontem",
				"어제",
				"เมื่อวาน",
				"hôm qua",
				"dün",
				"kemarin",
				"kahapon",
				"wczoraj",
				"вчера",
				"أمس"
			], yesterdayText].filter(Boolean)));
			config.TIME_KEYWORDS.YESTERDAY = new RegExp(combinedYesterday.join("|"), "i");
		} catch (e) {}
		try {
			const nowText = new Intl.RelativeTimeFormat(docLang, { numeric: "auto" }).format(0, "second").toLowerCase().trim();
			const combinedJustNow = Array.from(new Set([...[
				"剛剛",
				"just now",
				"たった今",
				"방금",
				"เมื่อสักครู่",
				"vừa xong",
				"à l'instant",
				"hace un momento",
				"gerade eben",
				"proprio ora",
				"agora mesmo",
				"baru saja",
				"az önce",
				"şimdi",
				"przed chwilą"
			], nowText].filter(Boolean)));
			config.TIME_KEYWORDS.JUST_NOW = new RegExp(combinedJustNow.join("|"), "i");
		} catch (e) {}
	}
	function updateAmPmPatternsRuntime() {
		const locales = new Set([
			"en",
			"es",
			"fr",
			"de",
			"it",
			"pt",
			"ru",
			"th",
			"id",
			"tr",
			"sv",
			"nl",
			"ar",
			"ja",
			"ko",
			"zh-TW",
			"zh-CN",
			"vi",
			"pl",
			"hi"
		]);
		if (typeof document !== "undefined" && document.documentElement && document.documentElement.lang) locales.add(document.documentElement.lang.toLowerCase());
		if (typeof navigator !== "undefined") {
			if (navigator.language) locales.add(navigator.language.toLowerCase());
			if (navigator.languages) navigator.languages.forEach((l) => locales.add(l.toLowerCase()));
		}
		const amKeywords = new Set();
		const pmKeywords = new Set();
		for (const locale of locales) try {
			const formatter = new Intl.DateTimeFormat(locale, {
				hour: "numeric",
				hour12: true
			});
			const amDate = new Date(2020, 0, 15, 9, 0, 0);
			const amText = formatter.format(amDate).replace(/[\d\s:.]/g, "").trim().toLowerCase();
			if (amText) amKeywords.add(amText);
			const pmDate = new Date(2020, 0, 15, 21, 0, 0);
			const pmText = formatter.format(pmDate).replace(/[\d\s:.]/g, "").trim().toLowerCase();
			if (pmText) pmKeywords.add(pmText);
		} catch (e) {}
		if (amKeywords.size > 0) {
			const originalAm = AM_PATTERN.source.split("|");
			const combinedAm = Array.from(new Set([...originalAm, ...amKeywords]));
			AM_PATTERN = new RegExp(combinedAm.join("|"), "i");
		}
		if (pmKeywords.size > 0) {
			const originalPm = PM_PATTERN.source.split("|");
			const combinedPm = Array.from(new Set([...originalPm, ...pmKeywords]));
			PM_PATTERN = new RegExp(combinedPm.join("|"), "i");
		}
	}
	function adjustHourForAmPm(hour, text) {
		if (PM_PATTERN.test(text)) {
			if (hour < 12) return hour + 12;
		} else if (AM_PATTERN.test(text)) {
			if (hour === 12) return 0;
		}
		return hour;
	}
	function convertToAbsoluteTimestamp(rawText) {
		if (!rawText) return "";
		let clean = rawText.replace(/[\u200b-\u200d\uFEFF\u200e\u200f]+/g, "").replace(/[\u202f\u00a0\s]+/g, " ").trim();
		const easternArabicDigits = /[٠١٢٣٤٥٦٧٨٩]/g;
		const arabicToWestern = (char) => String(char.charCodeAt(0) - 1632);
		clean = clean.replace(easternArabicDigits, arabicToWestern);
		if (!clean) return "";
		const now = new Date();
		function formatDate(d, includeTime = true) {
			const yyyy = d.getFullYear();
			const mm = String(d.getMonth() + 1).padStart(2, "0");
			const dd = String(d.getDate()).padStart(2, "0");
			if (!includeTime) return `${yyyy}/${mm}/${dd}`;
			return `${yyyy}/${mm}/${dd} ${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
		}
		if (config.TIME_KEYWORDS.JUST_NOW.test(clean)) return formatDate(now, true);
		let match = clean.match(config.TIME_KEYWORDS.MINUTES);
		if (match) {
			const mins = parseInt(match[1], 10);
			return formatDate(new Date(now.getTime() - mins * 60 * 1e3), true);
		}
		match = clean.match(config.TIME_KEYWORDS.HOURS);
		if (match) {
			const hrs = parseInt(match[1], 10);
			return formatDate(new Date(now.getTime() - hrs * 60 * 60 * 1e3), true);
		}
		match = clean.match(config.TIME_KEYWORDS.DAYS);
		if (match) {
			if (!(/月|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/i.test(clean) || clean.includes(":"))) {
				const days = parseInt(match[1], 10);
				return formatDate(new Date(now.getTime() - days * 24 * 60 * 60 * 1e3), false);
			}
		}
		match = clean.match(config.TIME_KEYWORDS.WEEKS);
		if (match) {
			const weeks = parseInt(match[1], 10);
			return formatDate(new Date(now.getTime() - weeks * 7 * 24 * 60 * 60 * 1e3), false);
		}
		if (config.TIME_KEYWORDS.YESTERDAY.test(clean)) {
			const yesterday = new Date(now.getTime() - 1440 * 60 * 1e3);
			const timeMatch = clean.match(/(\d{1,2})[:.](\d{2})/);
			let hour = now.getHours();
			let minute = now.getMinutes();
			if (timeMatch) {
				hour = parseInt(timeMatch[1], 10);
				minute = parseInt(timeMatch[2], 10);
				hour = adjustHourForAmPm(hour, clean);
			}
			return formatDate(new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate(), hour, minute), true);
		}
		const monthsMap = getMonthsMap();
		match = clean.match(/^(?:(\d{1,2})\.?\s+(?:de\s+)?)?([a-z\u00C0-\u00FF\u0400-\u04FF\u0E00-\u0E7F\u0600-\u06FF.]+)(?:\s+(\d{1,2}))?(?:,?\s+(\d{4}))?(?:\s*(?:г\.?|года))?(?:\s*,\s*|\s+)?(?:at|um|à|a las|alle|de|lúc|เวลา|в|pukul|في|saat|om|kl\.?)?\s*(\d{1,2})[:.](\d{2})\s*(am|pm)?/i);
		if (match) {
			const dayFromStart = match[1];
			const monthName = match[2].toLowerCase();
			const dayFromMid = match[3];
			let year = match[4] ? parseInt(match[4], 10) : now.getFullYear();
			let hour = parseInt(match[5], 10);
			const minute = parseInt(match[6], 10);
			match[7] && match[7].toLowerCase();
			const month = monthsMap[monthName];
			const day = parseInt(dayFromStart || dayFromMid || "1", 10);
			if (month && day >= 1 && day <= 31) {
				if (year > 2400) year -= 543;
				hour = adjustHourForAmPm(hour, clean);
				return formatDate(new Date(year, month - 1, day, hour, minute), true);
			}
		}
		match = clean.match(/^(?:(\d{1,2})\.?\s+(?:de\s+)?)?([a-z\u00C0-\u00FF\u0400-\u04FF\u0E00-\u0E7F\u0600-\u06FF.]+)(?:\s+(\d{1,2}))?(?:,?\s+(\d{4}))?(?:\s*(?:г\.?|года))?$/i);
		if (match) {
			const dayFromStart = match[1];
			const monthName = match[2].toLowerCase();
			const dayFromMid = match[3];
			let year = match[4] ? parseInt(match[4], 10) : now.getFullYear();
			const month = monthsMap[monthName];
			const day = parseInt(dayFromStart || dayFromMid || "1", 10);
			if (month && day >= 1 && day <= 31) {
				if (year > 2400) year -= 543;
				return formatDate(new Date(year, month - 1, day, 0, 0), false);
			}
		}
		match = clean.match(/^(?:(\d{4})\s*[年년]\s*)?(\d{1,2})\s*[月월]\s*(\d{1,2})\s*[日일]\s*(?:(?:上午|下午|午前|午後|오전|오후|SA|CH|at)?\s*)?(\d{1,2}):(\d{2})\s*(am|pm)?/i);
		if (match) {
			const year = match[1] ? parseInt(match[1], 10) : now.getFullYear();
			const month = parseInt(match[2], 10);
			const day = parseInt(match[3], 10);
			let hour = parseInt(match[4], 10);
			const minute = parseInt(match[5], 10);
			hour = adjustHourForAmPm(hour, clean);
			return formatDate(new Date(year, month - 1, day, hour, minute), true);
		}
		match = clean.match(/^(?:(\d{4})\s*[年년]\s*)?(\d{1,2})\s*[月월]\s*(\d{1,2})\s*[日일]\s*$/i);
		if (match) {
			const year = match[1] ? parseInt(match[1], 10) : now.getFullYear();
			const month = parseInt(match[2], 10);
			const day = parseInt(match[3], 10);
			return formatDate(new Date(year, month - 1, day, 0, 0), false);
		}
		match = clean.match(/^(\d{1,2})\s+tháng\s+(\d{1,2})(?:,?\s+(\d{4}))?\s*(?:lúc\s+)?(\d{1,2})[:.](\d{2})/i);
		if (match) {
			const day = parseInt(match[1], 10);
			const month = parseInt(match[2], 10);
			const year = match[3] ? parseInt(match[3], 10) : now.getFullYear();
			let hour = parseInt(match[4], 10);
			const minute = parseInt(match[5], 10);
			if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
				hour = adjustHourForAmPm(hour, clean);
				return formatDate(new Date(year, month - 1, day, hour, minute), true);
			}
		}
		match = clean.match(/^(\d{1,2})\s+tháng\s+(\d{1,2})(?:,?\s+(\d{4}))?$/i);
		if (match) {
			const day = parseInt(match[1], 10);
			const month = parseInt(match[2], 10);
			const year = match[3] ? parseInt(match[3], 10) : now.getFullYear();
			if (month >= 1 && month <= 12 && day >= 1 && day <= 31) return formatDate(new Date(year, month - 1, day, 0, 0), false);
		}
		const parseable = clean.replace(/年|月/g, "/").replace(/日/g, "").replace(/星期[一二三四五六日]/g, "").replace(/at/i, "");
		const parsedTimestamp = Date.parse(parseable);
		if (!isNaN(parsedTimestamp)) {
			const hasTime = /[::]|am|pm|上午|下午/i.test(clean);
			return formatDate(new Date(parsedTimestamp), hasTime);
		}
		return clean;
	}
	function isPeopleHomeUrl(url) {
		if (!url) return false;
		try {
			const u = new URL(url, window.location.origin);
			if (!u.hostname.includes("facebook.com")) return false;
			const segments = u.pathname.split("/").filter(Boolean);
			if (segments[0] === "people" && segments.length >= 2) {
				const postKeywords = [
					"posts",
					"videos",
					"reels",
					"reel",
					"photos",
					"photos_by",
					"about",
					"friends",
					"groups"
				];
				return !segments.some((seg) => postKeywords.includes(seg.toLowerCase()));
			}
			return false;
		} catch (e) {
			return false;
		}
	}
	var SEE_MORE_KEYWORDS = [
		"see more",
		"read more",
		"顯示更多",
		"閱讀更多",
		"查看更多",
		"展開",
		"展开",
		"显示更多",
		"阅读更多",
		"查看更多",
		"xem thêm",
		"もっと見る",
		"さらに表示",
		"더 보기",
		"ver más",
		"leer más",
		"voir plus",
		"afficher plus",
		"mehr anzeigen",
		"weiterlesen",
		"ver mais",
		"outro",
		"vedi altro",
		"lihat selengkapnya",
		"ดูเพิ่มเติม",
		"عرض المزيد",
		"еще",
		"показать еще"
	];
	function isSeeMoreButton(btn) {
		if (btn.tagName === "A" || btn.getAttribute("role") !== "button") return false;
		if (!(btn.closest("div[data-ad-rendering-role=\"story_message\"], div[data-ad-comet-preview=\"message\"]") !== null)) return false;
		const text = (btn.textContent || "").trim();
		if (text.length === 0 || text.length > 25) return false;
		const lowercaseText = text.toLowerCase();
		if (SEE_MORE_KEYWORDS.some((kw) => lowercaseText.includes(kw))) return true;
		let hasEllipsis = false;
		let prev = btn.previousSibling;
		while (prev) {
			const prevText = prev.textContent || "";
			if (prevText.includes("…") || prevText.includes("...")) {
				hasEllipsis = true;
				break;
			}
			prev = prev.previousSibling;
		}
		if (!hasEllipsis && btn.parentElement) {
			const remainingText = (btn.parentElement.textContent || "").replace(text, "");
			if (remainingText.includes("…") || remainingText.includes("...")) hasEllipsis = true;
		}
		return hasEllipsis;
	}
	function extractPostIdFromUrl(url) {
		if (!url) return null;
		const match = url.match(/\/posts\/([a-zA-Z0-9_]+)/) || url.match(/\/events\/([a-zA-Z0-9_]+)/) || url.match(/fbid=([a-zA-Z0-9_]+)/) || url.match(/\/videos\/([a-zA-Z0-9_]+)/) || url.match(/\/reel\/([a-zA-Z0-9_]+)/) || url.match(/story_fbid=([a-zA-Z0-9_]+)/) || url.match(/[?&]v=([a-zA-Z0-9_]+)/);
		return match ? match[1] : null;
	}
	function isTimestampLink(link, tk) {
		if (link.closest("h2, h3, h4, [data-ad-rendering-role=\"profile_name\"]")) return false;
		if (link.querySelector("svg, img")) return false;
		const href = link.getAttribute("href") || link.href || "";
		if (href.includes("comment_id=") || href.includes("reply_comment_id=")) return false;
		const label = link.getAttribute("aria-label") || "";
		const text = (link.textContent || "").trim();
		const hasTimeReference = /\d/.test(label) || /[0-9dhmw]/.test(text) || /剛剛|小時|分鐘|天|週|年|分|秒|時間|日|週間|ago|just|yesterday/i.test(text) || tk && (tk.JUST_NOW.test(text) || tk.YESTERDAY.test(text) || tk.MINUTES.test(text) || tk.HOURS.test(text) || tk.DAYS.test(text) || tk.WEEKS.test(text));
		const hasPostReference = href.includes("/posts/") || href.includes("/videos/") || href.includes("/watch") || href.includes("/permalink/") || href.includes("/reel/") || href.includes("fbid=") || href.includes("story_fbid=") || href.includes("/events/") || href.includes("/people/") || /[?&]v=\d+/.test(href);
		return !!(hasTimeReference && hasPostReference);
	}
	var BookmarkStorage = class {
		static KEY = "bookmarked_posts";
		static getAll() {
			if (typeof GM_getValue === "undefined") return [];
			return GM_getValue(this.KEY, []);
		}
		static save(bookmarks) {
			if (typeof GM_setValue === "undefined") return;
			GM_setValue(this.KEY, bookmarks);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		}
	};
	function cleanDomText(el) {
		if (!el) return "";
		const clone = el.cloneNode(true);
		clone.querySelectorAll("svg, [role=\"img\"], i[data-visualcompletion=\"css-img\"]").forEach((node) => {
			node.remove();
		});
		return (clone.textContent || "").trim();
	}
	if (typeof window !== "undefined" && typeof document !== "undefined") try {
		updateTimeKeywordsRuntime();
		updateAmPmPatternsRuntime();
	} catch (e) {
		console.warn("[FB Login Wall Remover] Failed to initialize dynamic runtime time formatting keywords:", e);
	}
	var WorkerHandler = class {
		workerParam = "fpc_worker_task";
		async run() {
			const taskId = new URLSearchParams(window.location.search).get(this.workerParam);
			if (!taskId) return;
			document.body.style.display = "none";
			const permalinkFormat = GM_getValue("copier_permalinkFormat", "author_id");
			const extractId = (url) => url ? url.match(/(?:posts|videos|reel|v|story_fbid|multi_permalinks)(?:[=/].*?)(\d{15,})/)?.[1] || null : null;
			const extractUser = (url) => url ? url.match(/facebook\.com\/([a-zA-Z0-9.]+)\/(?:posts|videos|reels)\//)?.[1] || null : null;
			const formatPermalink = (info) => {
				if (!info?.postId) return null;
				if (permalinkFormat === "shortest") return `https://fb.com/${info.postId}`;
				if (permalinkFormat === "full" && info.canonicalUrl) try {
					const u = new URL(info.canonicalUrl);
					u.search = "";
					return u.href.replace(/\/$/, "");
				} catch (e) {}
				if (permalinkFormat === "username" && info.username && info.username !== "profile.php") return `https://www.facebook.com/${info.username}/posts/${info.postId}`;
				if (info.profileId) return `https://www.facebook.com/${info.profileId}/posts/${info.postId}`;
				return `https://www.facebook.com/posts/${info.postId}`;
			};
			const findNestedValue = (obj, key) => {
				if (obj && typeof obj === "object") {
					if (key in obj) return obj[key];
					return Object.values(obj).reduce((acc, v) => acc ?? findNestedValue(v, key), void 0);
				}
			};
			const getFromRelay = () => {
				for (const script of document.querySelectorAll("script[type=\"application/json\"]")) try {
					const id = findNestedValue(JSON.parse(script.textContent || ""), "storyID");
					if (id) {
						const ids = atob(id).match(/(\d+)/g);
						if (ids && ids.length >= 2) return {
							profileId: ids[0],
							postId: ids[1],
							method: "relay"
						};
					}
				} catch (e) {}
				return null;
			};
			const getFromHead = () => {
				const url = document.querySelector("link[rel=\"canonical\"]")?.href;
				if (!url) return null;
				return {
					postId: extractId(url),
					username: extractUser(url),
					canonicalUrl: url,
					method: "head"
				};
			};
			const getFromBody = () => {
				for (const script of document.querySelectorAll("script[type=\"application/json\"]")) try {
					const text = script.textContent || "";
					if (!text.includes("debug_info") && !text.includes("share_fbid")) continue;
					const d = JSON.parse(text);
					const dbg = findNestedValue(d, "debug_info");
					if (dbg) {
						const ids = atob(dbg).match(/(\d+)/g);
						if (ids && ids.length >= 2) return {
							profileId: ids[0],
							postId: ids[1],
							method: "body_debug"
						};
					}
					const fbid = findNestedValue(d, "share_fbid");
					if (fbid) return {
						postId: fbid,
						method: "body_fbid"
					};
				} catch (e) {}
				return null;
			};
			const collectInfo = () => {
				return [
					getFromRelay(),
					getFromHead(),
					getFromBody()
				].reduce((acc, info) => ({
					...info,
					...acc
				}), {});
			};
			const determinePermalink = () => {
				const info = collectInfo();
				return info.postId ? {
					url: formatPermalink(info),
					method: info.method || "unknown"
				} : { url: null };
			};
			const findWithRetry = async (timeout = 5e3) => {
				const start = Date.now();
				while (Date.now() - start < timeout) {
					const result = determinePermalink();
					if (result.url) return result;
					await delay(350);
				}
				return {
					url: null,
					method: "worker_timeout"
				};
			};
			let listenerId;
			const fallbackUrl = window.location.href.split("?")[0];
			try {
				const result = await findWithRetry();
				const permalink = result.url ?? fallbackUrl;
				const method = result.method || "fallback";
				GM_setValue(taskId, {
					permalink,
					method
				});
			} catch (error) {
				console.error("[FB Login Wall Remover] [Worker] Critical Error:", error);
				GM_setValue(taskId, {
					permalink: fallbackUrl,
					method: "error_exception"
				});
			} finally {
				const closeTimeout = setTimeout(() => {
					if (listenerId) GM_removeValueChangeListener(listenerId);
					window.close();
				}, 5e3);
				listenerId = GM_addValueChangeListener(taskId, (_name, _oldVal, newVal, remote) => {
					if (remote && newVal && newVal.resolved) {
						clearTimeout(closeTimeout);
						GM_removeValueChangeListener(listenerId);
						try {
							GM_deleteValue(taskId);
						} catch (e) {}
						window.close();
					}
				});
			}
		}
	};
	var ScrollInterceptor = class {
		app;
		constructor(app) {
			this.app = app;
		}
		init() {
			const originalAddEventListener = EventTarget.prototype.addEventListener;
			Object.defineProperty(EventTarget.prototype, "addEventListener", {
				configurable: true,
				enumerable: true,
				get: () => function(type, listener, options) {
					if (type === "scroll") {
						const path = window.location.pathname;
						if (!(path.includes("/about_profile_transparency") || path.includes("/ads/library/"))) {
							if (this !== window) return;
						}
					}
					return originalAddEventListener.call(this, type, listener, options);
				}
			});
		}
	};
	var HistoryInterceptor = class {
		app;
		constructor(app) {
			this.app = app;
		}
		init() {
			const originalPushState = history.pushState;
			history.pushState = function(...args) {
				originalPushState.apply(this, args);
				window.dispatchEvent(new Event("historyChange"));
			};
			const originalReplaceState = history.replaceState;
			history.replaceState = function(...args) {
				originalReplaceState.apply(this, args);
				window.dispatchEvent(new Event("historyChange"));
			};
		}
	};
	var translations = {
		en: {
			linkDetrackerEnabled: "Enable Link De-tracker (Anti-Ad/Tracking)",
			setting_batchCopyMode: "Batch Copy Output Mode",
			batchCopyMode_file: "Download as File",
			batchCopyMode_clipboard: "Copy to Clipboard",
			batchCopyMode_locked_csv: "CSV format requires Download mode.",
			batchCopy_file_success: "Exported to file successfully.",
			notificationDeadlock: "A login prompt was hidden, but the feed can no longer load new content.\n[Tip] To prevent this, open links in a new tab (Middle-Click). Please reload to continue.",
			notificationSettingsReload: "Some settings updated. Please reload.",
			resetSettings: "Reset Settings",
			resetSettingsConfirm: "Reset all settings to default?",
			notificationSettingsReset: "Settings reset.",
			menuResetSettings: "🚨 Reset All Settings",
			autoOpenMediaInNewTab: "Auto-open media in new tab",
			showDeadlockNotification: "Show deadlock notification",
			hideUselessElements: "Hide useless UI elements",
			hidePostStats: "Hide post stats (Likes, Comments)",
			autoUnmuteEnabled: "Auto unmute videos",
			setVolumeLabel: "Auto-unmute volume",
			postNumberingEnabled: "Display post numbers",
			expandContentEnabled: "Auto-expand content",
			errorRecoveryEnabled: "Auto-reload on error",
			transparencyButtonsEnabled: "Show Page Transparency shortcuts",
			screenshotEnabled: "Enable post screenshot button",
			setting_toolsPosition: "Post Action Buttons Position",
			toolsPositionInnerRight: "Inside Card (Top-Right Hover)",
			toolsPositionOuterRight: "Outside Card (Right-Side Vertical)",
			idRevealerEnabled: "Enable ID Revealer (Click Title)",
			idRevealerTooltip: "Click to reveal ID & Info",
			idRevealerLinkFormat: "ID Link Format",
			idFormatUserID: "User ID URL (facebook.com/id)",
			idFormatClassic: "Classic Profile URL (profile.php?id=)",
			idFormatUsername: "Username URL (Current URL)",
			id_copy_all: "Copy All Info",
			id_label_user: "User ID",
			id_label_page: "Page ID",
			id_label_meta: "Profile ID",
			id_label_group: "Group ID",
			profile_name_label: "Name",
			profile_url_label: "Profile URL",
			copy_success_generic: "{label} Copied",
			all_copied: "All Info Copied",
			searchPlaceholder: "Search...",
			searchButton: "Search",
			searchGroupContextual: "Search Current Page",
			searchGroupGlobal: "Search All of Facebook",
			searchScopePosts: "Posts",
			searchScopePhotos: "Photos",
			searchScopeVideos: "Videos",
			searchScopeReels: "Reels",
			searchScopePages: "Pages",
			searchScopePeople: "People",
			searchScopeGroups: "Groups",
			searchScopeGlobalVideos: "Videos",
			searchScopeGlobalPosts: "Posts",
			searchScopeEvents: "Events",
			searchScopeMarketplace: "Marketplace",
			searchTooltipPosts: "Search current page posts (or global if on Home)",
			searchTooltipPhotos: "Search photos on this page",
			searchTooltipVideos: "Search videos on this page",
			searchTooltipReels: "Search Reels using \"Page Name\" + \"Keyword\"",
			searchTooltipPages: "Search for Pages, Public Figures, or Organizations",
			searchTooltipPeople: "Search for People across Facebook",
			searchTooltipGroups: "Search for Groups across Facebook",
			searchTooltipGlobalPosts: "Search for Public Posts across Facebook",
			searchTooltipGlobalVideos: "Search all videos on Facebook Watch",
			searchTooltipEvents: "Search for Events",
			searchTooltipMarketplace: "Search Marketplace items",
			searchAllContextualTooltip: "Search {scope} on this page via Google",
			navigateToContextual: "Go to {scope} section",
			pinToolbar: "Pin",
			unpinToolbar: "Unpin",
			shortcutWatch: "Watch",
			shortcutEvents: "Events",
			shortcutMarketplace: "Marketplace",
			settingsTitle: "Settings",
			saveAndClose: "Save & Close",
			menuSettings: "⚙️ Settings",
			settingsColumnGeneral: "General",
			settingsColumnNavigation: "Navigation",
			settingsColumnTools: "Tools & Utilities",
			keyBinderPress: "Press any key...",
			keyBinderNone: "(None)",
			settingsDetailsMetadata: "Advanced Metadata Settings",
			setting_autoLoadEnabled: "Auto Load Content",
			keyboardNavEnabled: "Enable keyboard navigation",
			navHighlighterEnabled: "Highlight active post border",
			heatmapBorderEnabled: "Apply heat color to border",
			keyNavNextPrimary: "Next (J)",
			keyNavPrevPrimary: "Prev (K)",
			keyNavNextSecondary: "Next (Right)",
			keyNavPrevSecondary: "Prev (Left)",
			floatingNavEnabled: "Enable floating buttons",
			floatingNavPrevTooltip: "Previous Post (Right-Click: First)",
			floatingNavNextTooltip: "Next Post (Right-Click: Last)",
			timelineHeatmapEnabled: "Show Interaction Heatmap (Color Dots)",
			timelineNavEnabled: "Enable Timeline Navigator",
			scrollRestorerAlignment: "Scroll Restorer Alignment",
			navigationScrollAlignment: "Alignment",
			scrollAlignmentCenter: "Center",
			scrollAlignmentTop: "Top",
			scrollAlignmentBottom: "Bottom",
			enableSmoothScrolling: "Smooth Scroll",
			continuousNavInterval: "Nav Interval",
			wheelNavEnabled: "Wheel Nav",
			wheelNavModifier: "Modifier",
			modifierAlt: "Alt",
			modifierCtrl: "Ctrl",
			modifierShift: "Shift",
			modifierNone: "None",
			copier_enablePermalink: "Enable Permalink Icon",
			copier_enableCopyContent: "Enable Smart Copy Button",
			copier_fetchPermalinkSmart: "Permalink (Smart)",
			copier_fetchPermalinkDirect: "Permalink (Direct)",
			copier_copyContent: "Copy Post Content",
			copier_copyContentSuccess: "✅ Content Copied ({count} chars)",
			copier_copyContentFailed: "❌ Copy Failed",
			copier_screenshot: "Capture Post Screenshot",
			screenshot_success: "✅ Screenshot downloaded successfully",
			screenshot_failed: "❌ Failed to capture screenshot",
			copier_processing: "Processing...",
			copier_successPermalink: "✅ Copied",
			copier_failure: "❌ Failed",
			copier_notificationPermalinkCopied: "Permalink copied:\n{url}",
			copier_relation_recommends: "{author1} recommends {author2}",
			copier_notificationErrorGeneric: "Failed to fetch.",
			copier_notificationErrorNoSourceUrl: "No source URL.",
			copier_notificationErrorTimeout: "Fetch timed out.",
			copier_notificationContentNotFound: "❌ Content not found.",
			copier_menu_useSmartLink: "Use Smart Link (Async)",
			copier_menu_permalinkFormat: "Permalink Format",
			copier_format_full: "Full URL",
			copier_format_username: "Username+ID",
			copier_format_author_id: "AuthorID+ID",
			copier_format_shortest: "Shortest",
			copier_includeEmojis: "Include emojis",
			copier_expandHashtags: "Expand Hashtags to URL",
			copier_expand_mentions: "Expand Mentions to URL",
			autoLoader_batchSize: "Batch Count",
			tooltipAutoLoadStart: "Auto-Load",
			tooltipAutoLoadStop: "Stop",
			tooltipBatchCopy: "Batch Copy",
			batchCopy_includeHeader: "Include Header in Batch Copy",
			autoLoad_status_loading: "Loading... ({current}/{target})",
			autoLoad_status_retrying: "Retrying...",
			autoLoad_status_success: "Done.",
			autoLoad_status_stopped: "Stopped.",
			autoLoad_status_deadlock: "Deadlock.",
			autoLoad_mode_incremental: "Mode: Incremental (+{n})",
			autoLoad_mode_target: "Mode: Target Total ({n})",
			autoLoad_target_reached: "Target count ({n}) already reached.",
			autoLoad_tooltip_incremental: "Auto Load (+{n})\nRight-click: Switch to Target Mode",
			autoLoad_tooltip_target: "Auto Load (Target {n})\nRight-click: Switch to Incremental Mode",
			batchCopy_start: "Processing {count} posts...",
			batchCopy_success: "Copied {count} posts to clipboard! ({chars} chars)",
			batchCopy_download_success: "Downloaded {count} posts! ({chars} chars)",
			batchCopy_empty: "No posts available to copy.",
			batchCopy_mode_clipboard: "Batch Mode: Clipboard Copy",
			batchCopy_mode_download: "Batch Mode: Download as File",
			setting_batchExportFormat: "Batch Export Format",
			tooltip_batchExportFormat: "Select the file format for batch export (Auto Load > Copy).",
			exportFormat_text: "Plain Text (.txt)",
			exportFormat_json: "JSON (.json)",
			exportFormat_csv: "CSV (.csv)",
			floatingNav_showAutoLoad: "Show Auto-Load",
			floatingNav_showBatchCopy: "Show Batch Copy",
			floatingNav_opacity: "Semi-Transparent when idle",
			copy_includeMetadata: "Include Metadata",
			copy_meta_url: "Include Link (Top)",
			copy_meta_order: "Include Order [#]",
			copy_meta_author_name: "Include Author Name",
			copy_meta_author_link: "Include Author Profile Link",
			copy_meta_date: "Include Date",
			copy_meta_absolute_date: "Use Absolute Date Format",
			copy_meta_stats_total: "Include Total Count (1.9K)",
			copy_meta_stats_detailed: "Include Details (👍❤️)",
			copy_meta_link_preview: "Include Link Preview",
			copy_meta_image_count: "Include Image Count",
			image_count_label: "Images",
			copy_meta_video_duration: "Include Video/Reel Duration",
			label_reel: "Reel",
			label_video: "Video",
			stats_label_like: "Like",
			stats_label_comment: "Comment",
			stats_label_share: "Share",
			stats_label_reaction: "Reactions",
			preview_label_title: "Title",
			preview_label_source: "Source",
			preview_label_desc: "Desc",
			preview_label_link: "Link",
			copier_shared_post_label: "Shared Post",
			label_no_text_content: "[No Text Content]",
			label_videos_plural: "Videos",
			tooltipAds: "Ads Library",
			tooltipTransparency: "Transparency",
			notificationReelSearchError: "Page name not found",
			excludeTranslation: "Exclude localized translations in Google Search (may cause empty results due to Google bugs)",
			appLanguage: "Language",
			langAuto: "Auto Detect",
			langEN: "English",
			langZH: "繁體中文 (zh-TW)",
			langJA: "日本語 (ja)",
			enableBookmarksLabel: "Enable Local Bookmarks (Posts & Pages)",
			bookmarkPositionLabel: "Bookmarks & Sidebar Position",
			bookmarkPositionLeft: "Left Side (Default)",
			bookmarkPositionRight: "Right Side",
			settingsColumnBookmarks: "Bookmarks",
			bookmark_post_added: "Post added to bookmarks.",
			bookmark_post_removed: "Post removed from bookmarks.",
			bookmark_page_added: "Page added to bookmarks.",
			bookmark_page_removed: "Page removed from bookmarks.",
			bookmark_tab_posts: "Posts",
			bookmark_tab_pages: "Pages & Groups",
			bookmark_empty: "No bookmarks yet.",
			bookmark_clear_btn: "Clear All Bookmarks",
			bookmark_export_btn: "Export Bookmarks (JSON)",
			bookmark_sort_label: "Sort",
			bookmark_sort_saved_at: "Date Bookmarked (Newest)",
			bookmark_sort_publish_time: "Date Published (Newest)",
			bookmark_sort_last_visited: "Last Visited (Newest)",
			bookmark_sort_name: "Name (A-Z / Stroke)",
			bookmark_confirm_clear: "Are you sure you want to clear all bookmarks? This cannot be undone.",
			bookmark_action_title: "Bookmark Post",
			bookmark_page_action_title: "Bookmark current page/group",
			bookmark_page_action_remove_title: "Remove page bookmark",
			bookmark_hover_preview_hint: "Hover or click a post to view full content",
			bookmark_open_original_post: "Open original post",
			bookmark_manage_btn: "Manage Bookmarks...",
			bookmark_view_full: "Read Full Post",
			bookmark_collapse: "Collapse",
			bookmark_menu_title: "My Bookmarks",
			bookmark_menu_posts: "Recent Bookmarked Posts",
			bookmark_menu_pages: "Recent Bookmarked Pages",
			bookmark_copy_title: "Copy link",
			bookmark_copy_content_title: "Copy post content",
			bookmark_copied_notification: "Link copied to clipboard.",
			bookmark_content_copied_notification: "Post content copied to clipboard.",
			bookmark_delete_confirm_title: "Click again to confirm delete",
			bookmark_delete_title: "Delete",
			bookmark_last_visited: "Last visited: {time}",
			bookmark_last_visited_never: "Last visited: Never",
			bookmark_search_placeholder: "Search bookmarks or tags...",
			bookmark_folder_label: "Folder",
			bookmark_folder_all: "All",
			bookmark_folder_root: "Uncategorized",
			bookmark_add_folder: "New Folder",
			bookmark_delete_folder_confirm: "Are you sure you want to delete this folder? Bookmarks inside will be moved to Uncategorized.",
			bookmark_tags_label: "Tags",
			bookmark_add_tag_btn: "Add Tag",
			bookmark_add_tag_placeholder: "Type tag and press Enter...",
			bookmark_move_to_folder: "Move to Folder",
			setting_screenshotScale: "Screenshot Resolution Scale",
			scale_1x: "1x (Standard)",
			scale_2x: "2x (High Quality)",
			scale_3x: "3x (Ultra High)",
			setting_screenshotExcludeComments: "Exclude Comments in Screenshot",
			setting_screenshotFormat: "Screenshot Output Format",
			format_png: "PNG (Lossless)",
			format_jpeg: "JPEG (Compressed)",
			setting_screenshotEmbedLink: "Embed Permalink in Screenshot",
			following_copy_button_title: "Copy Following List",
			following_copy_success: "Copied {count} following items!",
			following_copy_failed: "Failed to extract following list",
			timelineSortTooltip: "Switch Sort Mode",
			batchCopy_failed: "Batch export failed.",
			operation_failed: "Operation failed.",
			batchCopy_summary_title: "【 BATCH EXPORT SUMMARY 】",
			batchCopy_summary_source: "Source",
			batchCopy_summary_url: "URL",
			batchCopy_summary_time: "Time",
			batchCopy_summary_count: "Count",
			batchCopy_summary_posts: "Posts"
		},
		"zh-TW": {
			linkDetrackerEnabled: "啟用連結去追蹤化 (移除廣告參數)",
			setting_batchCopyMode: "批次複製輸出模式",
			batchCopyMode_file: "下載為檔案",
			batchCopyMode_clipboard: "複製到剪貼簿",
			batchCopyMode_locked_csv: "CSV 格式僅支援下載模式。",
			batchCopy_file_success: "已成功匯出檔案。",
			notificationDeadlock: "登入提示已被隱藏,但動態無法再載入新內容。\n[提示] 為防止此情況,請在新分頁中開啟連結 (中鍵點擊)。請重新整理以繼續。",
			notificationSettingsReload: "部分設定已更新,請重新整理頁面以完全生效。",
			resetSettings: "重設設定",
			resetSettingsConfirm: "您確定要將所有設定重設為預設值嗎?此操作無法復原。",
			notificationSettingsReset: "設定已重設為預設值,部分變更可能需要重新整理頁面才能生效。",
			menuResetSettings: "🚨 重設所有設定",
			autoOpenMediaInNewTab: "自動在新分頁開啟媒體 (防鎖定)",
			showDeadlockNotification: "顯示頁面鎖定通知",
			hideUselessElements: "隱藏對訪客無用的介面元素",
			hidePostStats: "隱藏貼文統計資料 (讚數、留言數)",
			autoUnmuteEnabled: "自動取消影片靜音",
			setVolumeLabel: "自動音量大小",
			postNumberingEnabled: "在動態消息上顯示貼文順序",
			expandContentEnabled: "自動展開貼文內容 (查看更多)",
			errorRecoveryEnabled: "錯誤頁面自動恢復 (按鈕偵測)",
			transparencyButtonsEnabled: "顯示粉絲專頁資訊透明度捷徑按鈕 (左下角)",
			screenshotEnabled: "啟用貼文卡片截圖按鈕",
			setting_toolsPosition: "貼文工具按鈕組顯示位置",
			toolsPositionInnerRight: "貼文卡片內 (右上角懸浮)",
			toolsPositionOuterRight: "貼文卡片外 (右側垂直懸浮)",
			idRevealerEnabled: "啟用 ID 顯示器 (點擊標題)",
			idRevealerTooltip: "點擊以顯示 Profile ID 與資訊",
			idRevealerLinkFormat: "ID 連結格式",
			idFormatUserID: "User ID 格式 (facebook.com/id)",
			idFormatClassic: "經典格式 (profile.php?id=)",
			idFormatUsername: "使用者名稱 (當前網址)",
			id_copy_all: "複製全部資訊",
			id_label_user: "User ID",
			id_label_page: "Page ID",
			id_label_meta: "Profile ID",
			id_label_group: "社團 ID",
			profile_name_label: "專頁名稱",
			profile_url_label: "Profile URL",
			copy_success_generic: "已複製 {label}",
			all_copied: "全部資訊已複製",
			searchPlaceholder: "搜尋...",
			searchButton: "搜尋",
			searchGroupContextual: "搜尋當前頁面",
			searchGroupGlobal: "搜尋整個 Facebook",
			searchScopePosts: "貼文",
			searchScopePhotos: "相片",
			searchScopeVideos: "影片",
			searchScopeReels: "連續短片",
			searchScopePages: "專頁",
			searchScopePeople: "人物",
			searchScopeGroups: "社團",
			searchScopeGlobalVideos: "影片",
			searchScopeGlobalPosts: "貼文",
			searchScopeEvents: "活動",
			searchScopeMarketplace: "市集",
			searchTooltipPosts: "搜尋目前頁面的貼文 (若在首頁則搜尋整個 Facebook)。",
			searchTooltipPhotos: "搜尋目前頁面的相片。",
			searchTooltipVideos: "搜尋目前頁面的影片。",
			searchTooltipReels: "使用「專頁名稱」+「關鍵字」來搜尋整個 Facebook 的連續短片。",
			searchTooltipPages: "在整個 Facebook 中搜尋粉絲專頁、公眾人物或組織。",
			searchTooltipPeople: "在整個 Facebook 中搜尋個人檔案。",
			searchTooltipGroups: "在整個 Facebook 中搜尋社團。",
			searchTooltipGlobalPosts: "在整個 Facebook 中搜尋公開貼文。",
			searchTooltipGlobalVideos: "使用 Facebook Watch 內建功能搜尋所有影片。",
			searchTooltipEvents: "使用 Facebook 內建功能搜尋所有活動。",
			searchTooltipMarketplace: "使用 Facebook Marketplace 內建功能搜尋所有商品。",
			searchAllContextualTooltip: "使用 Google 搜尋此頁面的所有 {scope}",
			navigateToContextual: "前往 {scope} 區塊",
			pinToolbar: "釘選工具列",
			unpinToolbar: "取消釘選工具列",
			shortcutWatch: "前往 Watch 影片",
			shortcutEvents: "前往 活動",
			shortcutMarketplace: "前往 Marketplace 市集",
			settingsTitle: "設定",
			saveAndClose: "儲存並關閉",
			menuSettings: "⚙️ 設定",
			settingsColumnGeneral: "一般設定",
			settingsColumnNavigation: "導覽設定",
			settingsColumnTools: "工具與其他設定",
			keyBinderPress: "請按任意鍵...",
			keyBinderNone: "(無)",
			settingsDetailsMetadata: "進階中繼資料設定",
			setting_autoLoadEnabled: "自動載入內容",
			keyboardNavEnabled: "啟用鍵盤導覽 (J/K)",
			navHighlighterEnabled: "高亮顯示當前貼文邊框",
			heatmapBorderEnabled: "使用互動熱度顏色標示貼文邊框",
			keyNavNextPrimary: "下一篇 (J)",
			keyNavPrevPrimary: "上一篇 (主要按鍵)",
			keyNavNextSecondary: "下一篇 (次要按鍵)",
			keyNavPrevSecondary: "上一篇 (次要按鍵)",
			floatingNavEnabled: "啟用浮動導覽按鈕",
			floatingNavPrevTooltip: "上一篇貼文 (右鍵:第一篇)",
			floatingNavNextTooltip: "下一篇貼文 (右鍵:最後一篇)",
			timelineHeatmapEnabled: "顯示互動熱點圖 (彩色圓點)",
			timelineNavEnabled: "啟用時間軸導覽 (右側捷徑)",
			scrollRestorerAlignment: "瀏覽位置復原對齊",
			navigationScrollAlignment: "導覽滾動對齊",
			scrollAlignmentCenter: "置中",
			scrollAlignmentTop: "貼齊頂部",
			enableSmoothScrolling: "啟用平滑捲動",
			continuousNavInterval: "連續導覽間隔時間",
			wheelNavEnabled: "啟用滑鼠滾輪導覽",
			wheelNavModifier: "滾輪導覽修飾鍵",
			modifierAlt: "Alt",
			modifierCtrl: "Ctrl",
			modifierShift: "Shift",
			modifierNone: "無 (取代頁面捲動)",
			copier_enablePermalink: "啟用 永久連結按鈕 (僅圖示)",
			copier_enableCopyContent: "啟用 複製內容按鈕 (智慧)",
			copier_fetchPermalinkSmart: "永久連結 (智慧)",
			copier_fetchPermalinkDirect: "永久連結 (直接)",
			copier_copyContent: "複製貼文內容",
			copier_copyContentSuccess: "✅ 內容已複製 ({count} 字)",
			copier_copyContentFailed: "❌ 複製失敗",
			copier_screenshot: "擷取貼文螢幕截圖",
			screenshot_success: "✅ 貼文截圖已成功下載",
			screenshot_failed: "❌ 擷取貼文截圖失敗",
			copier_processing: "處理中...",
			copier_successPermalink: "✅ 已複製",
			copier_failure: "❌ 失敗",
			copier_notificationPermalinkCopied: "永久連結已複製:\n{url}",
			copier_relation_recommends: "{author1} 推薦了 {author2}",
			copier_notificationErrorGeneric: "獲取永久連結失敗。",
			copier_notificationErrorNoSourceUrl: "失敗:找不到來源網址。",
			copier_notificationErrorTimeout: "失敗:背景處理逾時。",
			copier_notificationContentNotFound: "❌ 找不到內容區塊。",
			copier_menu_useSmartLink: "複製內容時使用智慧連結 (需等待)",
			copier_menu_permalinkFormat: "永久連結格式",
			copier_format_full: "完整網址 (含 Slug)",
			copier_format_username: "使用者名稱 + 貼文 ID",
			copier_format_author_id: "作者 ID + 貼文 ID (最可靠)",
			copier_format_shortest: "最短連結 (fb.com, 相容性較差)",
			copier_includeEmojis: "複製內容包含表情符號",
			copier_expandHashtags: "將 Hashtag 展開為網址",
			copier_expand_mentions: "將提及對象展開為網址",
			autoLoader_batchSize: "自動載入批次數量",
			tooltipAutoLoadStart: "自動載入貼文",
			tooltipAutoLoadStop: "停止載入",
			tooltipBatchCopy: "批次複製所有已載入貼文 (右鍵切換模式)",
			batchCopy_includeHeader: "批次複製包含頁首資訊",
			autoLoad_status_loading: "載入中... ({current}/{target})",
			autoLoad_status_retrying: "重試中... ({count}/{max})",
			autoLoad_status_success: "自動載入完成。",
			autoLoad_status_stopped: "使用者手動停止。",
			autoLoad_status_deadlock: "偵測到阻擋,載入已停止。",
			autoLoad_mode_incremental: "模式:遞增載入 (+{n})",
			autoLoad_mode_target: "模式:目標總數 ({n})",
			autoLoad_target_reached: "已達到目標數量 ({n})。",
			autoLoad_tooltip_incremental: "自動載入 (+{n})\n右鍵:切換至目標模式",
			autoLoad_tooltip_target: "自動載入 (達到 {n})\n右鍵:切換至遞增模式",
			setting_batchExportFormat: "批次匯出格式",
			tooltip_batchExportFormat: "選擇批次匯出(自動載入 > 複製)時的檔案格式。",
			batchCopy_start: "正在處理 {count} 篇貼文...",
			batchCopy_success: "已複製 {count} 篇貼文到剪貼簿!({chars} 字)",
			batchCopy_download_success: "已下載 {count} 篇貼文!(共 {chars} 字)",
			batchCopy_empty: "沒有可複製的貼文。",
			batchCopy_mode_clipboard: "批次模式:複製到剪貼簿",
			batchCopy_mode_download: "批次模式:下載為檔案",
			exportFormat_text: "純文字 (.txt)",
			exportFormat_json: "JSON (.json)",
			exportFormat_csv: "CSV (.csv)",
			floatingNav_showAutoLoad: "顯示 自動載入按鈕",
			floatingNav_showBatchCopy: "顯示 批次複製按鈕",
			floatingNav_opacity: "閒置時半透明 (降低干擾)",
			copy_includeMetadata: "複製內容包含中繼資料",
			copy_meta_url: "包含貼文連結 (置頂)",
			copy_meta_order: "包含貼文順序 [#xx]",
			copy_meta_author_name: "包含發文者名稱",
			copy_meta_author_link: "包含發文者網址",
			copy_meta_date: "包含發文時間",
			copy_meta_absolute_date: "使用絕對時間格式",
			copy_meta_stats_total: "包含總數 (1.9K 心情)",
			copy_meta_stats_detailed: "包含詳細心情 (👍❤️)",
			copy_meta_link_preview: "包含連結預覽資訊 (標題/來源/摘要)",
			copy_meta_image_count: "包含圖片數量統計",
			image_count_label: "圖片",
			copy_meta_video_duration: "包含影片/Reels 時長",
			label_reel: "Reel",
			label_video: "影片",
			stats_label_like: "讚",
			stats_label_comment: "留言",
			stats_label_share: "分享",
			stats_label_reaction: "心情",
			preview_label_title: "標題",
			preview_label_source: "來源",
			preview_label_desc: "摘要",
			preview_label_link: "連結",
			copier_shared_post_label: "分享的貼文",
			label_no_text_content: "[無文字內容]",
			label_videos_plural: "部影片",
			timelineSortTooltip: "切換排序模式",
			scrollAlignmentBottom: "靠下",
			tooltipAds: "前往 廣告檔案庫 (關於)",
			tooltipTransparency: "查看 粉絲專頁資訊透明度",
			notificationReelSearchError: "無法取得目前頁面名稱以進行連續短片搜尋。",
			excludeTranslation: "在 Google 搜尋中排除翻譯語系網頁 (最近的 Google 搜尋更新可能會導致搜尋結果無效)",
			appLanguage: "語言 (Language)",
			langAuto: "自動偵測",
			langEN: "English",
			langZH: "繁體中文 (zh-TW)",
			langJA: "日本語 (ja)",
			enableBookmarksLabel: "啟用本機書籤 (支援貼文與專頁)",
			bookmarkPositionLabel: "我的書籤與側邊欄位置",
			bookmarkPositionLeft: "左側 (預設)",
			bookmarkPositionRight: "右側",
			settingsColumnBookmarks: "我的書籤",
			bookmark_post_added: "已將貼文加入書籤。",
			bookmark_post_removed: "已將此貼文從書籤移除。",
			bookmark_page_added: "已將專頁加入書籤。",
			bookmark_page_removed: "已將專頁從書籤移除。",
			bookmark_tab_posts: "書籤貼文",
			bookmark_tab_pages: "書籤專頁與社團",
			bookmark_empty: "目前沒有書籤內容。",
			bookmark_clear_btn: "清除所有書籤",
			bookmark_export_btn: "匯出書籤資料 (JSON)",
			bookmark_sort_label: "排序",
			bookmark_sort_saved_at: "收藏時間 (新至舊)",
			bookmark_sort_publish_time: "貼文發佈時間 (新至舊)",
			bookmark_sort_last_visited: "上次瀏覽 (新至舊)",
			bookmark_sort_name: "名稱排序 (A-Z / 筆劃)",
			bookmark_confirm_clear: "您確定要清除所有書籤嗎?此操作無法復原。",
			bookmark_action_title: "將此貼文加入書籤",
			bookmark_page_action_title: "將此專頁或社團加入書籤",
			bookmark_page_action_remove_title: "將此專頁或社團從書籤移除",
			bookmark_hover_preview_hint: "將滑鼠懸停或點擊貼文以查看完整內容",
			bookmark_open_original_post: "開啟原始貼文",
			bookmark_menu_title: "我的書籤",
			bookmark_menu_pages: "書籤專頁與社團",
			bookmark_menu_posts: "書籤貼文",
			bookmark_manage_btn: "管理書籤內容...",
			bookmark_copy_title: "複製連結",
			bookmark_copy_content_title: "複製貼文內容",
			bookmark_copied_notification: "連結已複製到剪貼簿。",
			bookmark_content_copied_notification: "貼文內容已複製到剪貼簿。",
			bookmark_delete_confirm_title: "再次點選以確認刪除",
			bookmark_delete_title: "刪除",
			bookmark_last_visited: "上次瀏覽:{time}",
			bookmark_last_visited_never: "上次瀏覽:從未",
			bookmark_search_placeholder: "搜尋書籤內容或標籤...",
			bookmark_folder_label: "分類資料夾",
			bookmark_folder_all: "全部",
			bookmark_folder_root: "未分類",
			bookmark_add_folder: "新增資料夾",
			bookmark_delete_folder_confirm: "您確定要刪除此資料夾嗎?資料夾內的書籤將移至未分類。",
			bookmark_tags_label: "標籤",
			bookmark_add_tag_btn: "新增標籤",
			bookmark_add_tag_placeholder: "輸入標籤名稱後按 Enter...",
			bookmark_move_to_folder: "移動至資料夾",
			setting_screenshotScale: "截圖解析度倍率",
			scale_1x: "1x (標準)",
			scale_2x: "2x (高畫質)",
			scale_3x: "3x (超高畫質)",
			setting_screenshotExcludeComments: "截圖排除留言區",
			setting_screenshotFormat: "截圖輸出格式",
			format_png: "PNG (無損)",
			format_jpeg: "JPEG (高壓縮比)",
			setting_screenshotEmbedLink: "嵌入永久連結浮水印",
			following_copy_button_title: "複製追蹤名單",
			following_copy_success: "已複製 {count} 個追蹤項目!",
			following_copy_failed: "提取追蹤名單失敗",
			bookmark_collapse: "收合貼文",
			bookmark_view_full: "閱讀完整貼文",
			batchCopy_failed: "批次匯出失敗。",
			operation_failed: "操作失敗。",
			batchCopy_summary_title: "【 批次匯出摘要 】",
			batchCopy_summary_source: "來源",
			batchCopy_summary_url: "網址",
			batchCopy_summary_time: "時間",
			batchCopy_summary_count: "數量",
			batchCopy_summary_posts: "篇貼文"
		},
		ja: {
			linkDetrackerEnabled: "リンクの追跡防止を有効にする",
			notificationDeadlock: "ログインプロンプトが非表示になりましたが、フィードは新しいコンテンツを読み込めなくなりました。\n【ヒント】フィードがロックされないように、新しいタブでリンクを開く(中央クリック)習慣を付けてください。閲覧を続けるには、このページをリロードしてください。",
			notificationSettingsReload: "一部の設定が更新されました。完全に有効にするには、ページをリロードしてください。",
			resetSettings: "設定をリセット",
			resetSettingsConfirm: "すべての設定をデフォルトにリセットしますか?この操作は元に戻せません。",
			notificationSettingsReset: "設定がデフォルトにリセットされました。一部の変更は、ページをリロードすると有効になります。",
			menuResetSettings: "🚨 全ての設定をリセット",
			autoOpenMediaInNewTab: "メディアを新しいタブで開く (デッドロック防止)",
			showDeadlockNotification: "デッドロック通知を表示",
			hideUselessElements: "不要なUI要素を非表示にする(ゲスト用)",
			hidePostStats: "投稿の統計データを非表示 (いいね!、コメント数)",
			autoUnmuteEnabled: "動画のミュートを自動解除",
			setVolumeLabel: "自動音量",
			postNumberingEnabled: "フィードに投稿順序番号を表示する",
			expandContentEnabled: "投稿の内容を自動的に展開 (さらに表示)",
			errorRecoveryEnabled: "エラーページ自動回復 (ボタン検出)",
			transparencyButtonsEnabled: "ページの透明性ショートカットを表示 (左下)",
			screenshotEnabled: "投稿のスクリーンショットボタンを有効にする",
			setting_toolsPosition: "投稿アクションボタンの表示位置",
			toolsPositionInnerRight: "カード内 (右上ホバー)",
			toolsPositionOuterRight: "カード外 (右側垂直ホバー)",
			idRevealerEnabled: "ID表示機能を有効にする(タイトルをクリック)",
			idRevealerTooltip: "クリックしてプロフィールIDと情報を表示",
			idRevealerLinkFormat: "IDリンク形式",
			idFormatUserID: "User ID形式 (facebook.com/id)",
			idFormatClassic: "クラシック (profile.php?id=)",
			idFormatUsername: "ユーザー名 (現在のURL)",
			id_copy_all: "すべての情報をコピー",
			id_label_user: "User ID",
			id_label_page: "Page ID",
			id_label_meta: "Profile ID",
			id_label_group: "グループ ID",
			profile_name_label: "プロフィール名",
			profile_url_label: "Profile URL",
			copy_success_generic: "{label}をコピーしました",
			all_copied: "すべての情報をコピーしました",
			searchPlaceholder: "検索...",
			searchButton: "検索",
			searchGroupContextual: "現在のページを検索",
			searchGroupGlobal: "Facebook全体を検索",
			searchScopePosts: "投稿",
			searchScopePhotos: "写真",
			searchScopeVideos: "動画",
			searchScopeReels: "リール",
			searchScopePages: "ページ",
			searchScopePeople: "人物",
			searchScopeGroups: "グループ",
			searchScopeGlobalVideos: "動画",
			searchScopeGlobalPosts: "投稿",
			searchScopeEvents: "イベント",
			searchScopeMarketplace: "マーケット",
			searchTooltipPosts: "現在のページの投稿を検索(ホーム画面の場合は全体)",
			searchTooltipPhotos: "現在のページの写真内を検索",
			searchTooltipVideos: "現在のページの動画内を検索",
			searchTooltipReels: "「ページ名」+「キーワード」でリールを検索",
			searchTooltipPages: "Facebook全体でページ・著名人・組織を検索",
			searchTooltipPeople: "Facebook全体で人物を検索",
			searchTooltipGroups: "Facebook全体でグループを検索",
			searchTooltipGlobalPosts: "Facebook全体で公開投稿を検索",
			searchTooltipGlobalVideos: "Facebook Watch機能で動画を検索",
			searchTooltipEvents: "イベントを検索",
			searchTooltipMarketplace: "Marketplaceで商品を検索",
			searchAllContextualTooltip: "Googleを使ってこのページの {scope} を検索",
			navigateToContextual: "{scope} セクションへ移動",
			pinToolbar: "固定",
			unpinToolbar: "固定解除",
			shortcutWatch: "Watchへ",
			shortcutEvents: "イベントへ",
			shortcutMarketplace: "マーケットへ",
			settingsTitle: "設定",
			saveAndClose: "保存して閉じる",
			menuSettings: "⚙️ 設定",
			settingsColumnGeneral: "一般",
			settingsColumnNavigation: "ナビ",
			settingsColumnTools: "ツールとユーティリティ",
			keyBinderPress: "キーを押してください...",
			keyBinderNone: "(なし)",
			settingsDetailsMetadata: "高度なメタデータ設定",
			setting_autoLoadEnabled: "コンテンツの自動読み込み",
			setting_batchCopyMode: "一括コピー出力モード",
			batchCopyMode_file: "ファイルとしてダウンロード",
			batchCopyMode_clipboard: "クリップボードにコピー",
			batchCopyMode_locked_csv: "CSV形式はダウンロードモードのみ対応しています。",
			batchCopy_file_success: "ファイルへのエクスポートが完了しました。",
			keyboardNavEnabled: "キーボードナビゲーションを有効にする",
			navHighlighterEnabled: "アクティブな投稿を強調表示 (枠線)",
			heatmapBorderEnabled: "ヒートマップカラーを枠線に適用",
			keyNavNextPrimary: "次の投稿 (J)",
			keyNavPrevPrimary: "前の投稿 (K)",
			keyNavNextSecondary: "次の投稿 (→)",
			keyNavPrevSecondary: "前の投稿 (←)",
			floatingNavEnabled: "フローティングボタンを有効にする",
			floatingNavPrevTooltip: "前の投稿 (右クリック:最初へ)",
			floatingNavNextTooltip: "次の投稿 (右クリック:最後へ)",
			timelineHeatmapEnabled: "インタラクションヒートマップを表示",
			timelineSortTooltip: "ソートモードを切り替える",
			scrollRestorerAlignment: "スクロール復元位置",
			scrollAlignmentBottom: "下部",
			timelineNavEnabled: "タイムラインナビゲーションを有効にする",
			navigationScrollAlignment: "スクロール位置",
			scrollAlignmentCenter: "中央",
			scrollAlignmentTop: "上部",
			enableSmoothScrolling: "スムーズスクロール",
			continuousNavInterval: "連続間隔",
			wheelNavEnabled: "ホイールナビ",
			wheelNavModifier: "修飾キー",
			modifierAlt: "Alt",
			modifierCtrl: "Ctrl",
			modifierShift: "Shift",
			modifierNone: "なし",
			copier_enablePermalink: "固定リンクボタンを有効にする (アイコンのみ)",
			copier_enableCopyContent: "内容コピーボタンを有効にする (スマート)",
			copier_fetchPermalinkSmart: "固定リンク (スマート)",
			copier_fetchPermalinkDirect: "固定リンク (直接)",
			copier_copyContent: "投稿内容をコピー",
			copier_copyContentSuccess: "✅ コピーしました ({count} 文字)",
			copier_copyContentFailed: "❌ 失敗しました",
			copier_screenshot: "スクリーンショットをキャプチャ",
			screenshot_success: "✅ スクリーンショットが正常にダウンロードされました",
			screenshot_failed: "❌ スクリーンショットのキャプチャに失敗しました",
			copier_processing: "処理中...",
			copier_successPermalink: "✅ コピーしました",
			copier_failure: "❌ 失敗",
			copier_notificationPermalinkCopied: "固定リンクをクリップボードにコピーしました:\n{url}",
			copier_relation_recommends: "{author1} が {author2} をおすすめしています",
			copier_notificationErrorGeneric: "固定リンクの取得に失敗しました。",
			copier_notificationErrorNoSourceUrl: "失敗:ソースURLが見つかりません。",
			copier_notificationErrorTimeout: "失敗:取得タイムアウト。",
			copier_notificationContentNotFound: "❌ コンテンツが見つかりませんでした。",
			copier_menu_useSmartLink: "コンテンツコピー時にスマートリンクを使用 (待機あり)",
			copier_menu_permalinkFormat: "固定リンク形式",
			copier_format_full: "完全なURL",
			copier_format_username: "ユーザー名+ID",
			copier_format_author_id: "作者ID+ID (推奨)",
			copier_format_shortest: "短縮 (fb.com)",
			copier_includeEmojis: "絵文字を含める",
			copier_expandHashtags: "ハッシュタグをURLに展開",
			copier_expand_mentions: "メンションをURLに展開",
			autoLoader_batchSize: "自動読み込みバッチ数",
			tooltipAutoLoadStart: "投稿を自動読み込み",
			tooltipAutoLoadStop: "読み込み停止",
			tooltipBatchCopy: "読み込まれたすべての投稿を一括コピー (右クリックでモード切替)",
			batchCopy_includeHeader: "一括コピーにヘッダーを含める",
			autoLoad_status_loading: "読み込み中... ({current}/{target})",
			autoLoad_status_retrying: "再試行中... ({count}/{max})",
			autoLoad_status_success: "自動読み込み完了。",
			autoLoad_status_stopped: "ユーザーにより停止。",
			autoLoad_status_deadlock: "ブロックを検出。停止します。",
			autoLoad_mode_incremental: "モード:追加読み込み (+{n})",
			autoLoad_mode_target: "モード:目標到達まで ({n})",
			autoLoad_target_reached: "目標件数 ({n}) に到達済みです。",
			autoLoad_tooltip_incremental: "自動読み込み (+{n})\n右クリック:目標モードへ切替",
			autoLoad_tooltip_target: "自動読み込み (目標 {n})\n右クリック:増分モードへ切替",
			setting_batchExportFormat: "一括エクスポート形式",
			tooltip_batchExportFormat: "一括エクスポート(自動ロード > コピー)のファイル形式を選択します。",
			batchCopy_start: "{count} 件の投稿を処理中...",
			batchCopy_success: "{count} 件の投稿をクリップボードにコピーしました! ({chars} 文字)",
			batchCopy_download_success: "{count}件の投稿をダウンロードしました!({chars}文字)",
			batchCopy_empty: "コピーできる投稿がありません。",
			batchCopy_mode_clipboard: "バッチモード:クリップボードにコピー",
			batchCopy_mode_download: "バッチモード:ファイルとして保存",
			exportFormat_text: "プレーンテキスト (.txt)",
			exportFormat_json: "JSON (.json)",
			exportFormat_csv: "CSV (.csv)",
			floatingNav_showAutoLoad: "自動読み込みボタンを表示",
			floatingNav_showBatchCopy: "一括コピーボタンを表示",
			floatingNav_opacity: "待機時に半透明にする",
			copy_includeMetadata: "メタデータを含める (作成者、日付、リンク...)",
			copy_meta_url: "投稿リンクを含める (上部)",
			copy_meta_order: "投稿順序 [#xx] を含める (一括コピーのみ)",
			copy_meta_author_name: "作成者名を含める",
			copy_meta_author_link: "投稿者リンクを含める",
			copy_meta_date: "日付/時間を含める",
			copy_meta_absolute_date: "絶対時間フォーマットを使用する",
			copy_meta_stats_total: "合計リアクション数を含める",
			copy_meta_stats_detailed: "詳細なリアクションを含める",
			copy_meta_link_preview: "リンクプレビュー情報を含める",
			copy_meta_image_count: "画像数を含める",
			image_count_label: "画像",
			copy_meta_video_duration: "動画/リールの長さを含める",
			label_reel: "リール",
			label_video: "動画",
			stats_label_like: "いいね",
			stats_label_comment: "コメント",
			stats_label_share: "シェア",
			stats_label_reaction: "リアクション",
			preview_label_title: "タイトル",
			preview_label_source: "ソース",
			preview_label_desc: "概要",
			preview_label_link: "リンク",
			copier_shared_post_label: "シェアされた投稿",
			label_no_text_content: "[テキストコンテンツなし]",
			label_videos_plural: "本の動画",
			tooltipAds: "広告ライブラリ",
			tooltipTransparency: "ページの透明性",
			notificationReelSearchError: "ページ名が見つかりません。",
			excludeTranslation: "Google 検索で翻訳済みページを除外する (Googleのバグにより結果が空になる可能性があります)",
			appLanguage: "言語 (Language)",
			langAuto: "自動検出",
			langEN: "English",
			langZH: "繁體中文 (zh-TW)",
			langJA: "日本語 (ja)",
			enableBookmarksLabel: "ローカルブックマークを有効にする (投稿・ページ)",
			bookmarkPositionLabel: "ブックマークパネルの位置",
			bookmarkPositionLeft: "左側 (デフォルト)",
			bookmarkPositionRight: "右側",
			settingsColumnBookmarks: "ブックマーク",
			bookmark_post_added: "投稿をブックマークに保存しました。",
			bookmark_post_removed: "投稿をブックマークから削除しました。",
			bookmark_page_added: "ページをブックマークに保存しました。",
			bookmark_page_removed: "ページをブックマークから削除しました。",
			bookmark_tab_posts: "保存した投稿",
			bookmark_tab_pages: "保存したページ・グループ",
			bookmark_empty: "ブックマークはまだありません。",
			bookmark_clear_btn: "すべてのブックマークを消去",
			bookmark_export_btn: "ブックマークをエクスポート (JSON)",
			bookmark_sort_label: "並べ替え",
			bookmark_sort_saved_at: "保存日時 (新しい順)",
			bookmark_sort_publish_time: "投稿日時 (新しい順)",
			bookmark_sort_last_visited: "閲覧日時 (新しい順)",
			bookmark_sort_name: "名前順 (A-Z / 画数)",
			bookmark_confirm_clear: "すべてのブックマークを消去しますか?この操作は元に戻せません。",
			bookmark_action_title: "この投稿を保存",
			bookmark_page_action_title: "このページ・グループを保存",
			bookmark_page_action_remove_title: "このページ・グループの保存を解除",
			bookmark_hover_preview_hint: "投稿にホバーまたはクリックすると、全文が表示されます",
			bookmark_open_original_post: "元の投稿を開く",
			bookmark_manage_btn: "ブックマーク管理...",
			bookmark_view_full: "全文を表示",
			bookmark_collapse: "折りたたむ",
			bookmark_menu_title: "マイブックマーク",
			bookmark_menu_posts: "最近保存した投稿",
			bookmark_menu_pages: "Recent Bookmarked Pages",
			bookmark_copy_title: "リンクをコピー",
			bookmark_copy_content_title: "投稿内容をコピー",
			bookmark_copied_notification: "リンクをクリップボードにコピーしました。",
			bookmark_content_copied_notification: "投稿内容をクリップボードにコピーしました。",
			bookmark_delete_confirm_title: "もう一度クリックして削除",
			bookmark_delete_title: "削除",
			bookmark_last_visited: "前回の閲覧:{time}",
			bookmark_last_visited_never: "前回の閲覧:未閲覧",
			bookmark_search_placeholder: "ブックマークやタグを検索...",
			bookmark_folder_label: "フォルダ",
			bookmark_folder_all: "すべて",
			bookmark_folder_root: "未分類",
			bookmark_add_folder: "新規フォルダ",
			bookmark_delete_folder_confirm: "このフォルダを削除してもよろしいですか?フォルダ内のブックマークは未分類に移動します。",
			bookmark_tags_label: "タグ",
			bookmark_add_tag_btn: "タグを追加",
			bookmark_add_tag_placeholder: "タグを入力してEnter...",
			bookmark_move_to_folder: "フォルダに移動",
			setting_screenshotScale: "スクリーンショット解像度倍率",
			scale_1x: "1x (標準)",
			scale_2x: "2x (高画質)",
			scale_3x: "3x (超高画質)",
			setting_screenshotExcludeComments: "スクリーンショットからコメントを除外",
			setting_screenshotFormat: "スクリーンショット出力フォーマット",
			format_png: "PNG (無劣化)",
			format_jpeg: "JPEG (圧縮)",
			setting_screenshotEmbedLink: "固定リンクの透かしを埋め込む",
			following_copy_button_title: "フォロー一覧をコピー",
			following_copy_success: "{count} 件のフォローをコピーしました!",
			following_copy_failed: "フォロー一覧の取得に失敗しました",
			batchCopy_failed: "一括エクスポートに失敗しました。",
			operation_failed: "操作に失敗しました。",
			batchCopy_summary_title: "【 一括エクスポートサマリー 】",
			batchCopy_summary_source: "ソース",
			batchCopy_summary_url: "URL",
			batchCopy_summary_time: "時間",
			batchCopy_summary_count: "件数",
			batchCopy_summary_posts: "件"
		}
	}, n$1, l$3, u$3, t$2, i$3, r$2, o$3, e$2, f$3, c$2, a$2, s$2, h$3, p$3, v$2, d$3 = {}, w$3 = [], _$2 = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i, g$2 = Array.isArray;
	function m$3(n, l) {
		for (var u in l) n[u] = l[u];
		return n;
	}
	function b$2(n) {
		n && n.parentNode && n.parentNode.removeChild(n);
	}
	function k$2(l, u, t) {
		var i, r, o, e = {};
		for (o in u) "key" == o ? i = u[o] : "ref" == o ? r = u[o] : e[o] = u[o];
		if (arguments.length > 2 && (e.children = arguments.length > 3 ? n$1.call(arguments, 2) : t), "function" == typeof l && null != l.defaultProps) for (o in l.defaultProps) void 0 === e[o] && (e[o] = l.defaultProps[o]);
		return x$2(l, e, i, r, null);
	}
	function x$2(n, t, i, r, o) {
		var e = {
			type: n,
			props: t,
			key: i,
			ref: r,
			__k: null,
			__: null,
			__b: 0,
			__e: null,
			__c: null,
			constructor: void 0,
			__v: null == o ? ++u$3 : o,
			__i: -1,
			__u: 0
		};
		return null == o && null != l$3.vnode && l$3.vnode(e), e;
	}
	function S$1(n) {
		return n.children;
	}
	function C$1(n, l) {
		this.props = n, this.context = l;
	}
	function $(n, l) {
		if (null == l) return n.__ ? $(n.__, n.__i + 1) : null;
		for (var u; l < n.__k.length; l++) if (null != (u = n.__k[l]) && null != u.__e) return u.__e;
		return "function" == typeof n.type ? $(n) : null;
	}
	function I(n) {
		if (n.__P && n.__d) {
			var u = n.__v, t = u.__e, i = [], r = [], o = m$3({}, u);
			o.__v = u.__v + 1, l$3.vnode && l$3.vnode(o), q$1(n.__P, o, u, n.__n, n.__P.namespaceURI, 32 & u.__u ? [t] : null, i, null == t ? $(u) : t, !!(32 & u.__u), r), o.__v = u.__v, o.__.__k[o.__i] = o, D$1(i, o, r), u.__e = u.__ = null, o.__e != t && P(o);
		}
	}
	function P(n) {
		if (null != (n = n.__) && null != n.__c) return n.__e = n.__c.base = null, n.__k.some(function(l) {
			if (null != l && null != l.__e) return n.__e = n.__c.base = l.__e;
		}), P(n);
	}
	function A$1(n) {
		(!n.__d && (n.__d = !0) && i$3.push(n) && !H.__r++ || r$2 != l$3.debounceRendering) && ((r$2 = l$3.debounceRendering) || o$3)(H);
	}
	function H() {
		try {
			for (var n, l = 1; i$3.length;) i$3.length > l && i$3.sort(e$2), n = i$3.shift(), l = i$3.length, I(n);
		} finally {
			i$3.length = H.__r = 0;
		}
	}
	function L(n, l, u, t, i, r, o, e, f, c, a) {
		var s, h, p, v, y, _, g, m = t && t.__k || w$3, b = l.length;
		for (f = T$1(u, l, m, f, b), s = 0; s < b; s++) null != (p = u.__k[s]) && (h = -1 != p.__i && m[p.__i] || d$3, p.__i = s, _ = q$1(n, p, h, i, r, o, e, f, c, a), v = p.__e, p.ref && h.ref != p.ref && (h.ref && J(h.ref, null, p), a.push(p.ref, p.__c || v, p)), null == y && null != v && (y = v), (g = !!(4 & p.__u)) || h.__k === p.__k ? (f = j$2(p, f, n, g), g && h.__e && (h.__e = null)) : "function" == typeof p.type && void 0 !== _ ? f = _ : v && (f = v.nextSibling), p.__u &= -7);
		return u.__e = y, f;
	}
	function T$1(n, l, u, t, i) {
		var r, o, e, f, c, a = u.length, s = a, h = 0;
		for (n.__k = new Array(i), r = 0; r < i; r++) null != (o = l[r]) && "boolean" != typeof o && "function" != typeof o ? ("string" == typeof o || "number" == typeof o || "bigint" == typeof o || o.constructor == String ? o = n.__k[r] = x$2(null, o, null, null, null) : g$2(o) ? o = n.__k[r] = x$2(S$1, { children: o }, null, null, null) : void 0 === o.constructor && o.__b > 0 ? o = n.__k[r] = x$2(o.type, o.props, o.key, o.ref ? o.ref : null, o.__v) : n.__k[r] = o, f = r + h, o.__ = n, o.__b = n.__b + 1, e = null, -1 != (c = o.__i = O(o, u, f, s)) && (s--, (e = u[c]) && (e.__u |= 2)), null == e || null == e.__v ? (-1 == c && (i > a ? h-- : i < a && h++), "function" != typeof o.type && (o.__u |= 4)) : c != f && (c == f - 1 ? h-- : c == f + 1 ? h++ : (c > f ? h-- : h++, o.__u |= 4))) : n.__k[r] = null;
		if (s) for (r = 0; r < a; r++) null != (e = u[r]) && 0 == (2 & e.__u) && (e.__e == t && (t = $(e)), K(e, e));
		return t;
	}
	function j$2(n, l, u, t) {
		var i, r;
		if ("function" == typeof n.type) {
			for (i = n.__k, r = 0; i && r < i.length; r++) i[r] && (i[r].__ = n, l = j$2(i[r], l, u, t));
			return l;
		}
		n.__e != l && (t && (l && n.type && !l.parentNode && (l = $(n)), u.insertBefore(n.__e, l || null)), l = n.__e);
		do
			l = l && l.nextSibling;
		while (null != l && 8 == l.nodeType);
		return l;
	}
	function O(n, l, u, t) {
		var i, r, o, e = n.key, f = n.type, c = l[u], a = null != c && 0 == (2 & c.__u);
		if (null === c && null == e || a && e == c.key && f == c.type) return u;
		if (t > (a ? 1 : 0)) {
			for (i = u - 1, r = u + 1; i >= 0 || r < l.length;) if (null != (c = l[o = i >= 0 ? i-- : r++]) && 0 == (2 & c.__u) && e == c.key && f == c.type) return o;
		}
		return -1;
	}
	function z$1(n, l, u) {
		"-" == l[0] ? n.setProperty(l, null == u ? "" : u) : n[l] = null == u ? "" : "number" != typeof u || _$2.test(l) ? u : u + "px";
	}
	function N(n, l, u, t, i) {
		var r, o;
		n: if ("style" == l) if ("string" == typeof u) n.style.cssText = u;
		else {
			if ("string" == typeof t && (n.style.cssText = t = ""), t) for (l in t) u && l in u || z$1(n.style, l, "");
			if (u) for (l in u) t && u[l] == t[l] || z$1(n.style, l, u[l]);
		}
		else if ("o" == l[0] && "n" == l[1]) r = l != (l = l.replace(s$2, "$1")), o = l.toLowerCase(), l = o in n || "onFocusOut" == l || "onFocusIn" == l ? o.slice(2) : l.slice(2), n.l || (n.l = {}), n.l[l + r] = u, u ? t ? u[a$2] = t[a$2] : (u[a$2] = h$3, n.addEventListener(l, r ? v$2 : p$3, r)) : n.removeEventListener(l, r ? v$2 : p$3, r);
		else {
			if ("http://www.w3.org/2000/svg" == i) l = l.replace(/xlink(H|:h)/, "h").replace(/sName$/, "s");
			else if ("width" != l && "height" != l && "href" != l && "list" != l && "form" != l && "tabIndex" != l && "download" != l && "rowSpan" != l && "colSpan" != l && "role" != l && "popover" != l && l in n) try {
				n[l] = null == u ? "" : u;
				break n;
			} catch (n) {}
			"function" == typeof u || (null == u || !1 === u && "-" != l[4] ? n.removeAttribute(l) : n.setAttribute(l, "popover" == l && 1 == u ? "" : u));
		}
	}
	function V(n) {
		return function(u) {
			if (this.l) {
				var t = this.l[u.type + n];
				if (null == u[c$2]) u[c$2] = h$3++;
				else if (u[c$2] < t[a$2]) return;
				return t(l$3.event ? l$3.event(u) : u);
			}
		};
	}
	function q$1(n, u, t, i, r, o, e, f, c, a) {
		var s, h, p, v, y, d, _, k, x, M, $, I, P, A, H, T = u.type;
		if (void 0 !== u.constructor) return null;
		128 & t.__u && (c = !!(32 & t.__u), o = [f = u.__e = t.__e]), (s = l$3.__b) && s(u);
		n: if ("function" == typeof T) try {
			if (k = u.props, x = T.prototype && T.prototype.render, M = (s = T.contextType) && i[s.__c], $ = s ? M ? M.props.value : s.__ : i, t.__c ? _ = (h = u.__c = t.__c).__ = h.__E : (x ? u.__c = h = new T(k, $) : (u.__c = h = new C$1(k, $), h.constructor = T, h.render = Q), M && M.sub(h), h.state || (h.state = {}), h.__n = i, p = h.__d = !0, h.__h = [], h._sb = []), x && null == h.__s && (h.__s = h.state), x && null != T.getDerivedStateFromProps && (h.__s == h.state && (h.__s = m$3({}, h.__s)), m$3(h.__s, T.getDerivedStateFromProps(k, h.__s))), v = h.props, y = h.state, h.__v = u, p) x && null == T.getDerivedStateFromProps && null != h.componentWillMount && h.componentWillMount(), x && null != h.componentDidMount && h.__h.push(h.componentDidMount);
			else {
				if (x && null == T.getDerivedStateFromProps && k !== v && null != h.componentWillReceiveProps && h.componentWillReceiveProps(k, $), u.__v == t.__v || !h.__e && null != h.shouldComponentUpdate && !1 === h.shouldComponentUpdate(k, h.__s, $)) {
					u.__v != t.__v && (h.props = k, h.state = h.__s, h.__d = !1), u.__e = t.__e, u.__k = t.__k, u.__k.some(function(n) {
						n && (n.__ = u);
					}), w$3.push.apply(h.__h, h._sb), h._sb = [], h.__h.length && e.push(h);
					break n;
				}
				null != h.componentWillUpdate && h.componentWillUpdate(k, h.__s, $), x && null != h.componentDidUpdate && h.__h.push(function() {
					h.componentDidUpdate(v, y, d);
				});
			}
			if (h.context = $, h.props = k, h.__P = n, h.__e = !1, I = l$3.__r, P = 0, x) h.state = h.__s, h.__d = !1, I && I(u), s = h.render(h.props, h.state, h.context), w$3.push.apply(h.__h, h._sb), h._sb = [];
			else do
				h.__d = !1, I && I(u), s = h.render(h.props, h.state, h.context), h.state = h.__s;
			while (h.__d && ++P < 25);
			h.state = h.__s, null != h.getChildContext && (i = m$3(m$3({}, i), h.getChildContext())), x && !p && null != h.getSnapshotBeforeUpdate && (d = h.getSnapshotBeforeUpdate(v, y)), A = null != s && s.type === S$1 && null == s.key ? E$1(s.props.children) : s, f = L(n, g$2(A) ? A : [A], u, t, i, r, o, e, f, c, a), h.base = u.__e, u.__u &= -161, h.__h.length && e.push(h), _ && (h.__E = h.__ = null);
		} catch (n) {
			if (u.__v = null, c || null != o) if (n.then) {
				for (u.__u |= c ? 160 : 128; f && 8 == f.nodeType && f.nextSibling;) f = f.nextSibling;
				o[o.indexOf(f)] = null, u.__e = f;
			} else {
				for (H = o.length; H--;) b$2(o[H]);
				B$1(u);
			}
			else u.__e = t.__e, u.__k = t.__k, n.then || B$1(u);
			l$3.__e(n, u, t);
		}
		else null == o && u.__v == t.__v ? (u.__k = t.__k, u.__e = t.__e) : f = u.__e = G(t.__e, u, t, i, r, o, e, c, a);
		return (s = l$3.diffed) && s(u), 128 & u.__u ? void 0 : f;
	}
	function B$1(n) {
		n && (n.__c && (n.__c.__e = !0), n.__k && n.__k.some(B$1));
	}
	function D$1(n, u, t) {
		for (var i = 0; i < t.length; i++) J(t[i], t[++i], t[++i]);
		l$3.__c && l$3.__c(u, n), n.some(function(u) {
			try {
				n = u.__h, u.__h = [], n.some(function(n) {
					n.call(u);
				});
			} catch (n) {
				l$3.__e(n, u.__v);
			}
		});
	}
	function E$1(n) {
		return "object" != typeof n || null == n || n.__b > 0 ? n : g$2(n) ? n.map(E$1) : void 0 !== n.constructor ? null : m$3({}, n);
	}
	function G(u, t, i, r, o, e, f, c, a) {
		var s, h, p, v, y, w, _, m = i.props || d$3, k = t.props, x = t.type;
		if ("svg" == x ? o = "http://www.w3.org/2000/svg" : "math" == x ? o = "http://www.w3.org/1998/Math/MathML" : o || (o = "http://www.w3.org/1999/xhtml"), null != e) {
			for (s = 0; s < e.length; s++) if ((y = e[s]) && "setAttribute" in y == !!x && (x ? y.localName == x : 3 == y.nodeType)) {
				u = y, e[s] = null;
				break;
			}
		}
		if (null == u) {
			if (null == x) return document.createTextNode(k);
			u = document.createElementNS(o, x, k.is && k), c && (l$3.__m && l$3.__m(t, e), c = !1), e = null;
		}
		if (null == x) m === k || c && u.data == k || (u.data = k);
		else {
			if (e = "textarea" == x && null != k.defaultValue ? null : e && n$1.call(u.childNodes), !c && null != e) for (m = {}, s = 0; s < u.attributes.length; s++) m[(y = u.attributes[s]).name] = y.value;
			for (s in m) y = m[s], "dangerouslySetInnerHTML" == s ? p = y : "children" == s || s in k || "value" == s && "defaultValue" in k || "checked" == s && "defaultChecked" in k || N(u, s, null, y, o);
			for (s in k) y = k[s], "children" == s ? v = y : "dangerouslySetInnerHTML" == s ? h = y : "value" == s ? w = y : "checked" == s ? _ = y : c && "function" != typeof y || m[s] === y || N(u, s, y, m[s], o);
			if (h) c || p && (h.__html == p.__html || h.__html == u.innerHTML) || (u.innerHTML = h.__html), t.__k = [];
			else if (p && (u.innerHTML = ""), L("template" == t.type ? u.content : u, g$2(v) ? v : [v], t, i, r, "foreignObject" == x ? "http://www.w3.org/1999/xhtml" : o, e, f, e ? e[0] : i.__k && $(i, 0), c, a), null != e) for (s = e.length; s--;) b$2(e[s]);
			c && "textarea" != x || (s = "value", "progress" == x && null == w ? u.removeAttribute("value") : null != w && (w !== u[s] || "progress" == x && !w || "option" == x && w != m[s]) && N(u, s, w, m[s], o), s = "checked", null != _ && _ != u[s] && N(u, s, _, m[s], o));
		}
		return u;
	}
	function J(n, u, t) {
		try {
			if ("function" == typeof n) {
				var i = "function" == typeof n.__u;
				i && n.__u(), i && null == u || (n.__u = n(u));
			} else n.current = u;
		} catch (n) {
			l$3.__e(n, t);
		}
	}
	function K(n, u, t) {
		var i, r;
		if (l$3.unmount && l$3.unmount(n), (i = n.ref) && (i.current && i.current != n.__e || J(i, null, u)), null != (i = n.__c)) {
			if (i.componentWillUnmount) try {
				i.componentWillUnmount();
			} catch (n) {
				l$3.__e(n, u);
			}
			i.base = i.__P = null;
		}
		if (i = n.__k) for (r = 0; r < i.length; r++) i[r] && K(i[r], u, t || "function" != typeof n.type);
		t || b$2(n.__e), n.__c = n.__ = n.__e = void 0;
	}
	function Q(n, l, u) {
		return this.constructor(n, u);
	}
	function R(u, t, i) {
		var r, o, e, f;
		t == document && (t = document.documentElement), l$3.__ && l$3.__(u, t), o = (r = "function" == typeof i) ? null : i && i.__k || t.__k, e = [], f = [], q$1(t, u = (!r && i || t).__k = k$2(S$1, null, [u]), o || d$3, d$3, t.namespaceURI, !r && i ? [i] : o ? null : t.firstChild ? n$1.call(t.childNodes) : null, e, !r && i ? i : o ? o.__e : t.firstChild, r, f), D$1(e, u, f);
	}
	n$1 = w$3.slice, l$3 = { __e: function(n, l, u, t) {
		for (var i, r, o; l = l.__;) if ((i = l.__c) && !i.__) try {
			if ((r = i.constructor) && null != r.getDerivedStateFromError && (i.setState(r.getDerivedStateFromError(n)), o = i.__d), null != i.componentDidCatch && (i.componentDidCatch(n, t || {}), o = i.__d), o) return i.__E = i;
		} catch (l) {
			n = l;
		}
		throw n;
	} }, u$3 = 0, t$2 = function(n) {
		return null != n && void 0 === n.constructor;
	}, C$1.prototype.setState = function(n, l) {
		var u = null != this.__s && this.__s != this.state ? this.__s : this.__s = m$3({}, this.state);
		"function" == typeof n && (n = n(m$3({}, u), this.props)), n && m$3(u, n), null != n && this.__v && (l && this._sb.push(l), A$1(this));
	}, C$1.prototype.forceUpdate = function(n) {
		this.__v && (this.__e = !0, n && this.__h.push(n), A$1(this));
	}, C$1.prototype.render = S$1, i$3 = [], o$3 = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, e$2 = function(n, l) {
		return n.__v.__b - l.__v.__b;
	}, H.__r = 0, f$3 = Math.random().toString(8), c$2 = "__d" + f$3, a$2 = "__a" + f$3, s$2 = /(PointerCapture)$|Capture$/i, h$3 = 0, p$3 = V(!1), v$2 = V(!0);
	var t$1, r$1, u$2, i$2, o$2 = 0, f$2 = [], c$1 = l$3, e$1 = c$1.__b, a$1 = c$1.__r, v$1 = c$1.diffed, l$2 = c$1.__c, m$2 = c$1.unmount, s$1 = c$1.__;
	function p$2(n, t) {
		c$1.__h && c$1.__h(r$1, n, o$2 || t), o$2 = 0;
		var u = r$1.__H || (r$1.__H = {
			__: [],
			__h: []
		});
		return n >= u.__.length && u.__.push({}), u.__[n];
	}
	function d$2(n) {
		return o$2 = 1, h$2(D, n);
	}
	function h$2(n, u, i) {
		var o = p$2(t$1++, 2);
		if (o.t = n, !o.__c && (o.__ = [i ? i(u) : D(void 0, u), function(n) {
			var t = o.__N ? o.__N[0] : o.__[0], r = o.t(t, n);
			t !== r && (o.__N = [r, o.__[1]], o.__c.setState({}));
		}], o.__c = r$1, !r$1.__f)) {
			var f = function(n, t, r) {
				if (!o.__c.__H) return !0;
				var u = o.__c.__H.__.filter(function(n) {
					return n.__c;
				});
				if (u.every(function(n) {
					return !n.__N;
				})) return !c || c.call(this, n, t, r);
				var i = o.__c.props !== n;
				return u.some(function(n) {
					if (n.__N) {
						var t = n.__[0];
						n.__ = n.__N, n.__N = void 0, t !== n.__[0] && (i = !0);
					}
				}), c && c.call(this, n, t, r) || i;
			};
			r$1.__f = !0;
			var c = r$1.shouldComponentUpdate, e = r$1.componentWillUpdate;
			r$1.componentWillUpdate = function(n, t, r) {
				if (this.__e) {
					var u = c;
					c = void 0, f(n, t, r), c = u;
				}
				e && e.call(this, n, t, r);
			}, r$1.shouldComponentUpdate = f;
		}
		return o.__N || o.__;
	}
	function y$2(n, u) {
		var i = p$2(t$1++, 3);
		!c$1.__s && C(i.__H, u) && (i.__ = n, i.u = u, r$1.__H.__h.push(i));
	}
	function A(n) {
		return o$2 = 5, T(function() {
			return { current: n };
		}, []);
	}
	function T(n, r) {
		var u = p$2(t$1++, 7);
		return C(u.__H, r) && (u.__ = n(), u.__H = r, u.__h = n), u.__;
	}
	function j$1() {
		for (var n; n = f$2.shift();) {
			var t = n.__H;
			if (n.__P && t) try {
				t.__h.some(z), t.__h.some(B), t.__h = [];
			} catch (r) {
				t.__h = [], c$1.__e(r, n.__v);
			}
		}
	}
	c$1.__b = function(n) {
		r$1 = null, e$1 && e$1(n);
	}, c$1.__ = function(n, t) {
		n && t.__k && t.__k.__m && (n.__m = t.__k.__m), s$1 && s$1(n, t);
	}, c$1.__r = function(n) {
		a$1 && a$1(n), t$1 = 0;
		var i = (r$1 = n.__c).__H;
		i && (u$2 === r$1 ? (i.__h = [], r$1.__h = [], i.__.some(function(n) {
			n.__N && (n.__ = n.__N), n.u = n.__N = void 0;
		})) : (i.__h.some(z), i.__h.some(B), i.__h = [], t$1 = 0)), u$2 = r$1;
	}, c$1.diffed = function(n) {
		v$1 && v$1(n);
		var t = n.__c;
		t && t.__H && (t.__H.__h.length && (1 !== f$2.push(t) && i$2 === c$1.requestAnimationFrame || ((i$2 = c$1.requestAnimationFrame) || w$2)(j$1)), t.__H.__.some(function(n) {
			n.u && (n.__H = n.u), n.u = void 0;
		})), u$2 = r$1 = null;
	}, c$1.__c = function(n, t) {
		t.some(function(n) {
			try {
				n.__h.some(z), n.__h = n.__h.filter(function(n) {
					return !n.__ || B(n);
				});
			} catch (r) {
				t.some(function(n) {
					n.__h && (n.__h = []);
				}), t = [], c$1.__e(r, n.__v);
			}
		}), l$2 && l$2(n, t);
	}, c$1.unmount = function(n) {
		m$2 && m$2(n);
		var t, r = n.__c;
		r && r.__H && (r.__H.__.some(function(n) {
			try {
				z(n);
			} catch (n) {
				t = n;
			}
		}), r.__H = void 0, t && c$1.__e(t, r.__v));
	};
	var k$1 = "function" == typeof requestAnimationFrame;
	function w$2(n) {
		var t, r = function() {
			clearTimeout(u), k$1 && cancelAnimationFrame(t), setTimeout(n);
		}, u = setTimeout(r, 35);
		k$1 && (t = requestAnimationFrame(r));
	}
	function z(n) {
		var t = r$1, u = n.__c;
		"function" == typeof u && (n.__c = void 0, u()), r$1 = t;
	}
	function B(n) {
		var t = r$1;
		n.__c = n.__(), r$1 = t;
	}
	function C(n, t) {
		return !n || n.length !== t.length || t.some(function(t, r) {
			return t !== n[r];
		});
	}
	function D(n, t) {
		return "function" == typeof t ? t(n) : t;
	}
	var i$1 = Symbol.for("preact-signals");
	function t() {
		if (!(s > 1)) {
			var i, t = !1;
			(function() {
				var i = c;
				c = void 0;
				while (void 0 !== i) {
					if (i.S.v === i.v) i.S.i = i.i;
					i = i.o;
				}
			})();
			while (void 0 !== h$1) {
				var n = h$1;
				h$1 = void 0;
				v++;
				while (void 0 !== n) {
					var r = n.u;
					n.u = void 0;
					n.f &= -3;
					if (!(8 & n.f) && w$1(n)) try {
						n.c();
					} catch (n) {
						if (!t) {
							i = n;
							t = !0;
						}
					}
					n = r;
				}
			}
			v = 0;
			s--;
			if (t) throw i;
		} else s--;
	}
	function n(i) {
		if (s > 0) return i();
		e = ++u$1;
		s++;
		try {
			return i();
		} finally {
			t();
		}
	}
	var r = void 0;
	function o$1(i) {
		var t = r;
		r = void 0;
		try {
			return i();
		} finally {
			r = t;
		}
	}
	var f$1, h$1 = void 0, s = 0, v = 0, u$1 = 0, e = 0, c = void 0, d$1 = 0;
	function a(i) {
		if (void 0 !== r) {
			var t = i.n;
			if (void 0 === t || t.t !== r) {
				t = {
					i: 0,
					S: i,
					p: r.s,
					n: void 0,
					t: r,
					e: void 0,
					x: void 0,
					r: t
				};
				if (void 0 !== r.s) r.s.n = t;
				r.s = t;
				i.n = t;
				if (32 & r.f) i.S(t);
				return t;
			} else if (-1 === t.i) {
				t.i = 0;
				if (void 0 !== t.n) {
					t.n.p = t.p;
					if (void 0 !== t.p) t.p.n = t.n;
					t.p = r.s;
					t.n = void 0;
					r.s.n = t;
					r.s = t;
				}
				return t;
			}
		}
	}
	function l$1(i, t) {
		this.v = i;
		this.i = 0;
		this.n = void 0;
		this.t = void 0;
		this.l = 0;
		this.W = null == t ? void 0 : t.watched;
		this.Z = null == t ? void 0 : t.unwatched;
		this.name = null == t ? void 0 : t.name;
	}
	l$1.prototype.brand = i$1;
	l$1.prototype.h = function() {
		return !0;
	};
	l$1.prototype.S = function(i) {
		var t = this, n = this.t;
		if (n !== i && void 0 === i.e) {
			i.x = n;
			this.t = i;
			if (void 0 !== n) n.e = i;
			else o$1(function() {
				var i;
				null == (i = t.W) || i.call(t);
			});
		}
	};
	l$1.prototype.U = function(i) {
		var t = this;
		if (void 0 !== this.t) {
			var n = i.e, r = i.x;
			if (void 0 !== n) {
				n.x = r;
				i.e = void 0;
			}
			if (void 0 !== r) {
				r.e = n;
				i.x = void 0;
			}
			if (i === this.t) {
				this.t = r;
				if (void 0 === r) o$1(function() {
					var i;
					null == (i = t.Z) || i.call(t);
				});
			}
		}
	};
	l$1.prototype.subscribe = function(i) {
		var t = this;
		return j(function() {
			var n = t.value, o = r;
			r = void 0;
			try {
				i(n);
			} finally {
				r = o;
			}
		}, { name: "sub" });
	};
	l$1.prototype.valueOf = function() {
		return this.value;
	};
	l$1.prototype.toString = function() {
		return this.value + "";
	};
	l$1.prototype.toJSON = function() {
		return this.value;
	};
	l$1.prototype.peek = function() {
		var i = this;
		return o$1(function() {
			return i.value;
		});
	};
	Object.defineProperty(l$1.prototype, "value", {
		get: function() {
			var i = a(this);
			if (void 0 !== i) i.i = this.i;
			return this.v;
		},
		set: function(i) {
			if (i !== this.v) {
				if (v > 100) throw new Error("Cycle detected");
				(function(i) {
					if (0 !== s && 0 === v) {
						if (i.l !== e) {
							i.l = e;
							c = {
								S: i,
								v: i.v,
								i: i.i,
								o: c
							};
						}
					}
				})(this);
				this.v = i;
				this.i++;
				d$1++;
				s++;
				try {
					for (var n = this.t; void 0 !== n; n = n.x) n.t.N();
				} finally {
					t();
				}
			}
		}
	});
	function y$1(i, t) {
		return new l$1(i, t);
	}
	function w$1(i) {
		for (var t = i.s; void 0 !== t; t = t.n) if (t.S.i !== t.i || !t.S.h() || t.S.i !== t.i) return !0;
		return !1;
	}
	function _$1(i) {
		for (var t = i.s; void 0 !== t; t = t.n) {
			var n = t.S.n;
			if (void 0 !== n) t.r = n;
			t.S.n = t;
			t.i = -1;
			if (void 0 === t.n) {
				i.s = t;
				break;
			}
		}
	}
	function b$1(i) {
		var t = i.s, n = void 0;
		while (void 0 !== t) {
			var r = t.p;
			if (-1 === t.i) {
				t.S.U(t);
				if (void 0 !== r) r.n = t.n;
				if (void 0 !== t.n) t.n.p = r;
			} else n = t;
			t.S.n = t.r;
			if (void 0 !== t.r) t.r = void 0;
			t = r;
		}
		i.s = n;
	}
	function p$1(i, t) {
		l$1.call(this, void 0);
		this.x = i;
		this.s = void 0;
		this.g = d$1 - 1;
		this.f = 4;
		this.W = null == t ? void 0 : t.watched;
		this.Z = null == t ? void 0 : t.unwatched;
		this.name = null == t ? void 0 : t.name;
	}
	p$1.prototype = new l$1();
	p$1.prototype.h = function() {
		this.f &= -3;
		if (1 & this.f) return !1;
		if (32 == (36 & this.f)) return !0;
		this.f &= -5;
		if (this.g === d$1) return !0;
		this.g = d$1;
		this.f |= 1;
		if (this.i > 0 && !w$1(this)) {
			this.f &= -2;
			return !0;
		}
		var i = r;
		try {
			_$1(this);
			r = this;
			var t = this.x();
			if (16 & this.f || this.v !== t || 0 === this.i) {
				this.v = t;
				this.f &= -17;
				this.i++;
			}
		} catch (i) {
			this.v = i;
			this.f |= 16;
			this.i++;
		}
		r = i;
		b$1(this);
		this.f &= -2;
		return !0;
	};
	p$1.prototype.S = function(i) {
		if (void 0 === this.t) {
			this.f |= 36;
			for (var t = this.s; void 0 !== t; t = t.n) t.S.S(t);
		}
		l$1.prototype.S.call(this, i);
	};
	p$1.prototype.U = function(i) {
		if (void 0 !== this.t) {
			l$1.prototype.U.call(this, i);
			if (void 0 === this.t) {
				this.f &= -33;
				for (var t = this.s; void 0 !== t; t = t.n) t.S.U(t);
			}
		}
	};
	p$1.prototype.N = function() {
		if (!(2 & this.f)) {
			this.f |= 6;
			for (var i = this.t; void 0 !== i; i = i.x) i.t.N();
		}
	};
	Object.defineProperty(p$1.prototype, "value", { get: function() {
		if (1 & this.f) throw new Error("Cycle detected");
		var i = a(this);
		this.h();
		if (void 0 !== i) i.i = this.i;
		if (16 & this.f) throw this.v;
		return this.v;
	} });
	function g$1(i, t) {
		return new p$1(i, t);
	}
	function S(i) {
		var n = i.m;
		i.m = void 0;
		if ("function" == typeof n) {
			s++;
			var o = r;
			r = void 0;
			try {
				n();
			} catch (t) {
				i.f &= -2;
				i.f |= 8;
				m$1(i);
				throw t;
			} finally {
				r = o;
				t();
			}
		}
	}
	function m$1(i) {
		for (var t = i.s; void 0 !== t; t = t.n) t.S.U(t);
		i.x = void 0;
		i.s = void 0;
		S(i);
	}
	function x$1(i) {
		if (r !== this) throw new Error("Out-of-order effect");
		b$1(this);
		r = i;
		this.f &= -2;
		if (8 & this.f) m$1(this);
		t();
	}
	function E(i, t) {
		this.x = i;
		this.m = void 0;
		this.s = void 0;
		this.u = void 0;
		this.f = 32;
		this.name = null == t ? void 0 : t.name;
		if (f$1) f$1.push(this);
	}
	E.prototype.c = function() {
		var i = this.S();
		try {
			if (8 & this.f) return;
			if (void 0 === this.x) return;
			var t = this.x();
			if ("function" == typeof t) this.m = t;
		} finally {
			i();
		}
	};
	E.prototype.S = function() {
		if (1 & this.f) throw new Error("Cycle detected");
		this.f |= 1;
		this.f &= -9;
		S(this);
		_$1(this);
		s++;
		var i = r;
		r = this;
		return x$1.bind(this, i);
	};
	E.prototype.N = function() {
		if (!(2 & this.f)) {
			this.f |= 2;
			this.u = h$1;
			h$1 = this;
		}
	};
	E.prototype.d = function() {
		this.f |= 8;
		if (!(1 & this.f)) m$1(this);
	};
	E.prototype.dispose = function() {
		this.d();
	};
	function j(i, t) {
		var n = new E(i, t);
		try {
			n.c();
		} catch (i) {
			n.d();
			throw i;
		}
		var r = n.d.bind(n);
		r[Symbol.dispose] = r;
		return r;
	}
	var l, h, p = "undefined" != typeof window && !!window.__PREACT_SIGNALS_DEVTOOLS__, _ = [];
	j(function() {
		l = this.N;
	})();
	function g(i, r) {
		l$3[i] = r.bind(null, l$3[i] || function() {});
	}
	function b(i) {
		if (h) {
			var n = h;
			h = void 0;
			n();
		}
		h = i && i.S();
	}
	function y(i) {
		var n = this, t = i.data, e = useSignal(t);
		e.value = t;
		var f = T(function() {
			var i = n, t = n.__v;
			while (t = t.__) if (t.__c) {
				t.__c.__$f |= 4;
				break;
			}
			var o = g$1(function() {
				var i = e.value.value;
				return 0 === i ? 0 : !0 === i ? "" : i || "";
			}), f = g$1(function() {
				return !Array.isArray(o.value) && !t$2(o.value);
			}), a = j(function() {
				this.N = F;
				if (f.value) {
					var n = o.value;
					if (i.__v && i.__v.__e && 3 === i.__v.__e.nodeType) i.__v.__e.data = n;
				}
			}), v = n.__$u.d;
			n.__$u.d = function() {
				a();
				v.call(this);
			};
			return [f, o];
		}, []), a = f[0], v = f[1];
		return a.value ? v.peek() : v.value;
	}
	y.displayName = "ReactiveTextNode";
	Object.defineProperties(l$1.prototype, {
		constructor: {
			configurable: !0,
			value: void 0
		},
		type: {
			configurable: !0,
			value: y
		},
		props: {
			configurable: !0,
			get: function() {
				var i = this;
				return { data: { get value() {
					return i.value;
				} } };
			}
		},
		__b: {
			configurable: !0,
			value: 1
		}
	});
	g("__b", function(i, n) {
		if ("string" == typeof n.type) {
			var r, t = n.props;
			for (var o in t) if ("children" !== o) {
				var e = t[o];
				if (e instanceof l$1) {
					if (!r) n.__np = r = {};
					r[o] = e;
					t[o] = e.peek();
				}
			}
		}
		i(n);
	});
	g("__r", function(i, n) {
		i(n);
		if (n.type !== S$1) {
			b();
			var r, o = n.__c;
			if (o) {
				o.__$f &= -2;
				if (void 0 === (r = o.__$u)) o.__$u = r = function(i, n) {
					var r;
					j(function() {
						r = this;
					}, { name: n });
					r.c = i;
					return r;
				}(function() {
					var i;
					if (p) null == (i = r.y) || i.call(r);
					o.__$f |= 1;
					o.setState({});
				}, "function" == typeof n.type ? n.type.displayName || n.type.name : "");
			}
			b(r);
		}
	});
	g("__e", function(i, n, r, t) {
		b();
		i(n, r, t);
	});
	g("diffed", function(i, n) {
		b();
		var r;
		if ("string" == typeof n.type && (r = n.__e)) {
			var t = n.__np, o = n.props;
			if (t) {
				var e = r.U;
				if (e) for (var f in e) {
					var u = e[f];
					if (void 0 !== u && !(f in t)) {
						u.d();
						e[f] = void 0;
					}
				}
				else {
					e = {};
					r.U = e;
				}
				for (var a in t) {
					var c = e[a], v = t[a];
					if (void 0 === c) {
						c = w(r, a, v);
						e[a] = c;
					} else c.o(v, o);
				}
			}
		}
		i(n);
	});
	function w(i, n, r, t) {
		var o = n in i && void 0 === i.ownerSVGElement, e = y$1(r), f = r.peek();
		return {
			o: function(i, n) {
				e.value = i;
				f = i.peek();
			},
			d: j(function() {
				this.N = F;
				var r = e.value.value;
				if (f !== r) {
					f = void 0;
					if (o) i[n] = r;
					else if (null != r && (!1 !== r || "-" === n[4])) i.setAttribute(n, r);
					else i.removeAttribute(n);
				} else f = void 0;
			})
		};
	}
	g("unmount", function(i, n) {
		if ("string" == typeof n.type) {
			var r = n.__e;
			if (r) {
				var t = r.U;
				if (t) {
					r.U = void 0;
					for (var o in t) {
						var e = t[o];
						if (e) e.d();
					}
				}
			}
			var f = n.__np;
			if (f) {
				var u = n.props;
				for (var a in f) u[a] = f[a];
			}
			n.__np = void 0;
		} else {
			var c = n.__c;
			if (c) {
				var v = c.__$u;
				if (v) {
					c.__$u = void 0;
					v.d();
				}
			}
		}
		i(n);
	});
	g("__h", function(i, n, r, t) {
		if (t < 3 || 9 === t) n.__$f |= 2;
		i(n, r, t);
	});
	C$1.prototype.shouldComponentUpdate = function(i, n) {
		if (this.__R) return !0;
		var r = this.__$u, t = r && void 0 !== r.s;
		for (var o in n) return !0;
		if (this.__f || "boolean" == typeof this.u && !0 === this.u) {
			var e = 2 & this.__$f;
			if (!(t || e || 4 & this.__$f)) return !0;
			if (1 & this.__$f) return !0;
		} else {
			if (!(t || 4 & this.__$f)) return !0;
			if (3 & this.__$f) return !0;
		}
		for (var f in i) if ("__source" !== f && i[f] !== this.props[f]) return !0;
		for (var u in this.props) if (!(u in i)) return !0;
		return !1;
	};
	function useSignal(i, n) {
		return T(function() {
			return y$1(i, n);
		}, []);
	}
	var q = function(i) {
		queueMicrotask(function() {
			queueMicrotask(i);
		});
	};
	function x() {
		n(function() {
			var i;
			while (i = _.shift()) l.call(i);
		});
	}
	function F() {
		if (1 === _.push(this)) (l$3.requestAnimationFrame || q)(x);
	}
	var f = 0;
	Array.isArray;
	function u(e, t, n, o, i, u) {
		t || (t = {});
		var a, c, p = t;
		if ("ref" in p) for (c in p = {}, t) "ref" == c ? a = t[c] : p[c] = t[c];
		var l = {
			type: e,
			props: p,
			key: n,
			ref: a,
			__k: null,
			__: null,
			__b: 0,
			__e: null,
			__c: null,
			constructor: void 0,
			__v: --f,
			__i: -1,
			__u: 0,
			__source: i,
			__self: u
		};
		if ("function" == typeof e && (a = e.defaultProps)) for (c in a) void 0 === p[c] && (p[c] = a[c]);
		return l$3.vnode && l$3.vnode(l), l;
	}
	var getPostCopyContent$1 = (post, app) => {
		const PHT = app.modules.postHeaderTools;
		if (PHT && typeof PHT.formatPostData === "function") {
			const formattedData = {
				meta: {
					id: post.id,
					url: post.url,
					author: [{
						name: post.authorName,
						link: post.authorLink
					}],
					timestamp: post.timestamp
				},
				stats: post.stats || {
					reactions: {
						total: 0,
						detailed: []
					},
					comments: 0,
					shares: 0
				},
				media: post.media || {
					imageCount: 0,
					videoDuration: null,
					linkPreview: null
				},
				content: post.content,
				sharedPost: post.sharedPost
			};
			return PHT.formatPostData(formattedData, "text");
		}
		return post.content || post.excerpt || "";
	};
	var PreviewCopyLinkButton = ({ url, app, T }) => {
		const [copied, setCopied] = d$2(false);
		y$2(() => {
			if (!copied) return;
			const timer = setTimeout(() => setCopied(false), 1500);
			return () => clearTimeout(timer);
		}, [copied]);
		const handleCopy = (e) => {
			e.preventDefault();
			e.stopPropagation();
			navigator.clipboard.writeText(url).then(() => {
				setCopied(true);
				if (app.modules.toastNotifier) app.modules.toastNotifier.show(T.bookmark_copied_notification || "Link copied to clipboard.", "success");
			});
		};
		return u("button", {
			onClick: handleCopy,
			title: T.bookmark_copy_title || "Copy link",
			style: {
				background: "#E4E6EB",
				border: "none",
				borderRadius: "50%",
				cursor: "pointer",
				width: "24px",
				height: "24px",
				display: "flex",
				alignItems: "center",
				justifyContent: "center",
				color: "#050505",
				transition: "transform 0.1s ease, background-color 0.2s ease",
				outline: "none"
			},
			onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#D8DADF",
			onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#E4E6EB",
			onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.85)",
			onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)",
			children: copied ? "✅" : "🔗"
		});
	};
	var PreviewCopyContentButton = ({ post, app, T }) => {
		const [copied, setCopied] = d$2(false);
		y$2(() => {
			if (!copied) return;
			const timer = setTimeout(() => setCopied(false), 1500);
			return () => clearTimeout(timer);
		}, [copied]);
		const handleCopy = (e) => {
			e.preventDefault();
			e.stopPropagation();
			const textToCopy = getPostCopyContent$1(post, app);
			navigator.clipboard.writeText(textToCopy).then(() => {
				setCopied(true);
				if (app.modules.toastNotifier) app.modules.toastNotifier.show(T.bookmark_content_copied_notification || "Post content copied to clipboard.", "success");
			});
		};
		return u("button", {
			onClick: handleCopy,
			title: T.bookmark_copy_content_title || "Copy post content",
			style: {
				background: "#E4E6EB",
				border: "none",
				borderRadius: "50%",
				cursor: "pointer",
				width: "24px",
				height: "24px",
				display: "flex",
				alignItems: "center",
				justifyContent: "center",
				color: "#050505",
				transition: "transform 0.1s ease, background-color 0.2s ease",
				outline: "none"
			},
			onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#D8DADF",
			onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#E4E6EB",
			onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.85)",
			onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)",
			children: copied ? "✅" : "📋"
		});
	};
	var SettingRow = ({ def, signals, app, isGrid }) => {
		const sig = signals[def.key];
		const T = app.state.T;
		const SM = app.modules.settingsManager;
		const [isRecording, setIsRecording] = d$2(false);
		if (!sig) return null;
		const isDependentDisabled = () => {
			if (def.key === "autoUnmuteVolume") return !signals.autoUnmuteEnabled.value;
			if (def.key.startsWith("keyNav")) return !signals.keyboardNavEnabled.value;
			if (def.key === "copier_permalinkFormat") return !signals.permalinkCopierEnabled.value;
			if (def.key === "idRevealerLinkFormat") return !signals.idRevealerEnabled.value;
			if (def.key === "autoLoadBatchSize") return !signals.floatingNavEnabled.value;
			if (["floatingNav_showAutoLoad", "floatingNav_showBatchCopy"].includes(def.key)) return !signals.floatingNavEnabled.value;
			if (def.key.startsWith("screenshot") && def.key !== "screenshotEnabled") return !signals.screenshotEnabled.value;
			if ([
				"copy_meta_url",
				"copy_meta_order",
				"copy_meta_author_name",
				"copy_meta_author_link",
				"copy_meta_date",
				"copy_meta_absolute_date",
				"copy_meta_stats",
				"copy_meta_link_preview",
				"copy_meta_image_count",
				"copy_meta_video_duration"
			].includes(def.key)) return !signals.copy_includeMetadata.value;
			if (["copy_meta_stats_total", "copy_meta_stats_detailed"].includes(def.key)) return !signals.copy_includeMetadata.value || !signals.copy_meta_stats.value;
			return false;
		};
		const disabled = isDependentDisabled();
		const handleValueChange = (newValue) => {
			sig.value = newValue;
			SM.updateSetting(def.key, newValue);
			if (def.instant) SM.handleSettingChange(def.key, newValue, app.state.settings[def.key]);
			if (def.key === "batchExportFormat" && newValue === "csv") {
				signals.batchCopyMode.value = "file";
				SM.updateSetting("batchCopyMode", "file");
			}
		};
		const getIndentStyle = () => {
			if ([
				"copy_meta_stats_total",
				"copy_meta_stats_detailed",
				"floatingNav_showAutoLoad",
				"floatingNav_showBatchCopy"
			].includes(def.key)) return {
				paddingLeft: "16px",
				borderLeft: "2px solid #eee"
			};
			return {};
		};
		const formatKey = (k) => {
			return {
				" ": "Space",
				"ArrowUp": "↑",
				"ArrowDown": "↓",
				"ArrowLeft": "←",
				"ArrowRight": "→",
				"Escape": "Esc"
			}[k] || (k.length === 1 ? k.toUpperCase() : k);
		};
		const handleKeybindClick = () => {
			setIsRecording(true);
			const keyHandler = (ev) => {
				ev.preventDefault();
				ev.stopPropagation();
				const key = ev.key;
				if (key === "Escape") {
					document.removeEventListener("keydown", keyHandler, true);
					setIsRecording(false);
					return;
				}
				if (key === "Backspace" || key === "Delete") {
					handleValueChange("");
					document.removeEventListener("keydown", keyHandler, true);
					setIsRecording(false);
					return;
				}
				if ([
					"Shift",
					"Control",
					"Alt",
					"Meta",
					"CapsLock"
				].includes(key)) return;
				handleValueChange(key);
				document.removeEventListener("keydown", keyHandler, true);
				setIsRecording(false);
			};
			document.addEventListener("keydown", keyHandler, true);
		};
		const labelText = T[def.labelKey] || def.labelKey;
		const renderInput = () => {
			switch (def.type) {
				case "boolean": return u("label", {
					className: "gm-switch gm-input-right",
					children: [u("input", {
						type: "checkbox",
						id: `setting-${def.key}`,
						checked: sig.value,
						disabled,
						onChange: (e) => handleValueChange(e.target.checked)
					}), u("span", { className: "gm-slider" })]
				});
				case "range": return u("div", {
					className: "gm-range-container",
					children: [u("input", {
						type: "range",
						id: `setting-${def.key}`,
						min: def.options?.min,
						max: def.options?.max,
						step: def.options?.step,
						value: sig.value,
						disabled,
						onInput: (e) => handleValueChange(parseInt(e.target.value, 10))
					}), u("span", {
						style: {
							marginLeft: "12px",
							minWidth: "45px",
							textAlign: "right",
							fontSize: "13px"
						},
						children: [sig.value, def.options?.unit || ""]
					})]
				});
				case "text": return u("input", {
					className: "gm-input-text",
					type: "text",
					id: `setting-${def.key}`,
					value: sig.value,
					disabled,
					onInput: (e) => handleValueChange(e.target.value)
				});
				case "select":
					const isLockedCsv = def.key === "batchCopyMode" && signals.batchExportFormat.value === "csv";
					return u("select", {
						className: "gm-input-select",
						id: `setting-${def.key}`,
						value: sig.value,
						disabled: disabled || isLockedCsv,
						title: isLockedCsv ? T.batchCopyMode_locked_csv || "CSV format requires Download mode" : "",
						onChange: (e) => handleValueChange(e.target.value),
						children: def.options.map((opt) => u("option", {
							value: opt.value,
							children: T[opt.labelKey] || opt.value
						}, opt.value))
					});
				case "keybinder": return u("button", {
					className: `gm-keybinder-btn ${isRecording ? "recording" : ""}`,
					disabled,
					onClick: handleKeybindClick,
					children: isRecording ? T.keyBinderPress || "Press key..." : formatKey(sig.value) || T.keyBinderNone || "(None)"
				});
				default: return null;
			}
		};
		const getRowClassName = () => {
			let className = "gm-setting-row";
			if (def.type !== "boolean") className += " full-width";
			if (isGrid) {
				if ([
					"boolean",
					"range",
					"select",
					"keybinder"
				].includes(def.type) || ["floatingNav_showAutoLoad", "floatingNav_showBatchCopy"].includes(def.key)) className += " span-2";
			}
			return className;
		};
		return u("div", {
			className: getRowClassName(),
			style: {
				opacity: disabled ? .5 : 1,
				pointerEvents: disabled ? "none" : "auto",
				...getIndentStyle()
			},
			children: [u("label", {
				className: "gm-setting-label",
				htmlFor: `setting-${def.key}`,
				children: labelText
			}), renderInput()]
		});
	};
	var DeleteConfirmButton$1 = ({ onDelete, title, T }) => {
		const [confirming, setConfirming] = d$2(false);
		y$2(() => {
			if (!confirming) return;
			const timer = setTimeout(() => setConfirming(false), 3e3);
			return () => clearTimeout(timer);
		}, [confirming]);
		const handleClick = (e) => {
			e.preventDefault();
			e.stopPropagation();
			if (confirming) {
				onDelete();
				setConfirming(false);
			} else setConfirming(true);
		};
		const isZh = T.saveAndClose?.includes("儲存");
		const isJa = T.saveAndClose?.includes("保存");
		const confirmText = isZh ? "確定?" : isJa ? "確定?" : "Confirm?";
		return u("button", {
			className: "gm-delete-confirm-btn",
			onClick: handleClick,
			title: confirming ? T.bookmark_delete_confirm_title || "Click again to confirm delete" : title || T.bookmark_delete_title || "Delete",
			style: {
				background: "transparent",
				border: confirming ? "1px solid #FA383E" : "none",
				backgroundColor: confirming ? "#FFEBEB" : "transparent",
				cursor: "pointer",
				padding: "4px 8px",
				display: "inline-flex",
				alignItems: "center",
				justifyContent: "center",
				borderRadius: "6px",
				transition: "all 0.2s",
				height: "28px",
				gap: "4px"
			},
			children: confirming ? u("span", {
				style: {
					fontSize: "11px",
					color: "#FA383E",
					fontWeight: "bold",
					display: "inline-flex",
					alignItems: "center",
					gap: "2px"
				},
				children: ["⚠️ ", confirmText]
			}) : u("svg", {
				viewBox: "0 0 24 24",
				width: "14",
				height: "14",
				fill: "#FA383E",
				children: u("path", { d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" })
			})
		});
	};
	var showCustomConfirm$1 = (app, message, onConfirm) => {
		const T = app.state.T;
		const container = document.createElement("div");
		document.body.appendChild(container);
		const close = () => {
			R(null, container);
			container.remove();
		};
		const handleConfirm = () => {
			onConfirm();
			close();
		};
		const isZh = T.saveAndClose?.includes("儲存") || T.saveAndClose?.includes("保存");
		R(u("div", {
			style: {
				position: "fixed",
				inset: "0",
				backgroundColor: "rgba(0,0,0,0.4)",
				backdropFilter: "blur(4px)",
				webkitBackdropFilter: "blur(4px)",
				zIndex: 999999,
				display: "flex",
				alignItems: "center",
				justifyContent: "center",
				animation: "gm-fade-in 0.2s ease-out"
			},
			onClick: close,
			children: u("div", {
				style: {
					backgroundColor: "#ffffff",
					borderRadius: "12px",
					padding: "20px",
					width: "360px",
					boxShadow: "0 8px 30px rgba(0,0,0,0.2)",
					display: "flex",
					flexDirection: "column",
					gap: "16px"
				},
				onClick: (e) => e.stopPropagation(),
				children: [u("div", {
					style: {
						fontSize: "15px",
						color: "#050505",
						fontWeight: 500,
						lineHeight: 1.4,
						whiteSpace: "pre-line",
						textAlign: "left"
					},
					children: message
				}), u("div", {
					style: {
						display: "flex",
						justifyContent: "flex-end",
						gap: "8px"
					},
					children: [u("button", {
						onClick: close,
						style: {
							padding: "6px 16px",
							border: "1px solid #CED0D4",
							background: "#ffffff",
							color: "#050505",
							borderRadius: "6px",
							cursor: "pointer",
							fontSize: "13px",
							fontWeight: 600,
							transition: "background 0.2s"
						},
						onMouseEnter: (e) => e.currentTarget.style.background = "#F0F2F5",
						onMouseLeave: (e) => e.currentTarget.style.background = "#ffffff",
						children: isZh ? "取消" : "Cancel"
					}), u("button", {
						onClick: handleConfirm,
						style: {
							padding: "6px 16px",
							border: "none",
							background: "#1877F2",
							color: "#ffffff",
							borderRadius: "6px",
							cursor: "pointer",
							fontSize: "13px",
							fontWeight: 600,
							transition: "background 0.2s"
						},
						onMouseEnter: (e) => e.currentTarget.style.background = "#166FE5",
						onMouseLeave: (e) => e.currentTarget.style.background = "#1877F2",
						children: isZh ? "確定" : "Confirm"
					})]
				})]
			})
		}), container);
	};
	var BookmarksPanel = ({ app }) => {
		const T = app.state.T;
		const formatLastVisited = (timestamp, T) => {
			if (!timestamp) return T.bookmark_last_visited_never || "Last visited: Never";
			const date = new Date(timestamp);
			const yyyy = date.getFullYear();
			const mm = String(date.getMonth() + 1).padStart(2, "0");
			const dd = String(date.getDate()).padStart(2, "0");
			const hh = String(date.getHours()).padStart(2, "0");
			const min = String(date.getMinutes()).padStart(2, "0");
			return (T.bookmark_last_visited || "Last visited: {time}").replace("{time}", `${yyyy}/${mm}/${dd} ${hh}:${min}`);
		};
		const [posts, setPosts] = d$2([]);
		const [pages, setPages] = d$2([]);
		const [folders, setFolders] = d$2([]);
		const [activeSubTab, setActiveSubTab] = d$2("posts");
		const [activePost, setActivePost] = d$2(null);
		const [sortPostsBy, setSortPostsBy] = d$2(GM_getValue("bookmark_sort_posts_by", "savedAt"));
		const [sortPagesBy, setSortPagesBy] = d$2(GM_getValue("bookmark_sort_pages_by", "savedAt"));
		const [activeFolderId, setActiveFolderId] = d$2("all");
		const [filterText, setFilterText] = d$2("");
		const [newFolderName, setNewFolderName] = d$2("");
		const [showFolderAddInput, setShowFolderAddInput] = d$2(false);
		const [newTagInput, setNewTagInput] = d$2("");
		const [editingPageTagsUrl, setEditingPageTagsUrl] = d$2(null);
		const [newPageTagInput, setNewPageTagInput] = d$2("");
		const renderPostMetadata = (post) => {
			const hasStats = post.stats && (post.stats.reactions?.total || post.stats.comments || post.stats.shares);
			const hasMedia = post.media && (post.media.imageCount > 0 || post.media.videoDuration);
			if (!hasStats && !hasMedia) return null;
			return u("div", {
				style: {
					display: "flex",
					flexWrap: "wrap",
					gap: "6px 10px",
					paddingBottom: "8px",
					borderBottom: "1px solid #f0f2f5",
					alignItems: "center",
					fontSize: "12px",
					color: "#65676B"
				},
				children: [
					post.stats?.reactions?.total && u("span", {
						style: {
							display: "flex",
							alignItems: "center",
							gap: "3px"
						},
						title: post.stats.reactions.detailed?.join(" | ") || "",
						children: ["👍 ", post.stats.reactions.total]
					}),
					post.stats?.comments && u("span", {
						style: {
							display: "flex",
							alignItems: "center",
							gap: "3px"
						},
						children: ["💬 ", post.stats.comments]
					}),
					post.stats?.shares && u("span", {
						style: {
							display: "flex",
							alignItems: "center",
							gap: "3px"
						},
						children: ["↗️ ", post.stats.shares]
					}),
					hasStats && hasMedia && u("span", {
						style: { color: "#ccc" },
						children: "|"
					}),
					post.media?.imageCount > 0 && u("span", {
						style: {
							display: "flex",
							alignItems: "center",
							gap: "3px"
						},
						children: [
							"🖼️ ",
							post.media.imageCount,
							" ",
							T.image_count_label || "Images"
						]
					}),
					post.media?.videoDuration && u("span", {
						style: {
							display: "flex",
							alignItems: "center",
							gap: "3px"
						},
						children: ["🎥 ", post.media.videoDuration]
					})
				]
			});
		};
		const renderLinkPreview = (lp) => {
			if (!lp || !lp.title && !lp.url) return null;
			let domain = lp.source || "";
			if (!domain && lp.url) try {
				domain = new URL(lp.url).hostname.replace("www.", "");
			} catch (e) {}
			return u("a", {
				href: lp.url || "#",
				target: "_blank",
				rel: "noopener noreferrer",
				style: {
					display: "block",
					textDecoration: "none",
					color: "inherit",
					border: "1px solid #E4E6EB",
					borderRadius: "8px",
					overflow: "hidden",
					backgroundColor: "#F8F9FA",
					transition: "background-color 0.15s ease",
					marginTop: "5px"
				},
				onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#F0F2F5",
				onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#F8F9FA",
				children: u("div", {
					style: {
						padding: "5px 8px",
						display: "flex",
						flexDirection: "column",
						gap: "2px"
					},
					children: [
						domain && u("div", {
							style: {
								fontSize: "11px",
								color: "#65676B",
								textTransform: "uppercase",
								letterSpacing: "0.5px"
							},
							children: domain
						}),
						lp.title && u("div", {
							style: {
								fontSize: "13px",
								fontWeight: "bold",
								color: "#1C1E21",
								lineHeight: "1.3"
							},
							children: lp.title
						}),
						lp.desc && u("div", {
							style: {
								fontSize: "12px",
								color: "#65676B",
								lineHeight: "1.4",
								display: "-webkit-box",
								webkitLineClamp: 2,
								webkitBoxOrient: "vertical",
								overflow: "hidden"
							},
							children: lp.desc
						})
					]
				})
			});
		};
		const renderSharedPost = (shared) => {
			if (!shared) return null;
			const hasStats = shared.stats && (shared.stats.reactions?.total || shared.stats.comments || shared.stats.shares);
			const hasMedia = shared.media && (shared.media.imageCount > 0 || shared.media.videoDuration);
			const authorList = shared.meta?.author || shared.author || [];
			const timestamp = shared.meta?.timestamp || shared.date || "";
			const postUrl = shared.meta?.url || shared.url || "";
			return u("div", {
				style: {
					marginTop: "5px",
					padding: "5px 10px",
					borderLeft: "3px solid #bec3c9",
					backgroundColor: "#F8F9FA",
					borderRadius: "4px",
					display: "flex",
					flexDirection: "column",
					gap: "4px",
					fontSize: "12px"
				},
				children: [
					u("div", {
						style: {
							display: "flex",
							alignItems: "baseline",
							gap: "6px",
							flexWrap: "wrap"
						},
						children: [
							u("span", {
								style: {
									fontSize: "10.5px",
									color: "#65676B",
									fontWeight: "bold",
									textTransform: "uppercase"
								},
								children: T.copier_shared_post_label || "Shared Post"
							}),
							authorList.length > 0 ? authorList.map((a, idx) => u("span", {
								style: {
									display: "inline-flex",
									alignItems: "center"
								},
								children: [idx > 0 && u("span", {
									style: {
										margin: "0 4px",
										color: "#888"
									},
									children: "&"
								}), a.link ? u("a", {
									href: a.link,
									target: "_blank",
									rel: "noopener",
									style: {
										fontWeight: "bold",
										color: "#1877F2",
										textDecoration: "none"
									},
									children: a.name
								}) : u("span", {
									style: {
										fontWeight: "bold",
										color: "#4b4f56"
									},
									children: a.name
								})]
							}, idx)) : u("span", {
								style: {
									fontWeight: "bold",
									color: "#888"
								},
								children: "Unknown"
							}),
							timestamp && u("span", {
								style: {
									fontSize: "10.5px",
									color: "#888"
								},
								children: ["• ", timestamp]
							}),
							postUrl && u("a", {
								href: postUrl,
								target: "_blank",
								rel: "noopener",
								style: {
									fontSize: "10.5px",
									color: "#1877F2",
									textDecoration: "none",
									marginLeft: "auto"
								},
								title: "Open shared post link",
								children: "↗️"
							})
						]
					}),
					(hasStats || hasMedia) && u("div", {
						style: {
							display: "flex",
							gap: "8px",
							color: "#65676B",
							fontSize: "11px",
							borderBottom: "1px dashed #ddd",
							paddingBottom: "4px"
						},
						children: [
							shared.stats?.reactions?.total && u("span", { children: ["👍 ", shared.stats.reactions.total] }),
							shared.stats?.comments && u("span", { children: ["💬 ", shared.stats.comments] }),
							shared.stats?.shares && u("span", { children: ["↗️ ", shared.stats.shares] }),
							shared.media?.imageCount > 0 && u("span", { children: [
								"🖼️ ",
								shared.media.imageCount,
								" ",
								T.image_count_label || "Images"
							] }),
							shared.media?.videoDuration && u("span", { children: ["🎥 ", shared.media.videoDuration] })
						]
					}),
					shared.content && u("div", {
						style: {
							whiteSpace: "pre-wrap",
							wordBreak: "break-word",
							color: "#1c1e21"
						},
						children: shared.content
					}),
					shared.media?.linkPreview && renderLinkPreview(shared.media.linkPreview)
				]
			});
		};
		const loadBookmarks = () => {
			const loadedPosts = BookmarkStorage.getAll();
			setPosts(loadedPosts);
			setPages(GM_getValue("bookmarked_pages", []));
			setFolders(GM_getValue("bookmarked_folders", []));
			if (loadedPosts.length > 0) setActivePost((prev) => {
				if (!prev) return loadedPosts[0];
				return loadedPosts.find((p) => p.id === prev.id) || loadedPosts[0];
			});
			else setActivePost(null);
		};
		y$2(() => {
			loadBookmarks();
			window.addEventListener("gm-bookmarks-updated", loadBookmarks);
			return () => window.removeEventListener("gm-bookmarks-updated", loadBookmarks);
		}, []);
		const handleAddFolder = (name) => {
			const trimmed = name.trim();
			if (!trimmed) return;
			const currentFolders = GM_getValue("bookmarked_folders", []);
			if (currentFolders.some((f) => f.name.toLowerCase() === trimmed.toLowerCase())) {
				if (app.modules.toastNotifier) app.modules.toastNotifier.show("Folder name already exists.", "failure");
				return;
			}
			const newFolder = {
				id: "folder_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9),
				name: trimmed,
				createdAt: Date.now()
			};
			const updated = [...currentFolders, newFolder];
			GM_setValue("bookmarked_folders", updated);
			setFolders(updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const handleDeleteFolder = (folderId, folderName) => {
			showCustomConfirm$1(app, (T.bookmark_delete_folder_confirm || "Are you sure you want to delete this folder? Bookmarks inside will be moved to Uncategorized.").replace("{name}", folderName), () => {
				const updatedFolders = GM_getValue("bookmarked_folders", []).filter((x) => x.id !== folderId);
				GM_setValue("bookmarked_folders", updatedFolders);
				setFolders(updatedFolders);
				const pList = BookmarkStorage.getAll();
				BookmarkStorage.save(pList.map((p) => p.folderId === folderId ? {
					...p,
					folderId: null
				} : p));
				const pgList = GM_getValue("bookmarked_pages", []);
				GM_setValue("bookmarked_pages", pgList.map((pg) => pg.folderId === folderId ? {
					...pg,
					folderId: null
				} : pg));
				if (activeFolderId === folderId) setActiveFolderId("all");
				window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
			});
		};
		const addPostTag = (post, tag) => {
			const trimmed = tag.trim();
			if (!trimmed) return;
			const updated = BookmarkStorage.getAll().map((p) => {
				if (p.id === post.id) {
					const tags = p.tags || [];
					if (!tags.includes(trimmed)) return {
						...p,
						tags: [...tags, trimmed]
					};
				}
				return p;
			});
			BookmarkStorage.save(updated);
			const updatedPost = updated.find((p) => p.id === post.id);
			if (updatedPost) setActivePost(updatedPost);
		};
		const removePostTag = (post, tag) => {
			const updated = BookmarkStorage.getAll().map((p) => {
				if (p.id === post.id) {
					const tags = p.tags || [];
					return {
						...p,
						tags: tags.filter((t) => t !== tag)
					};
				}
				return p;
			});
			BookmarkStorage.save(updated);
			const updatedPost = updated.find((p) => p.id === post.id);
			if (updatedPost) setActivePost(updatedPost);
		};
		const movePostToFolder = (post, folderId) => {
			const updated = BookmarkStorage.getAll().map((p) => {
				if (p.id === post.id) return {
					...p,
					folderId: folderId || null
				};
				return p;
			});
			BookmarkStorage.save(updated);
			const updatedPost = updated.find((p) => p.id === post.id);
			if (updatedPost) setActivePost(updatedPost);
		};
		const addPageTag = (page, tag) => {
			const trimmed = tag.trim();
			if (!trimmed) return;
			const updated = GM_getValue("bookmarked_pages", []).map((p) => {
				if (p.url === page.url) {
					const tags = p.tags || [];
					if (!tags.includes(trimmed)) return {
						...p,
						tags: [...tags, trimmed]
					};
				}
				return p;
			});
			GM_setValue("bookmarked_pages", updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const removePageTag = (page, tag) => {
			const updated = GM_getValue("bookmarked_pages", []).map((p) => {
				if (p.url === page.url) {
					const tags = p.tags || [];
					return {
						...p,
						tags: tags.filter((t) => t !== tag)
					};
				}
				return p;
			});
			GM_setValue("bookmarked_pages", updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const movePageToFolder = (page, folderId) => {
			const updated = GM_getValue("bookmarked_pages", []).map((p) => {
				if (p.url === page.url) return {
					...p,
					folderId: folderId || null
				};
				return p;
			});
			GM_setValue("bookmarked_pages", updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const handleDeletePost = (id) => {
			const list = posts.filter((p) => p.id !== id);
			setPosts(list);
			BookmarkStorage.save(list);
			if (activePost?.id === id) setActivePost(list.length > 0 ? list[0] : null);
			const PHT = app.modules.postHeaderTools;
			if (PHT) PHT.reEvaluateAllButtons();
		};
		const handleDeletePage = (url) => {
			const list = pages.filter((p) => p.url !== url);
			setPages(list);
			GM_setValue("bookmarked_pages", list);
			const FN = app.modules.floatingNavigator;
			if (FN) FN.updateVisibility();
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const getLocale = () => {
			const savedLang = GM_getValue("appLanguage", "auto");
			let lang = savedLang === "auto" ? navigator.language.toLowerCase() : savedLang;
			if (lang.startsWith("ja")) return "ja";
			if (lang.startsWith("zh")) return "zh-Hant";
			return "en";
		};
		const sortPosts = (items) => {
			return [...items].sort((a, b) => {
				if (sortPostsBy === "publishTime") {
					const pA = a.timestamp ? Date.parse(a.timestamp) : 0;
					const pB = b.timestamp ? Date.parse(b.timestamp) : 0;
					return (isNaN(pB) ? 0 : pB) - (isNaN(pA) ? 0 : pA);
				}
				if (sortPostsBy === "name") return (a.authorName || "").localeCompare(b.authorName || "", getLocale(), {
					numeric: true,
					sensitivity: "base"
				});
				return (b.savedAt || 0) - (a.savedAt || 0);
			});
		};
		const sortPages = (items) => {
			return [...items].sort((a, b) => {
				if (sortPagesBy === "lastVisitedAt") return (b.lastVisitedAt || 0) - (a.lastVisitedAt || 0);
				if (sortPagesBy === "name") return (a.title || "").localeCompare(b.title || "", getLocale(), {
					numeric: true,
					sensitivity: "base"
				});
				return (b.savedAt || 0) - (a.savedAt || 0);
			});
		};
		const query = filterText.toLowerCase().trim();
		const filteredPosts = sortPosts(posts.filter((post) => {
			if (activeFolderId === "root") {
				if (post.folderId) return false;
			} else if (activeFolderId !== "all") {
				if (post.folderId !== activeFolderId) return false;
			}
			if (query) {
				const matchText = (post.authorName || "") + " " + (post.excerpt || "") + " " + (post.content || "");
				const matchTags = (post.tags || []).join(" ");
				return matchText.toLowerCase().includes(query) || matchTags.toLowerCase().includes(query);
			}
			return true;
		}));
		const filteredPages = sortPages(pages.filter((page) => {
			if (activeFolderId === "root") {
				if (page.folderId) return false;
			} else if (activeFolderId !== "all") {
				if (page.folderId !== activeFolderId) return false;
			}
			if (query) {
				const matchText = (page.title || "") + " " + (page.desc || "") + " " + (page.url || "");
				const matchTags = (page.tags || []).join(" ");
				return matchText.toLowerCase().includes(query) || matchTags.toLowerCase().includes(query);
			}
			return true;
		}));
		return u("div", {
			className: "gm-bookmarks-panel",
			style: {
				display: "flex",
				flexDirection: "column",
				height: "100%"
			},
			children: [
				u("div", {
					style: {
						display: "flex",
						borderBottom: "1px solid #ddd",
						marginBottom: "6px",
						gap: "8px"
					},
					children: [u("button", {
						className: `gm-tab-btn ${activeSubTab === "posts" ? "active" : ""}`,
						style: {
							padding: "5px 12px",
							cursor: "pointer",
							border: "none",
							background: "transparent",
							borderBottom: activeSubTab === "posts" ? "2px solid #1877F2" : "none",
							fontWeight: activeSubTab === "posts" ? "bold" : "normal"
						},
						onClick: () => setActiveSubTab("posts"),
						children: [
							T.bookmark_tab_posts || "Posts",
							" (",
							filteredPosts.length,
							")"
						]
					}), u("button", {
						className: `gm-tab-btn ${activeSubTab === "pages" ? "active" : ""}`,
						style: {
							padding: "5px 12px",
							cursor: "pointer",
							border: "none",
							background: "transparent",
							borderBottom: activeSubTab === "pages" ? "2px solid #1877F2" : "none",
							fontWeight: activeSubTab === "pages" ? "bold" : "normal"
						},
						onClick: () => setActiveSubTab("pages"),
						children: [
							T.bookmark_tab_pages || "Pages",
							" (",
							filteredPages.length,
							")"
						]
					})]
				}),
				u("div", {
					style: {
						display: "flex",
						gap: "8px",
						marginBottom: "6px",
						alignItems: "center",
						flexWrap: "wrap"
					},
					children: [
						u("div", {
							style: {
								position: "relative",
								display: "flex",
								alignItems: "center",
								width: "220px"
							},
							children: [
								u("span", {
									style: {
										position: "absolute",
										left: "8px",
										top: "50%",
										transform: "translateY(-50%)",
										fontSize: "13px",
										color: "#888",
										pointerEvents: "none"
									},
									children: "🔍"
								}),
								u("input", {
									type: "text",
									placeholder: T.bookmark_search_placeholder || "Search bookmarks...",
									value: filterText,
									onInput: (e) => setFilterText(e.target.value),
									style: {
										width: "100%",
										padding: "2px 24px 2px 24px",
										fontSize: "12px",
										borderRadius: "6px",
										border: "1px solid #ccc",
										outline: "none",
										backgroundColor: "#F0F2F5",
										height: "26px",
										boxSizing: "border-box"
									}
								}),
								filterText && u("button", {
									onClick: () => setFilterText(""),
									style: {
										position: "absolute",
										right: "8px",
										top: "50%",
										transform: "translateY(-50%)",
										border: "none",
										background: "transparent",
										cursor: "pointer",
										fontSize: "11px",
										color: "#888",
										padding: "2px"
									},
									children: "✖"
								})
							]
						}),
						u("div", {
							style: {
								display: "flex",
								alignItems: "center",
								gap: "4px"
							},
							children: [u("span", {
								style: {
									fontSize: "12px",
									color: "#65676B"
								},
								children: [T.bookmark_sort_label || "Sort", ":"]
							}), activeSubTab === "posts" ? u("select", {
								value: sortPostsBy,
								onChange: (e) => {
									const val = e.target.value;
									setSortPostsBy(val);
									GM_setValue("bookmark_sort_posts_by", val);
								},
								style: {
									padding: "2px 8px",
									borderRadius: "6px",
									border: "1px solid #ccc",
									backgroundColor: "#fff",
									fontSize: "12px",
									outline: "none",
									height: "26px"
								},
								children: [
									u("option", {
										value: "savedAt",
										children: T.bookmark_sort_saved_at || "Saved Date"
									}),
									u("option", {
										value: "publishTime",
										children: T.bookmark_sort_publish_time || "Publish Date"
									}),
									u("option", {
										value: "name",
										children: T.bookmark_sort_name || "Name"
									})
								]
							}) : u("select", {
								value: sortPagesBy,
								onChange: (e) => {
									const val = e.target.value;
									setSortPagesBy(val);
									GM_setValue("bookmark_sort_pages_by", val);
								},
								style: {
									padding: "2px 8px",
									borderRadius: "6px",
									border: "1px solid #ccc",
									backgroundColor: "#fff",
									fontSize: "12px",
									outline: "none",
									height: "26px"
								},
								children: [
									u("option", {
										value: "savedAt",
										children: T.bookmark_sort_saved_at || "Saved Date"
									}),
									u("option", {
										value: "lastVisitedAt",
										children: T.bookmark_sort_last_visited || "Last Visited"
									}),
									u("option", {
										value: "name",
										children: T.bookmark_sort_name || "Name"
									})
								]
							})]
						}),
						u("div", {
							style: {
								display: "flex",
								alignItems: "center",
								gap: "4px"
							},
							children: [u("span", {
								style: {
									fontSize: "12px",
									color: "#65676B"
								},
								children: [T.bookmark_folder_label || "Folder", ":"]
							}), u("select", {
								value: activeFolderId,
								onChange: (e) => setActiveFolderId(e.target.value),
								style: {
									padding: "2px 8px",
									borderRadius: "6px",
									border: "1px solid #ccc",
									backgroundColor: "#fff",
									fontSize: "12px",
									outline: "none",
									height: "26px"
								},
								children: [
									u("option", {
										value: "all",
										children: T.bookmark_folder_all || "All"
									}),
									u("option", {
										value: "root",
										children: T.bookmark_folder_root || "Uncategorized"
									}),
									folders.map((f) => u("option", {
										value: f.id,
										children: ["📁 ", f.name]
									}, f.id))
								]
							})]
						}),
						activeFolderId !== "all" && activeFolderId !== "root" && u("button", {
							onClick: () => {
								const currentFolder = folders.find((f) => f.id === activeFolderId);
								if (currentFolder) handleDeleteFolder(currentFolder.id, currentFolder.name);
							},
							style: {
								padding: "2px 8px",
								borderRadius: "6px",
								border: "1px solid #FA383E",
								backgroundColor: "#fff",
								color: "#FA383E",
								fontSize: "12px",
								cursor: "pointer",
								height: "26px"
							},
							children: ["❌ ", T.bookmark_delete_title || "Delete"]
						}),
						showFolderAddInput ? u("div", {
							style: {
								display: "flex",
								gap: "2px",
								alignItems: "center"
							},
							children: [u("input", {
								type: "text",
								placeholder: T.bookmark_add_folder || "New folder",
								value: newFolderName,
								onInput: (e) => setNewFolderName(e.target.value),
								onKeyDown: (e) => {
									if (e.key === "Enter") {
										handleAddFolder(newFolderName);
										setNewFolderName("");
										setShowFolderAddInput(false);
									} else if (e.key === "Escape") {
										setShowFolderAddInput(false);
										setNewFolderName("");
									}
								},
								style: {
									fontSize: "12px",
									padding: "2px 8px",
									borderRadius: "6px",
									border: "1px solid #1877F2",
									outline: "none",
									height: "26px",
									width: "100px",
									boxSizing: "border-box"
								},
								autoFocus: true
							}), u("button", {
								onClick: () => {
									handleAddFolder(newFolderName);
									setNewFolderName("");
									setShowFolderAddInput(false);
								},
								style: {
									padding: "2px 8px",
									borderRadius: "6px",
									border: "none",
									background: "#1877F2",
									color: "#fff",
									fontSize: "12px",
									cursor: "pointer",
									height: "26px"
								},
								children: "✓"
							})]
						}) : u("button", {
							onClick: () => setShowFolderAddInput(true),
							style: {
								padding: "2px 10px",
								borderRadius: "6px",
								border: "1px dashed #888",
								backgroundColor: "transparent",
								color: "#555",
								fontSize: "12px",
								cursor: "pointer",
								height: "26px"
							},
							children: ["📁+ ", T.bookmark_add_folder || "New Folder"]
						})
					]
				}),
				u("div", {
					style: {
						flex: 1,
						display: "flex",
						minHeight: 0
					},
					children: activeSubTab === "posts" ? filteredPosts.length === 0 ? u("div", {
						style: {
							flex: 1,
							color: "#888",
							textAlign: "center",
							padding: "32px 0"
						},
						children: T.bookmark_empty || "No bookmarks."
					}) : u("div", {
						style: {
							display: "flex",
							gap: "12px",
							flex: 1,
							minHeight: 0,
							overflow: "hidden",
							width: "100%"
						},
						children: [u("div", {
							style: {
								width: "300px",
								flexShrink: 0,
								overflowY: "auto",
								height: "100%",
								paddingRight: "2px",
								boxSizing: "border-box"
							},
							children: filteredPosts.map((post) => {
								const isSelected = activePost?.id === post.id;
								return u("div", {
									onMouseEnter: () => setActivePost(post),
									onClick: () => setActivePost(post),
									onFocus: () => setActivePost(post),
									tabIndex: 0,
									className: "gm-settings-bookmark-card",
									style: {
										display: "flex",
										justifyContent: "space-between",
										alignItems: "center",
										padding: "5px 8px",
										border: `1px solid ${isSelected ? "#1877F2" : "#eee"}`,
										borderRadius: "8px",
										marginBottom: "4px",
										gap: "6px",
										backgroundColor: isSelected ? "#F0F2F5" : "#f9f9f9",
										cursor: "pointer",
										transition: "all 0.15s ease",
										outline: "none",
										position: "relative"
									},
									children: [u("div", {
										className: "gm-settings-bookmark-text-container",
										style: {
											flex: 1,
											minWidth: 0
										},
										children: [
											u("div", {
												style: {
													display: "flex",
													gap: "6px",
													alignItems: "baseline",
													flexWrap: "nowrap",
													justifyContent: "space-between"
												},
												children: [u("span", {
													style: {
														fontWeight: "bold",
														color: "#1877F2",
														fontSize: "12px",
														whiteSpace: "nowrap",
														overflow: "hidden",
														textOverflow: "ellipsis",
														maxWidth: "160px"
													},
													title: post.authorName,
													children: post.authorName
												}), u("span", {
													className: "gm-bookmark-timestamp",
													style: {
														fontSize: "9px",
														color: "#888",
														flexShrink: 0
													},
													children: post.timestamp
												})]
											}),
											u("div", {
												style: {
													fontSize: "11px",
													color: "#555",
													marginTop: "2px",
													whiteSpace: "nowrap",
													overflow: "hidden",
													textOverflow: "ellipsis"
												},
												title: post.excerpt,
												children: post.excerpt
											}),
											post.tags && post.tags.length > 0 && u("div", {
												style: {
													display: "flex",
													flexWrap: "wrap",
													gap: "2px",
													marginTop: "3px"
												},
												children: post.tags.map((tag) => u("span", {
													style: {
														background: "#E4E6EB",
														color: "#050505",
														borderRadius: "8px",
														padding: "0px 4px",
														fontSize: "9px",
														display: "inline-block"
													},
													children: ["#", tag]
												}, tag))
											})
										]
									}), u("div", {
										className: "gm-settings-bookmark-action-buttons",
										style: {
											display: "flex",
											gap: "2px",
											alignItems: "center",
											flexShrink: 0,
											position: "absolute",
											right: "6px",
											top: "50%",
											transform: "translateY(-50%)"
										},
										onClick: (e) => e.stopPropagation(),
										children: [u("a", {
											className: "gm-settings-card-open-btn",
											href: post.url,
											target: "_blank",
											rel: "noopener",
											style: {
												fontSize: "10px",
												color: "#1877F2",
												textDecoration: "none",
												padding: "3px"
											},
											title: T.bookmark_open_original_post || "Open original post",
											children: "↗️"
										}), u(DeleteConfirmButton$1, {
											onDelete: () => handleDeletePost(post.id),
											title: T.bookmark_post_removed || "Remove bookmark",
											T
										})]
									})]
								}, post.id);
							})
						}), u("div", {
							style: {
								flex: 1,
								minWidth: 0,
								borderLeft: "1px solid #ddd",
								paddingLeft: "12px",
								display: "flex",
								flexDirection: "column",
								height: "100%",
								boxSizing: "border-box"
							},
							children: activePost ? u("div", {
								style: {
									display: "flex",
									flexDirection: "column",
									flex: 1,
									minHeight: 0,
									gap: "4px"
								},
								children: [
									u("div", {
										style: {
											marginBottom: "2px",
											flexShrink: 0,
											display: "flex",
											alignItems: "center",
											justifyContent: "space-between"
										},
										children: [u("div", {
											style: {
												display: "flex",
												alignItems: "baseline",
												gap: "6px"
											},
											children: [u("a", {
												href: activePost.authorLink,
												target: "_blank",
												rel: "noopener",
												style: {
													fontWeight: "bold",
													color: "#1877F2",
													textDecoration: "none",
													fontSize: "14px"
												},
												children: activePost.authorName
											}), u("span", {
												style: {
													fontSize: "11px",
													color: "#888"
												},
												children: ["• ", activePost.timestamp]
											})]
										}), u("div", {
											style: {
												display: "flex",
												gap: "6px",
												alignItems: "center"
											},
											children: [u(PreviewCopyLinkButton, {
												url: activePost.url,
												app,
												T
											}), u(PreviewCopyContentButton, {
												post: activePost,
												app,
												T
											})]
										})]
									}),
									u("div", {
										style: {
											padding: "4px 6px",
											backgroundColor: "#F0F2F5",
											borderRadius: "6px",
											display: "flex",
											flexDirection: "column",
											gap: "3px",
											fontSize: "12px",
											border: "1px solid #E4E6EB",
											flexShrink: 0
										},
										children: [u("div", {
											style: {
												display: "flex",
												gap: "8px",
												alignItems: "center",
												flexWrap: "wrap"
											},
											children: [u("div", {
												style: {
													display: "flex",
													alignItems: "center",
													gap: "4px",
													flex: 1,
													minWidth: "120px"
												},
												children: [u("span", {
													style: {
														fontWeight: "bold",
														color: "#65676B"
													},
													children: "📁"
												}), u("select", {
													value: activePost.folderId || "",
													onChange: (e) => movePostToFolder(activePost, e.target.value || null),
													style: {
														padding: "1px 4px",
														borderRadius: "4px",
														border: "1px solid #ccc",
														fontSize: "12px",
														outline: "none",
														width: "100%",
														backgroundColor: "#fff",
														height: "20px"
													},
													children: [u("option", {
														value: "",
														children: T.bookmark_folder_root || "Uncategorized"
													}), folders.map((f) => u("option", {
														value: f.id,
														children: f.name
													}, f.id))]
												})]
											}), u("div", {
												style: {
													display: "flex",
													alignItems: "center",
													gap: "4px",
													flex: 1,
													minWidth: "120px"
												},
												children: [u("span", {
													style: {
														fontWeight: "bold",
														color: "#65676B"
													},
													children: "🏷️"
												}), u("input", {
													type: "text",
													placeholder: T.bookmark_add_tag_placeholder || "Add tag...",
													value: newTagInput,
													onInput: (e) => setNewTagInput(e.target.value),
													onKeyDown: (e) => {
														if (e.key === "Enter") {
															addPostTag(activePost, newTagInput);
															setNewTagInput("");
														}
													},
													style: {
														padding: "1px 4px",
														fontSize: "12px",
														borderRadius: "4px",
														border: "1px solid #ccc",
														width: "100%",
														outline: "none",
														boxSizing: "border-box",
														height: "20px"
													}
												})]
											})]
										}), activePost.tags && activePost.tags.length > 0 && u("div", {
											style: {
												display: "flex",
												flexWrap: "wrap",
												gap: "3px",
												marginTop: "2px"
											},
											children: activePost.tags.map((tag) => u("span", {
												style: {
													background: "#E4E6EB",
													color: "#050505",
													borderRadius: "10px",
													padding: "1px 6px",
													fontSize: "11px",
													display: "inline-flex",
													alignItems: "center",
													gap: "2px"
												},
												children: [
													"#",
													tag,
													u("span", {
														className: "gm-tag-badge-remove-btn",
														style: {
															cursor: "pointer",
															color: "#888",
															fontWeight: "bold"
														},
														onClick: () => removePostTag(activePost, tag),
														children: "×"
													})
												]
											}, tag))
										})]
									}),
									u("div", {
										style: {
											flex: 1,
											overflowY: "auto",
											backgroundColor: "#ffffff",
											border: "1px solid #e0e0e0",
											borderRadius: "6px",
											padding: "6px 8px",
											fontSize: "13px",
											lineHeight: "1.4",
											color: "#1c1e21",
											fontFamily: "inherit",
											display: "flex",
											flexDirection: "column",
											gap: "5px",
											boxSizing: "border-box"
										},
										children: [
											renderPostMetadata(activePost),
											u("div", {
												style: {
													whiteSpace: "pre-wrap",
													wordBreak: "break-word"
												},
												children: activePost.content || activePost.excerpt
											}),
											activePost.sharedPost && renderSharedPost(activePost.sharedPost),
											activePost.media?.linkPreview && renderLinkPreview(activePost.media.linkPreview)
										]
									})
								]
							}) : u("div", {
								style: {
									flex: 1,
									display: "flex",
									alignItems: "center",
									justifyContent: "center",
									color: "#888",
									fontSize: "12px",
									textAlign: "center",
									border: "1px dashed #ccc",
									borderRadius: "6px",
									padding: "16px"
								},
								children: T.bookmark_hover_preview_hint || "Hover or click a post to view full content"
							})
						})]
					}) : u("div", {
						style: {
							flex: 1,
							overflowY: "auto",
							height: "100%",
							paddingRight: "4px"
						},
						children: filteredPages.length === 0 ? u("div", {
							style: {
								color: "#888",
								textAlign: "center",
								padding: "32px 0"
							},
							children: T.bookmark_empty || "No bookmarks."
						}) : filteredPages.map((page) => {
							const folder = folders.find((f) => f.id === page.folderId);
							const folderName = folder ? folder.name : T.bookmark_folder_root || "Uncategorized";
							const isEditing = editingPageTagsUrl === page.url;
							return u("div", {
								className: "gm-settings-page-card",
								children: [u("div", {
									className: "gm-settings-page-info",
									style: isEditing ? { paddingRight: "220px" } : void 0,
									children: [
										u("a", {
											href: page.url,
											target: "_blank",
											rel: "noopener",
											style: {
												fontWeight: "bold",
												color: "#1877F2",
												textDecoration: "none",
												fontSize: "14px",
												display: "block",
												whiteSpace: "nowrap",
												overflow: "hidden",
												textOverflow: "ellipsis"
											},
											children: page.title
										}),
										page.desc && u("div", {
											style: {
												fontSize: "12px",
												color: "#65676B",
												marginTop: "2px",
												lineHeight: "1.4",
												wordBreak: "break-word",
												whiteSpace: "pre-wrap"
											},
											children: page.desc
										}),
										u("div", {
											style: {
												display: "flex",
												gap: "12px",
												alignItems: "center",
												marginTop: "2px",
												flexWrap: "wrap"
											},
											children: [
												u("span", {
													style: {
														fontSize: "11px",
														color: "#888",
														overflow: "hidden",
														textOverflow: "ellipsis",
														maxWidth: "280px"
													},
													children: ["🔗 ", page.url]
												}),
												u("span", {
													style: {
														fontSize: "11px",
														color: "#888"
													},
													children: ["🕒 ", formatLastVisited(page.lastVisitedAt || page.savedAt, T)]
												}),
												u("span", {
													style: {
														fontSize: "11px",
														color: "#888"
													},
													children: ["📁 ", folderName]
												})
											]
										}),
										page.tags && page.tags.length > 0 && u("div", {
											style: {
												display: "flex",
												flexWrap: "wrap",
												gap: "3px",
												marginTop: "4px"
											},
											children: page.tags.map((tag) => u("span", {
												style: {
													background: "#E4E6EB",
													color: "#050505",
													borderRadius: "10px",
													padding: "1px 6px",
													fontSize: "10px",
													display: "inline-flex",
													alignItems: "center",
													gap: "2px"
												},
												children: [
													"#",
													tag,
													u("span", {
														className: "gm-tag-badge-remove-btn",
														style: {
															cursor: "pointer",
															color: "#888",
															fontWeight: "bold"
														},
														onClick: () => removePageTag(page, tag),
														children: "×"
													})
												]
											}, tag))
										})
									]
								}), u("div", {
									className: "gm-settings-page-actions",
									style: isEditing ? {
										opacity: 1,
										pointerEvents: "auto"
									} : void 0,
									children: [
										u("div", {
											style: {
												display: "flex",
												alignItems: "center",
												gap: "4px"
											},
											children: u("select", {
												value: page.folderId || "",
												onChange: (e) => movePageToFolder(page, e.target.value || null),
												style: {
													padding: "2px 4px",
													borderRadius: "4px",
													border: "1px solid #ccc",
													fontSize: "11px",
													outline: "none",
													height: "24px",
													backgroundColor: "#fff"
												},
												children: [u("option", {
													value: "",
													children: T.bookmark_folder_root || "Uncategorized"
												}), folders.map((f) => u("option", {
													value: f.id,
													children: f.name
												}, f.id))]
											})
										}),
										isEditing ? u("div", {
											style: {
												display: "flex",
												gap: "2px",
												alignItems: "center"
											},
											children: u("input", {
												type: "text",
												placeholder: T.bookmark_add_tag_placeholder || "Type tag and Enter...",
												value: newPageTagInput,
												onInput: (e) => setNewPageTagInput(e.target.value),
												onKeyDown: (e) => {
													if (e.key === "Enter") {
														addPageTag(page, newPageTagInput);
														setNewPageTagInput("");
														setEditingPageTagsUrl(null);
													} else if (e.key === "Escape") setEditingPageTagsUrl(null);
												},
												onBlur: () => {
													setTimeout(() => setEditingPageTagsUrl(null), 200);
												},
												style: {
													padding: "2px 4px",
													border: "1px solid #1877F2",
													borderRadius: "4px",
													fontSize: "11px",
													outline: "none",
													width: "100px",
													height: "24px",
													boxSizing: "border-box"
												},
												autoFocus: true
											})
										}) : u("button", {
											onClick: () => {
												setNewPageTagInput("");
												setEditingPageTagsUrl(page.url);
											},
											style: {
												padding: "2px 6px",
												borderRadius: "4px",
												border: "1px dashed #888",
												backgroundColor: "transparent",
												fontSize: "11px",
												cursor: "pointer",
												height: "24px",
												display: "inline-flex",
												alignItems: "center",
												transition: "all 0.15s"
											},
											children: ["🏷️+ ", T.bookmark_add_tag_btn || "Add Tag"]
										}),
										u(DeleteConfirmButton$1, {
											onDelete: () => handleDeletePage(page.url),
											title: T.bookmark_page_action_remove_title || "Remove page bookmark",
											T
										})
									]
								})]
							}, page.url);
						})
					})
				})
			]
		});
	};
	var SettingsComponent = ({ app, signals, initialTab, onClose, onSave, onReset }) => {
		const T = app.state.T;
		const SM = app.modules.settingsManager;
		const [activeTab, setActiveTab] = d$2(initialTab || "general");
		const handleExport = () => {
			const backup = {
				posts: BookmarkStorage.getAll(),
				pages: GM_getValue("bookmarked_pages", []),
				folders: GM_getValue("bookmarked_folders", []),
				exportedAt: Date.now()
			};
			const blob = new Blob([JSON.stringify(backup, null, 2)], { type: "application/json" });
			const url = URL.createObjectURL(blob);
			const link = document.createElement("a");
			link.href = url;
			link.download = `FB_Bookmarks_Backup_${new Date().toISOString().slice(0, 10)}.json`;
			link.click();
			URL.revokeObjectURL(url);
		};
		const handleClearAll = () => {
			showCustomConfirm$1(app, T.bookmark_confirm_clear || "Clear all bookmarks?", () => {
				BookmarkStorage.save([]);
				GM_setValue("bookmarked_pages", []);
				const PHT = app.modules.postHeaderTools;
				if (PHT) PHT.reEvaluateAllButtons();
				const FN = app.modules.floatingNavigator;
				if (FN) FN.updateVisibility();
			});
		};
		y$2(() => {
			if (initialTab) setActiveTab(initialTab);
		}, [initialTab]);
		y$2(() => {
			const modalEl = document.querySelector(".gm-settings-modal");
			if (modalEl) if (activeTab === "bookmarks") modalEl.classList.add("wide");
			else modalEl.classList.remove("wide");
			return () => {
				if (modalEl) modalEl.classList.remove("wide");
			};
		}, [activeTab]);
		const groups = [
			{
				id: "general",
				title: T.settingsColumnGeneral || "General"
			},
			{
				id: "navigation",
				title: T.settingsColumnNavigation || "Navigation"
			},
			{
				id: "tools",
				title: T.settingsColumnTools || "Tools"
			},
			{
				id: "bookmarks",
				title: T.settingsColumnBookmarks || "Bookmarks"
			}
		];
		const currentDefinitions = SM.definitions.filter((def) => def.group === activeTab);
		const metaKeys = [
			"copy_meta_url",
			"copy_meta_order",
			"copy_meta_author_name",
			"copy_meta_author_link",
			"copy_meta_date",
			"copy_meta_stats",
			"copy_meta_link_preview",
			"copy_meta_image_count",
			"copy_meta_video_duration",
			"copy_meta_stats_total",
			"copy_meta_stats_detailed"
		];
		return u(S$1, { children: [
			u("div", {
				className: "gm-settings-header",
				children: [u("h2", {
					className: "gm-settings-title",
					children: T.settingsTitle || "Settings"
				}), u("button", {
					className: "gm-settings-close-btn",
					onClick: onClose,
					children: "×"
				})]
			}),
			u("div", {
				className: "gm-settings-body",
				children: [u("div", {
					className: "gm-settings-sidebar",
					children: groups.map((group) => u("button", {
						className: `gm-tab-btn ${activeTab === group.id ? "active" : ""}`,
						onClick: () => setActiveTab(group.id),
						children: group.title
					}, group.id))
				}), u("div", {
					className: "gm-settings-content",
					children: u("div", {
						className: "gm-panel active",
						children: [u("h3", {
							style: {
								margin: "0 0 4px 0",
								fontSize: "18px",
								borderBottom: "1px solid #eee",
								paddingBottom: "4px"
							},
							children: groups.find((g) => g.id === activeTab)?.title
						}), activeTab === "bookmarks" ? u(BookmarksPanel, { app }) : u("div", {
							className: "gm-grid-hybrid",
							children: currentDefinitions.map((def) => {
								if (def.key === "copy_includeMetadata") {
									const metadataSubDefs = SM.definitions.filter((d) => metaKeys.includes(d.key));
									return u(S$1, { children: [u(SettingRow, {
										def,
										signals,
										app,
										isGrid: true
									}), u("details", {
										className: "gm-details span-2",
										children: [u("summary", {
											className: "gm-summary",
											children: T.settingsDetailsMetadata || "Advanced Metadata Settings"
										}), u("div", {
											className: "gm-details-content",
											children: metadataSubDefs.map((subDef) => u(SettingRow, {
												def: subDef,
												signals,
												app,
												isGrid: false
											}, subDef.key))
										})]
									})] }, def.key);
								}
								if (metaKeys.includes(def.key)) return null;
								return u(SettingRow, {
									def,
									signals,
									app,
									isGrid: true
								}, def.key);
							})
						})]
					})
				})]
			}),
			u("div", {
				className: "gm-settings-footer",
				children: activeTab === "bookmarks" ? u(S$1, { children: [u("button", {
					className: "gm-settings-export-btn",
					onClick: handleExport,
					children: T.bookmark_export_btn || "Export Bookmarks (JSON)"
				}), u("div", {
					style: {
						display: "flex",
						gap: "8px"
					},
					children: u("button", {
						className: "gm-settings-clear-all-btn",
						onClick: handleClearAll,
						children: T.bookmark_clear_btn || "Clear All Bookmarks"
					})
				})] }) : u(S$1, { children: [u("button", {
					className: "gm-btn-reset",
					onClick: onReset,
					children: T.resetSettings || "Reset Settings"
				}), u("div", {
					style: {
						display: "flex",
						gap: "8px"
					},
					children: u("button", {
						className: "gm-btn-save",
						onClick: onSave,
						children: T.saveAndClose || "Save & Close"
					})
				})] })
			})
		] });
	};
	var SettingsModal = class {
		app;
		backdropEl = null;
		modalEl = null;
		signals = {};
		constructor(app) {
			this.app = app;
		}
		open(initialTab = "general") {
			const T = this.app.state.T;
			const SM = this.app.modules.settingsManager;
			SM.definitions.forEach((def) => {
				if (!this.signals[def.key]) this.signals[def.key] = y$1(this.app.state.settings[def.key]);
				else this.signals[def.key].value = this.app.state.settings[def.key];
			});
			if (!this.backdropEl || !this.modalEl) {
				this.backdropEl = document.createElement("div");
				this.backdropEl.className = "gm-settings-backdrop";
				this.backdropEl.style.display = "none";
				document.body.appendChild(this.backdropEl);
				this.modalEl = document.createElement("div");
				this.modalEl.className = "gm-settings-modal";
				this.modalEl.style.display = "none";
				document.body.appendChild(this.modalEl);
				const preventDefault = (e) => {
					e.preventDefault();
					e.stopPropagation();
				};
				this.backdropEl.addEventListener("wheel", preventDefault, { passive: false });
				this.backdropEl.addEventListener("touchmove", preventDefault, { passive: false });
				this.backdropEl.addEventListener("click", () => this.close());
			}
			document.body.style.overflow = "hidden";
			R(u(SettingsComponent, {
				app: this.app,
				signals: this.signals,
				initialTab,
				onClose: () => this.close(),
				onSave: () => this.saveAndClose(),
				onReset: () => {
					showCustomConfirm$1(this.app, T.resetSettingsConfirm || "Reset settings to default?", () => {
						SM.resetAllSettings();
						SM.definitions.forEach((def) => {
							this.signals[def.key].value = this.app.state.settings[def.key];
						});
						if (this.app.modules.toastNotifier) this.app.modules.toastNotifier.show(T.notificationSettingsReset || "Settings reset", "success");
					});
				}
			}, Date.now().toString()), this.modalEl);
			this.backdropEl.style.display = "block";
			this.modalEl.style.display = "flex";
			requestAnimationFrame(() => {
				this.backdropEl?.classList.add("open");
				this.modalEl?.classList.add("open");
			});
		}
		close() {
			if (this.backdropEl && this.modalEl) {
				this.backdropEl.classList.remove("open");
				this.modalEl.classList.remove("open");
				document.body.style.overflow = "";
				setTimeout(() => {
					if (this.backdropEl && this.modalEl) {
						this.backdropEl.style.display = "none";
						this.modalEl.style.display = "none";
						R(null, this.modalEl);
					}
				}, 300);
			}
		}
		saveAndClose() {
			if (this.app.modules.settingsManager.definitions.some((def) => {
				return def.needsReload && this.app.state.settings[def.key] !== GM_getValue(def.key);
			}) && this.app.modules.toastNotifier) this.app.modules.toastNotifier.show(this.app.state.T.notificationSettingsReload || "Some settings updated. Please reload.", "success");
			this.close();
		}
	};
	var SettingsManager = class {
		app;
		definitions = [];
		registeredCommands = [];
		defaults = {
			LINK_DETRACKER: true,
			AUTO_OPEN_MEDIA: true,
			HIDE_USELESS: true,
			HIDE_STATS: false,
			SHOW_DEADLOCK: true,
			ERROR_RECOVERY: true,
			TRANSPARENCY_BTNS: true,
			ID_REVEALER: true,
			ID_LINK_FORMAT: "userid",
			AUTO_UNMUTE: true,
			UNMUTE_VOLUME: 25,
			POST_NUMBERING: true,
			EXPAND_CONTENT: true,
			KEY_NAV: true,
			KEY_NEXT_PRI: "j",
			KEY_PREV_PRI: "k",
			KEY_NEXT_SEC: "ArrowRight",
			KEY_PREV_SEC: "ArrowLeft",
			FLOATING_NAV: true,
			SHOW_AUTO_LOAD: true,
			SHOW_BATCH_COPY: true,
			FLOATING_OPACITY: true,
			BATCH_SIZE: 20,
			TIMELINE_NAV: true,
			NAV_HIGHLIGHTER: true,
			HEATMAP_BORDER: true,
			TIMELINE_HEATMAP: true,
			WHEEL_NAV: true,
			WHEEL_MODIFIER: "shiftKey",
			SCROLL_ALIGNMENT: "top",
			RESTORE_ALIGNMENT: "bottom",
			SMOOTH_SCROLL: true,
			NAV_INTERVAL: 500,
			PERMALINK_COPIER: true,
			COPY_CONTENT_BTN: true,
			SCREENSHOT_ENABLED: true,
			SMART_LINK: true,
			INCLUDE_EMOJIS: true,
			BATCH_HEADER: true,
			EXPAND_HASHTAGS: false,
			EXPAND_MENTIONS: true,
			META_MASTER: true,
			META_URL: true,
			META_ORDER: true,
			META_AUTHOR: true,
			META_AUTHOR_LINK: true,
			META_DATE: true,
			META_ABSOLUTE_DATE: true,
			META_PREVIEW: true,
			META_IMG_COUNT: true,
			META_VID_DURATION: true,
			META_STATS: true,
			META_STATS_TOTAL: true,
			META_STATS_DETAILED: true,
			PERMALINK_FORMAT: "author_id",
			BATCH_EXPORT_FORMAT: "json",
			BATCH_COPY_MODE: "file",
			EXCLUDE_TRANSLATION: false,
			BOOKMARKS_ENABLED: true,
			BOOKMARK_POSITION: "left",
			APP_LANGUAGE: "auto",
			TOOLS_POSITION: "inner-right",
			SCREENSHOT_SCALE: 1,
			SCREENSHOT_EXCLUDE_COMMENTS: true,
			SCREENSHOT_FORMAT: "jpeg",
			SCREENSHOT_EMBED_LINK: true
		};
		constructor(app) {
			this.app = app;
		}
		_getDefinitions() {
			const D = this.defaults;
			const generalSettings = [
				{
					key: "linkDetrackerEnabled",
					type: "boolean",
					defaultValue: D.LINK_DETRACKER,
					labelKey: "linkDetrackerEnabled",
					group: "general"
				},
				{
					key: "autoOpenMediaInNewTab",
					type: "boolean",
					defaultValue: D.AUTO_OPEN_MEDIA,
					labelKey: "autoOpenMediaInNewTab",
					group: "general"
				},
				{
					key: "hideUselessElements",
					type: "boolean",
					defaultValue: D.HIDE_USELESS,
					labelKey: "hideUselessElements",
					group: "general",
					needsReload: true
				},
				{
					key: "hidePostStats",
					type: "boolean",
					defaultValue: D.HIDE_STATS,
					labelKey: "hidePostStats",
					group: "general",
					instant: true
				},
				{
					key: "showDeadlockNotification",
					type: "boolean",
					defaultValue: D.SHOW_DEADLOCK,
					labelKey: "showDeadlockNotification",
					group: "general"
				},
				{
					key: "errorRecoveryEnabled",
					type: "boolean",
					defaultValue: D.ERROR_RECOVERY,
					labelKey: "errorRecoveryEnabled",
					group: "general"
				},
				{
					key: "transparencyButtonsEnabled",
					type: "boolean",
					defaultValue: D.TRANSPARENCY_BTNS,
					labelKey: "transparencyButtonsEnabled",
					group: "general"
				},
				{
					key: "idRevealerEnabled",
					type: "boolean",
					defaultValue: D.ID_REVEALER,
					labelKey: "idRevealerEnabled",
					group: "general"
				},
				{
					key: "idRevealerLinkFormat",
					type: "select",
					defaultValue: D.ID_LINK_FORMAT,
					labelKey: "idRevealerLinkFormat",
					options: [
						{
							value: "userid",
							labelKey: "idFormatUserID"
						},
						{
							value: "classic",
							labelKey: "idFormatClassic"
						},
						{
							value: "username",
							labelKey: "idFormatUsername"
						}
					],
					group: "general"
				},
				{
					key: "autoUnmuteEnabled",
					type: "boolean",
					defaultValue: D.AUTO_UNMUTE,
					labelKey: "autoUnmuteEnabled",
					group: "general",
					instant: true
				},
				{
					key: "autoUnmuteVolume",
					type: "range",
					defaultValue: D.UNMUTE_VOLUME,
					labelKey: "setVolumeLabel",
					options: {
						min: 0,
						max: 100,
						step: 5,
						unit: "%"
					},
					group: "general",
					instant: true
				},
				{
					key: "postNumberingEnabled",
					type: "boolean",
					defaultValue: D.POST_NUMBERING,
					labelKey: "postNumberingEnabled",
					group: "general"
				},
				{
					key: "expandContentEnabled",
					type: "boolean",
					defaultValue: D.EXPAND_CONTENT,
					labelKey: "expandContentEnabled",
					group: "general"
				},
				{
					key: "appLanguage",
					type: "select",
					defaultValue: D.APP_LANGUAGE,
					labelKey: "appLanguage",
					options: [
						{
							value: "auto",
							labelKey: "langAuto"
						},
						{
							value: "en",
							labelKey: "langEN"
						},
						{
							value: "zh-TW",
							labelKey: "langZH"
						},
						{
							value: "ja",
							labelKey: "langJA"
						}
					],
					group: "general",
					needsReload: true
				}
			];
			const navigationSettings = [
				{
					key: "keyboardNavEnabled",
					type: "boolean",
					defaultValue: D.KEY_NAV,
					labelKey: "keyboardNavEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "keyNavNextPrimary",
					type: "keybinder",
					defaultValue: D.KEY_NEXT_PRI,
					labelKey: "keyNavNextPrimary",
					group: "navigation",
					instant: true
				},
				{
					key: "keyNavPrevPrimary",
					type: "keybinder",
					defaultValue: D.KEY_PREV_PRI,
					labelKey: "keyNavPrevPrimary",
					group: "navigation",
					instant: true
				},
				{
					key: "keyNavNextSecondary",
					type: "keybinder",
					defaultValue: D.KEY_NEXT_SEC,
					labelKey: "keyNavNextSecondary",
					group: "navigation",
					instant: true
				},
				{
					key: "keyNavPrevSecondary",
					type: "keybinder",
					defaultValue: D.KEY_PREV_SEC,
					labelKey: "keyNavPrevSecondary",
					group: "navigation",
					instant: true
				},
				{
					key: "floatingNavEnabled",
					type: "boolean",
					defaultValue: D.FLOATING_NAV,
					labelKey: "floatingNavEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "floatingNav_showAutoLoad",
					type: "boolean",
					defaultValue: D.SHOW_AUTO_LOAD,
					labelKey: "floatingNav_showAutoLoad",
					group: "navigation",
					instant: true
				},
				{
					key: "floatingNav_showBatchCopy",
					type: "boolean",
					defaultValue: D.SHOW_BATCH_COPY,
					labelKey: "floatingNav_showBatchCopy",
					group: "navigation",
					instant: true
				},
				{
					key: "batchExportFormat",
					type: "select",
					defaultValue: D.BATCH_EXPORT_FORMAT,
					labelKey: "setting_batchExportFormat",
					options: [
						{
							value: "text",
							labelKey: "exportFormat_text"
						},
						{
							value: "json",
							labelKey: "exportFormat_json"
						},
						{
							value: "csv",
							labelKey: "exportFormat_csv"
						}
					],
					tooltipKey: "tooltip_batchExportFormat",
					group: "navigation",
					instant: true
				},
				{
					key: "batchCopyMode",
					type: "select",
					defaultValue: D.BATCH_COPY_MODE,
					labelKey: "setting_batchCopyMode",
					options: [{
						value: "file",
						labelKey: "batchCopyMode_file"
					}, {
						value: "clipboard",
						labelKey: "batchCopyMode_clipboard"
					}],
					group: "navigation",
					instant: true
				},
				{
					key: "autoLoadBatchSize",
					type: "range",
					defaultValue: D.BATCH_SIZE,
					labelKey: "autoLoader_batchSize",
					options: {
						min: 10,
						max: 200,
						step: 5,
						unit: ""
					},
					group: "navigation"
				},
				{
					key: "timelineNavEnabled",
					type: "boolean",
					defaultValue: D.TIMELINE_NAV,
					labelKey: "timelineNavEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "navHighlighterEnabled",
					type: "boolean",
					defaultValue: D.NAV_HIGHLIGHTER,
					labelKey: "navHighlighterEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "heatmapBorderEnabled",
					type: "boolean",
					defaultValue: D.HEATMAP_BORDER,
					labelKey: "heatmapBorderEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "timelineHeatmapEnabled",
					type: "boolean",
					defaultValue: D.TIMELINE_HEATMAP,
					labelKey: "timelineHeatmapEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "wheelNavEnabled",
					type: "boolean",
					defaultValue: D.WHEEL_NAV,
					labelKey: "wheelNavEnabled",
					group: "navigation",
					instant: true
				},
				{
					key: "wheelNavModifier",
					type: "select",
					defaultValue: D.WHEEL_MODIFIER,
					labelKey: "wheelNavModifier",
					options: [
						{
							value: "altKey",
							labelKey: "modifierAlt"
						},
						{
							value: "ctrlKey",
							labelKey: "modifierCtrl"
						},
						{
							value: "shiftKey",
							labelKey: "modifierShift"
						},
						{
							value: "none",
							labelKey: "modifierNone"
						}
					],
					group: "navigation",
					instant: true
				},
				{
					key: "navigationScrollAlignment",
					type: "select",
					defaultValue: D.SCROLL_ALIGNMENT,
					labelKey: "navigationScrollAlignment",
					options: [
						{
							value: "center",
							labelKey: "scrollAlignmentCenter"
						},
						{
							value: "top",
							labelKey: "scrollAlignmentTop"
						},
						{
							value: "bottom",
							labelKey: "scrollAlignmentBottom"
						}
					],
					group: "navigation",
					instant: true
				},
				{
					key: "scrollRestorerAlignment",
					type: "select",
					defaultValue: D.RESTORE_ALIGNMENT,
					labelKey: "scrollRestorerAlignment",
					options: [
						{
							value: "center",
							labelKey: "scrollAlignmentCenter"
						},
						{
							value: "top",
							labelKey: "scrollAlignmentTop"
						},
						{
							value: "bottom",
							labelKey: "scrollAlignmentBottom"
						}
					],
					group: "navigation",
					instant: true
				},
				{
					key: "enableSmoothScrolling",
					type: "boolean",
					defaultValue: D.SMOOTH_SCROLL,
					labelKey: "enableSmoothScrolling",
					group: "navigation",
					instant: true
				},
				{
					key: "floatingNavOpacity",
					type: "boolean",
					defaultValue: D.FLOATING_OPACITY,
					labelKey: "floatingNav_opacity",
					group: "navigation",
					instant: true
				},
				{
					key: "continuousNavInterval",
					type: "range",
					defaultValue: D.NAV_INTERVAL,
					labelKey: "continuousNavInterval",
					options: {
						min: 0,
						max: 1e3,
						step: 50,
						unit: "ms"
					},
					group: "navigation"
				}
			];
			const toolsSettings = [
				{
					key: "permalinkCopierEnabled",
					type: "boolean",
					defaultValue: D.PERMALINK_COPIER,
					labelKey: "copier_enablePermalink",
					group: "tools",
					instant: true
				},
				{
					key: "enableCopyContentButton",
					type: "boolean",
					defaultValue: D.COPY_CONTENT_BTN,
					labelKey: "copier_enableCopyContent",
					group: "tools",
					instant: true
				},
				{
					key: "screenshotEnabled",
					type: "boolean",
					defaultValue: D.SCREENSHOT_ENABLED,
					labelKey: "screenshotEnabled",
					group: "tools",
					instant: true
				},
				{
					key: "copier_useSmartLink",
					type: "boolean",
					defaultValue: D.SMART_LINK,
					labelKey: "copier_menu_useSmartLink",
					group: "tools",
					instant: true
				},
				{
					key: "copier_includeEmojis",
					type: "boolean",
					defaultValue: D.INCLUDE_EMOJIS,
					labelKey: "copier_includeEmojis",
					group: "tools",
					instant: true
				},
				{
					key: "batchCopy_includeHeader",
					type: "boolean",
					defaultValue: D.BATCH_HEADER,
					labelKey: "batchCopy_includeHeader",
					group: "tools"
				},
				{
					key: "copier_expandHashtags",
					type: "boolean",
					defaultValue: D.EXPAND_HASHTAGS,
					labelKey: "copier_expandHashtags",
					group: "tools"
				},
				{
					key: "copier_expandMentions",
					type: "boolean",
					defaultValue: D.EXPAND_MENTIONS,
					labelKey: "copier_expand_mentions",
					group: "tools"
				},
				{
					key: "copy_includeMetadata",
					type: "boolean",
					defaultValue: D.META_MASTER,
					labelKey: "copy_includeMetadata",
					group: "tools",
					instant: true
				},
				{
					key: "copy_meta_url",
					type: "boolean",
					defaultValue: D.META_URL,
					labelKey: "copy_meta_url",
					group: "tools"
				},
				{
					key: "copy_meta_order",
					type: "boolean",
					defaultValue: D.META_ORDER,
					labelKey: "copy_meta_order",
					group: "tools"
				},
				{
					key: "copy_meta_author_name",
					type: "boolean",
					defaultValue: D.META_AUTHOR,
					labelKey: "copy_meta_author_name",
					group: "tools"
				},
				{
					key: "copy_meta_author_link",
					type: "boolean",
					defaultValue: D.META_AUTHOR_LINK,
					labelKey: "copy_meta_author_link",
					group: "tools"
				},
				{
					key: "copy_meta_date",
					type: "boolean",
					defaultValue: D.META_DATE,
					labelKey: "copy_meta_date",
					group: "tools"
				},
				{
					key: "copy_meta_absolute_date",
					type: "boolean",
					defaultValue: D.META_ABSOLUTE_DATE,
					labelKey: "copy_meta_absolute_date",
					group: "tools"
				},
				{
					key: "copy_meta_link_preview",
					type: "boolean",
					defaultValue: D.META_PREVIEW,
					labelKey: "copy_meta_link_preview",
					group: "tools"
				},
				{
					key: "copy_meta_image_count",
					type: "boolean",
					defaultValue: D.META_IMG_COUNT,
					labelKey: "copy_meta_image_count",
					group: "tools"
				},
				{
					key: "copy_meta_video_duration",
					type: "boolean",
					defaultValue: D.META_VID_DURATION,
					labelKey: "copy_meta_video_duration",
					group: "tools"
				},
				{
					key: "copy_meta_stats",
					type: "boolean",
					defaultValue: D.META_STATS,
					labelKey: "copy_meta_stats",
					group: "tools"
				},
				{
					key: "copy_meta_stats_total",
					type: "boolean",
					defaultValue: D.META_STATS_TOTAL,
					labelKey: "copy_meta_stats_total",
					group: "tools"
				},
				{
					key: "copy_meta_stats_detailed",
					type: "boolean",
					defaultValue: D.META_STATS_DETAILED,
					labelKey: "copy_meta_stats_detailed",
					group: "tools"
				},
				{
					key: "copier_permalinkFormat",
					type: "select",
					defaultValue: D.PERMALINK_FORMAT,
					labelKey: "copier_menu_permalinkFormat",
					options: [
						{
							value: "author_id",
							labelKey: "copier_format_author_id"
						},
						{
							value: "username",
							labelKey: "copier_format_username"
						},
						{
							value: "full",
							labelKey: "copier_format_full"
						},
						{
							value: "shortest",
							labelKey: "copier_format_shortest"
						}
					],
					group: "tools"
				},
				{
					key: "excludeTranslation",
					type: "boolean",
					defaultValue: D.EXCLUDE_TRANSLATION,
					labelKey: "excludeTranslation",
					group: "tools"
				},
				{
					key: "enableBookmarks",
					type: "boolean",
					defaultValue: D.BOOKMARKS_ENABLED,
					labelKey: "enableBookmarksLabel",
					group: "tools",
					instant: true
				},
				{
					key: "bookmarkPosition",
					type: "select",
					defaultValue: D.BOOKMARK_POSITION,
					labelKey: "bookmarkPositionLabel",
					options: [{
						value: "left",
						labelKey: "bookmarkPositionLeft"
					}, {
						value: "right",
						labelKey: "bookmarkPositionRight"
					}],
					group: "tools",
					instant: true
				},
				{
					key: "toolsPosition",
					type: "select",
					defaultValue: D.TOOLS_POSITION,
					labelKey: "setting_toolsPosition",
					options: [{
						value: "inner-right",
						labelKey: "toolsPositionInnerRight"
					}, {
						value: "outer-right",
						labelKey: "toolsPositionOuterRight"
					}],
					group: "tools",
					instant: true
				},
				{
					key: "screenshotScale",
					type: "select",
					defaultValue: D.SCREENSHOT_SCALE,
					labelKey: "setting_screenshotScale",
					options: [
						{
							value: 1,
							labelKey: "scale_1x"
						},
						{
							value: 2,
							labelKey: "scale_2x"
						},
						{
							value: 3,
							labelKey: "scale_3x"
						}
					],
					group: "tools",
					instant: true
				},
				{
					key: "screenshotExcludeComments",
					type: "boolean",
					defaultValue: D.SCREENSHOT_EXCLUDE_COMMENTS,
					labelKey: "setting_screenshotExcludeComments",
					group: "tools",
					instant: true
				},
				{
					key: "screenshotFormat",
					type: "select",
					defaultValue: D.SCREENSHOT_FORMAT,
					labelKey: "setting_screenshotFormat",
					options: [{
						value: "png",
						labelKey: "format_png"
					}, {
						value: "jpeg",
						labelKey: "format_jpeg"
					}],
					group: "tools",
					instant: true
				},
				{
					key: "screenshotEmbedLink",
					type: "boolean",
					defaultValue: D.SCREENSHOT_EMBED_LINK,
					labelKey: "setting_screenshotEmbedLink",
					group: "tools",
					instant: true
				}
			];
			return [
				...generalSettings,
				...navigationSettings,
				...toolsSettings
			];
		}
		init() {
			this.definitions = this._getDefinitions();
			this.definitions.forEach((def) => {
				this.app.state.settings[def.key] = GM_getValue(def.key, def.defaultValue);
			});
			this.renderMenu();
		}
		renderMenu() {
			if (this.registeredCommands && this.registeredCommands.length > 0) this.registeredCommands.forEach((cmdId) => GM_unregisterMenuCommand(cmdId));
			this.registeredCommands = [];
			const T = this.app.state.T;
			const settingsCommand = () => {
				if (this.app.modules.settingsModal) this.app.modules.settingsModal.open();
			};
			const menuSettingsId = GM_registerMenuCommand(T.menuSettings || "⚙️ Settings", settingsCommand);
			this.registeredCommands.push(menuSettingsId);
			const resetCommand = () => {
				showCustomConfirm$1(this.app, T.resetSettingsConfirm || "Reset settings to default?", () => {
					this.resetAllSettings();
					if (this.app.modules.toastNotifier) this.app.modules.toastNotifier.show(T.notificationSettingsReset || "Settings reset", "success");
				});
			};
			const menuResetSettingsId = GM_registerMenuCommand(T.menuResetSettings || "🚨 Reset Settings", resetCommand);
			this.registeredCommands.push(menuResetSettingsId);
		}
		updateSetting(key, value) {
			GM_setValue(key, value);
			this.app.state.settings[key] = value;
		}
		handleSettingChange(key, newValue, oldValue) {
			const PHT = this.app.modules.postHeaderTools;
			const FN = this.app.modules.floatingNavigator;
			const TN = this.app.modules.timelineNavigator;
			const SI = this.app.modules.styleInjector;
			const ER = this.app.modules.errorRecovery;
			const TA = this.app.modules.transparencyActions;
			const CE = this.app.modules.contentExpander;
			const IR = this.app.modules.idRevealer;
			switch (key) {
				case "permalinkCopierEnabled":
				case "enableCopyContentButton":
				case "screenshotEnabled":
				case "copier_useSmartLink":
				case "copier_includeEmojis":
				case "copy_includeMetadata":
				case "toolsPosition":
					if (PHT) PHT.reEvaluateAllButtons();
					break;
				case "floatingNavEnabled":
					if (newValue) {
						if (FN) FN.init();
					} else if (FN) FN.deinit();
					break;
				case "timelineNavEnabled":
					if (newValue) {
						if (TN) TN.init();
					} else if (TN) TN.deinit();
					if (FN && this.app.state.settings.floatingNavEnabled) {
						FN.deinit();
						FN.init();
					}
					break;
				case "floatingNavOpacity":
					if (FN) FN.updateOpacityState(!!newValue);
					break;
				case "hidePostStats":
					if (SI) SI.updateStatsBarVisibility(!!newValue);
					break;
				case "errorRecoveryEnabled":
					if (newValue && ER) ER.init();
					break;
				case "transparencyButtonsEnabled":
					if (newValue) {
						if (TA) TA.init();
					} else if (TA) TA.deinit();
					break;
				case "idRevealerEnabled":
					if (newValue && IR) IR.init();
					break;
				case "expandContentEnabled":
					if (newValue && CE) CE.init();
					break;
				case "enableBookmarks":
					if (PHT) PHT.reEvaluateAllButtons();
					if (FN && this.app.state.settings.floatingNavEnabled) {
						FN.deinit();
						FN.init();
					}
					break;
				case "bookmarkPosition":
					window.dispatchEvent(new CustomEvent("gm-bookmark-position-changed", { detail: newValue }));
					break;
				case "keyboardNavEnabled":
					const KN = this.app.modules.keyboardNavigator;
					if (KN) if (newValue) KN.init();
					else KN.deinit();
					break;
				case "keyNavNextPrimary":
				case "keyNavPrevPrimary":
				case "keyNavNextSecondary":
				case "keyNavPrevSecondary":
					const KN_keys = this.app.modules.keyboardNavigator;
					if (KN_keys && this.app.state.settings.keyboardNavEnabled) {
						KN_keys.deinit();
						KN_keys.init();
					}
					break;
				case "wheelNavEnabled":
					const WN = this.app.modules.wheelNavigator;
					if (WN) if (newValue) WN.init();
					else WN.deinit();
					break;
				case "wheelNavModifier":
					const WN_mod = this.app.modules.wheelNavigator;
					if (WN_mod && this.app.state.settings.wheelNavEnabled) {
						WN_mod.deinit();
						WN_mod.init();
					}
					break;
				case "autoUnmuteEnabled":
					const AM = this.app.modules.autoUnmuter;
					if (AM) if (newValue) AM.init();
					else AM.deinit();
					break;
				case "autoUnmuteVolume":
					const AM_vol = this.app.modules.autoUnmuter;
					if (AM_vol) AM_vol.updateVolume(newValue);
					break;
				case "batchCopyMode":
				case "batchExportFormat":
					if (FN && this.app.state.settings.floatingNavEnabled) FN.updateBatchCopyTooltip();
					break;
				case "timelineHeatmapEnabled":
					if (TN) TN.refresh(true);
					break;
				case "heatmapBorderEnabled":
				case "navHighlighterEnabled":
					const PNC = this.app.modules.postNavigatorCore;
					if (PNC) {
						if (key === "navHighlighterEnabled" && !newValue) {
							const currentHighlighted = document.querySelector(`.${this.app.config.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS}`);
							if (currentHighlighted) {
								currentHighlighted.classList.remove(this.app.config.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS);
								delete currentHighlighted.dataset.heat;
							}
						}
						if (PNC.currentPostIndex !== -1) PNC.updateActivePost(PNC.currentPostIndex, "manual");
					}
					break;
			}
		}
		resetAllSettings() {
			this.definitions.forEach((def) => {
				const oldValue = this.app.state.settings[def.key];
				const newValue = def.defaultValue;
				if (oldValue !== newValue) {
					this.updateSetting(def.key, newValue);
					if (def.instant) this.handleSettingChange(def.key, newValue, oldValue);
				}
			});
		}
	};
	var ToastNotifier = class {
		app;
		activeToasts = new Map();
		constructor(app) {
			this.app = app;
		}
		show(message, type = "success", duration = 4e3, id = null) {
			if (id && this.activeToasts.has(id)) {
				const existing = this.activeToasts.get(id);
				if (existing.element && document.body.contains(existing.element)) {
					const span = existing.element.querySelector("span");
					if (span) span.innerHTML = message;
					existing.element.className = `gm-toast gm-toast-${type} gm-toast-visible`;
					clearTimeout(existing.timer);
					existing.timer = setTimeout(() => this.dismiss(id), duration);
					return { remove: () => this.dismiss(id) };
				} else this.activeToasts.delete(id);
			}
			const toast = this.app.utils.createStyledElement("div", {}, {
				className: `gm-toast gm-toast-${type}`,
				innerHTML: `<span>${message}</span>`
			});
			document.body.append(toast);
			toast.getBoundingClientRect();
			toast.classList.add("gm-toast-visible");
			const hideTimer = setTimeout(() => {
				this.dismiss(id, toast);
			}, duration);
			if (id) this.activeToasts.set(id, {
				element: toast,
				timer: hideTimer
			});
			return { remove: () => {
				clearTimeout(hideTimer);
				this.dismiss(id, toast);
			} };
		}
		dismiss(id, element) {
			let toast = element;
			if (id && this.activeToasts.has(id)) {
				toast = this.activeToasts.get(id).element;
				this.activeToasts.delete(id);
			}
			if (toast) {
				toast.classList.remove("gm-toast-visible");
				setTimeout(() => {
					if (toast && toast.parentNode) toast.remove();
				}, 500);
			}
		}
	};
	var DomCleaner = class {
		app;
		observer = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			const C = this.app.config;
			const T = this.app.state.T;
			const FINGERPRINTS = [
				{
					selector: `${C.SELECTORS.GLOBAL.DIALOG}:has([href*="/policies/cookies/"]) [role="button"][tabindex="0"]`,
					action: "click"
				},
				{
					selector: `${C.SELECTORS.GLOBAL.DIALOG}:has(${C.SELECTORS.GLOBAL.LOGIN_FORM})`,
					action: "handle_login_modal"
				},
				{
					selector: ".generic_dialog:has(input[name=\"login\"])",
					action: "handle_legacy_login_modal"
				}
			];
			const showDeadlockNotification = () => {
				if (!this.app.state.settings.showDeadlockNotification) return;
				if (this.app.utils.isFeedPage && !this.app.utils.isFeedPage()) return;
				if (this.app.modules.toastNotifier) this.app.modules.toastNotifier.show(T.notificationDeadlock || "Page may be deadlocked", "failure", 8e3);
			};
			const runEngine = () => {
				for (const fp of FINGERPRINTS) {
					if (fp.setting && !this.app.state.settings[fp.setting]) continue;
					document.querySelectorAll(fp.selector).forEach((el) => {
						const htmlEl = el;
						if (htmlEl.dataset[C.PROCESSED_MARKER]) return;
						htmlEl.dataset[C.PROCESSED_MARKER] = "true";
						switch (fp.action) {
							case "click":
								htmlEl.click();
								break;
							case "handle_login_modal":
								const closeButton = htmlEl.querySelector(C.SELECTORS.GLOBAL.CLOSE_BUTTON);
								if (closeButton) closeButton.click();
								else {
									const container = Array.from(document.querySelectorAll(C.SELECTORS.GLOBAL.MODAL_CONTAINER)).find((c) => c.contains(htmlEl));
									if (container) {
										container.style.display = "none";
										console.warn(`${C.LOG_PREFIX} Non-closable modal hidden. Page may be deadlocked.`);
										showDeadlockNotification();
									}
								}
								if (this.app.modules.scrollRestorer) this.app.modules.scrollRestorer.triggerRestore();
								break;
							case "handle_legacy_login_modal":
								htmlEl.style.display = "none";
								if (this.app.modules.scrollRestorer) this.app.modules.scrollRestorer.triggerRestore();
								break;
						}
					});
				}
			};
			const throttledEngine = this.app.utils.throttle(runEngine, C.THROTTLE_DELAY);
			this.observer = new MutationObserver(throttledEngine);
			this.observer.observe(document.documentElement, {
				childList: true,
				subtree: true
			});
			throttledEngine();
		}
		destroy() {
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
		}
	};
	var UiCleaner = class {
		app;
		observer = null;
		historyChangeHandler = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			this.process();
			this.startObserver();
			this.historyChangeHandler = () => this.handleHistoryChange();
			window.addEventListener("historyChange", this.historyChangeHandler);
		}
		handleHistoryChange() {
			setTimeout(() => this.process(), 500);
		}
		startObserver() {
			if (this.observer) return;
			this.observer = new MutationObserver(this.app.utils.throttle(() => {
				this.process();
			}, 500));
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
		}
		process() {
			this.cleanVideoPageUI();
		}
		cleanVideoPageUI() {
			const C = this.app.config;
			const toolbarSelector = C.SELECTORS.GLOBAL.VIDEO_PAGE_TOOLBAR_ROOT;
			document.querySelectorAll(toolbarSelector).forEach((el) => {
				const htmlEl = el;
				if (htmlEl.querySelector("a[aria-label=\"Close reels viewer and return to feed\"]") || htmlEl.querySelector("a[aria-label=\"關閉 Reel 檢視畫面並返回動態消息\"]") || htmlEl.querySelector("a[aria-label=\"リール動画のビューアーを閉じてフィードに戻る\"]") || htmlEl.querySelector("a[aria-label=\"Close viewer and return to feed\"]") || htmlEl.querySelector("a[aria-label=\"關閉檢視工具並返回動態消息\"]") || htmlEl.querySelector("a[aria-label=\"ビューアーを閉じてフィードに戻る\"]") || htmlEl.querySelector("i[style*=\"-402px\"]")) return;
				if (htmlEl.style.position !== "absolute") {
					htmlEl.style.setProperty("position", "absolute", "important");
					htmlEl.style.setProperty("top", "0", "important");
					htmlEl.style.setProperty("width", "100%", "important");
					htmlEl.style.setProperty("z-index", "999", "important");
				}
			});
			const followLabels = C.CONSTANTS.FOLLOW_BUTTON_LABELS;
			if (!followLabels) return;
			document.querySelectorAll("[role=\"button\"]").forEach((btn) => {
				const htmlBtn = btn;
				if (htmlBtn.style.display === "none") return;
				const label = htmlBtn.getAttribute("aria-label");
				if (label) {
					const trimmedLabel = label.trim();
					if (followLabels.some((l) => {
						if (trimmedLabel === l) return true;
						const prefix = /[\u4e00-\u9fa5\u3040-\u30ff\u1100-\u11ff]/.test(l) ? l : l + " ";
						return trimmedLabel.startsWith(prefix);
					})) htmlBtn.style.setProperty("display", "none", "important");
				}
			});
		}
		destroy() {
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			if (this.historyChangeHandler) {
				window.removeEventListener("historyChange", this.historyChangeHandler);
				this.historyChangeHandler = null;
			}
		}
	};
	var ContentExpander = class {
		app;
		observer = null;
		expandedArticles = new WeakSet();
		constructor(app) {
			this.app = app;
		}
		init() {
			if (!this.app.state.settings.expandContentEnabled) return;
			const C = this.app.config.TEXT_EXPANDER;
			const runExpander = () => {
				const selector = `${C.SCOPE_SELECTOR} ${C.BUTTON_SELECTOR}`;
				document.querySelectorAll(selector).forEach((btn) => {
					const htmlBtn = btn;
					if (htmlBtn.hasAttribute(C.PROCESSED_ATTR)) return;
					if (htmlBtn.offsetParent === null) return;
					if (htmlBtn.closest("a[href*=\"/reel/\"]") || htmlBtn.closest("a[href*=\"/watch/\"]")) return;
					const postEl = htmlBtn.closest("div[role=\"article\"]");
					if (postEl && this.expandedArticles.has(postEl)) return;
					if (isSeeMoreButton(htmlBtn)) {
						if (postEl) this.expandedArticles.add(postEl);
						htmlBtn.setAttribute(C.PROCESSED_ATTR, "true");
						htmlBtn.click();
					}
				});
			};
			const throttledRun = this.app.utils.throttle(runExpander, 500);
			this.observer = new MutationObserver(throttledRun);
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
			runExpander();
		}
		destroy() {
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
		}
	};
	var LinkIntervention = class {
		app;
		clickHandlerBound = null;
		mouseoverHandlerBound = null;
		contextMenuHandlerBound = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			this.clickHandlerBound = this.handleClick.bind(this);
			this.mouseoverHandlerBound = this.handleMouseover.bind(this);
			this.contextMenuHandlerBound = (e) => {
				const target = e.target;
				if (target) {
					if (target.closest(".gm-floating-nav") || target.closest(".gm-transparency-btn")) return;
				}
				e.stopPropagation();
			};
			document.addEventListener("click", this.clickHandlerBound, true);
			document.addEventListener("auxclick", this.clickHandlerBound, true);
			document.addEventListener("mouseover", this.mouseoverHandlerBound, true);
			document.addEventListener("contextmenu", this.contextMenuHandlerBound, true);
			try {
				const originalPushState = history.pushState.bind(history);
				const originalReplaceState = history.replaceState.bind(history);
				const interceptNavigation = (original, state, title, url) => {
					return original(state, title, url);
				};
				history.pushState = (state, title, url) => interceptNavigation(originalPushState, state, title, url);
				history.replaceState = (state, title, url) => interceptNavigation(originalReplaceState, state, title, url);
			} catch (e) {
				console.error("Antigravity: Failed to hook history API", e);
			}
		}
		handleClick(event) {
			if (event.button === 2) return;
			const target = event.target;
			if (!target) return;
			if (target.closest("[role=\"banner\"], [role=\"navigation\"], .gm-floating-nav") || target.closest(".gm-bookmarks-sidebar") || target.closest(".gm-settings-modal")) return;
			const settings = this.app.state.settings;
			if (settings.autoOpenMediaInNewTab && (event.type === "click" || event.type === "mousedown")) {
				const post = target.closest("div[role=\"article\"]");
				if (post) {
					const reelLink = Array.from(post.querySelectorAll("a[href*=\"/reel/\"], a[href*=\"/watch/\"], a[href*=\"/videos/\"]")).find((a) => !a.href.includes("comment_id") && !a.href.includes("reply_comment_id"));
					const hasVideo = post.querySelector("video");
					if (reelLink || hasVideo) {
						const btn = target.closest("[role=\"button\"], button, [role=\"link\"], a");
						const isTargetGm = target.classList && target.classList.contains("gm-inject-btn") || typeof target.className === "string" && target.className.includes("gm-");
						const isBtnGm = btn && (typeof btn.className === "string" && btn.className.includes("gm-") || btn.classList && btn.classList.contains("gm-inject-btn"));
						if (isTargetGm || isBtnGm) return;
						const label = btn ? (btn.getAttribute("aria-label") || btn.textContent || "").toLowerCase() : "";
						if (btn && btn.querySelector(`path[d*="M16 5.414V8a1 1 0 1 0 2 0V4a2 2 0 0 0-2-2h-4"]`) || label.includes("expand") || label.includes("點擊可展開")) {
							if (event.type === "click") {
								event.preventDefault();
								event.stopPropagation();
								const cleanUrl = this.cleanUrl(reelLink ? reelLink.href : window.location.href);
								this.app.utils.smartOpen(event, cleanUrl);
							}
							return;
						}
						const isInteractive = btn || target.closest("input, select, textarea, [role=\"slider\"], [role=\"progressbar\"], [role=\"menuitem\"], [role=\"menuitemradio\"], [role=\"menu\"], [role=\"listbox\"], [role=\"option\"], [aria-haspopup=\"true\"]");
						const isStructuralScope = target.closest("[role=\"toolbar\"]") || target.closest("[role=\"banner\"]") || target.closest("[role=\"contentinfo\"]");
						if (isInteractive || isStructuralScope) {
							const link = target.closest("a");
							if (link && /\/photo\/?\?|\/photos?\/|\/videos?\/|\/reel\/|\/watch\/|fbid=/.test(link.href)) {
								if (target.closest("[role=\"slider\"], [role=\"progressbar\"]")) return;
								if (btn && (btn.tagName === "A" || btn.getAttribute("role") === "link")) {
									const video = btn.querySelector("video");
									if (video) {
										event.preventDefault();
										event.stopPropagation();
										if (video.paused) video.play();
										else video.pause();
										return;
									}
								} else {
									const hasCssSprite = btn && (btn.querySelector("[data-visualcompletion=\"css-img\"]") || target.getAttribute("data-visualcompletion") === "css-img");
									const isSvg = target.tagName === "svg" || target.tagName === "path" || btn && btn.querySelector("svg");
									if (hasCssSprite || isSvg || /Play|Pause|播放|暫停|再生|Play video|播放影片|動画を再生/i.test(label) || /Volume|Mute|Unmute|Settings|Fullscreen|Captions|音量|靜音|設定|全螢幕|字幕|フルスクリーン|ミュート/i.test(label)) return;
								}
							} else return;
						}
						if (!target.closest("a")) {
							const video = post.querySelector("video");
							if (video) {
								if (target.closest("h2, h3, h4, span, p, [data-ad-rendering-role=\"story_message\"]")) return;
								if (target.querySelector) {
									if (target.querySelector("h2, h3, h4") || target.querySelector("[role=\"toolbar\"]") || target.querySelector("[aria-label*=\"Comment\"]") || target.querySelector("[aria-label*=\"Reply\"]") || target.querySelector("form")) return;
								}
								event.preventDefault();
								event.stopPropagation();
								if (event.type === "click") if (video.paused) video.play();
								else video.pause();
								return;
							}
						}
					}
				}
			}
			const link = target.closest("a");
			if (!link || !link.href) return;
			const isMedia = /\/photo\/?\?|\/photos?\/|\/videos?\/|\/reel\/|\/watch\/|fbid=/.test(link.href);
			const isList = /\/photos_by\/|\/photos_albums/.test(link.href);
			if (event.button === 0 && settings.autoOpenMediaInNewTab && isMedia && !isList) {
				event.preventDefault();
				event.stopPropagation();
				const cleanUrl = this.cleanUrl(link.href);
				this.app.utils.smartOpen(event, cleanUrl);
				return;
			}
			if (settings.linkDetrackerEnabled && (link.target === "_blank" || event.ctrlKey || event.metaKey || event.button === 1)) {
				const clean = this.cleanUrl(link.href);
				if (clean !== link.href) link.href = clean;
			}
		}
		handleMouseover(event) {
			if (!this.app.state.settings.linkDetrackerEnabled) return;
			const target = event.target;
			if (!target) return;
			const link = target.closest("a");
			if (!link || !link.href) return;
			const url = link.href;
			if (url.includes("?") || url.includes("l.facebook.com")) {
				const clean = this.cleanUrl(url);
				if (clean !== url) link.href = clean;
			}
		}
		cleanUrl(url) {
			try {
				const urlObj = new URL(url);
				if (urlObj.hostname.includes("l.facebook.com") && urlObj.searchParams.has("u")) {
					const realUrl = decodeURIComponent(urlObj.searchParams.get("u") || "");
					return this.cleanUrl(realUrl);
				}
				if (this.app.utils.isPeopleHomeUrl && this.app.utils.isPeopleHomeUrl(urlObj.href)) {
					urlObj.search = "";
					try {
						return decodeURIComponent(urlObj.href.replace(/\/$/, "")) + "/";
					} catch (e) {
						return urlObj.href.replace(/\/$/, "") + "/";
					}
				}
				this.app.utils.cleanUrlParams(urlObj);
				if (urlObj.hostname.includes("facebook.com")) {
					const keep = [
						"id",
						"fbid",
						"story_fbid",
						"v",
						"set",
						"p",
						"pb",
						"q",
						"query"
					];
					Array.from(urlObj.searchParams.keys()).forEach((key) => {
						if (!keep.includes(key) && !key.startsWith("qp")) urlObj.searchParams.delete(key);
					});
				}
				return urlObj.href.replace(/\/$/, "");
			} catch (e) {
				return url;
			}
		}
		destroy() {
			if (this.clickHandlerBound) {
				document.removeEventListener("click", this.clickHandlerBound, true);
				document.removeEventListener("auxclick", this.clickHandlerBound, true);
				this.clickHandlerBound = null;
			}
			if (this.mouseoverHandlerBound) {
				document.removeEventListener("mouseover", this.mouseoverHandlerBound, true);
				this.mouseoverHandlerBound = null;
			}
			if (this.contextMenuHandlerBound) {
				document.removeEventListener("contextmenu", this.contextMenuHandlerBound, true);
				this.contextMenuHandlerBound = null;
			}
		}
	};
	var StyleInjector = class {
		app;
		mainStyleElement = null;
		statsStyleElement = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			const settings = this.app.state.settings;
			try {
				const div = document.createElement("div");
				Object.assign(div.style, {
					width: "100px",
					height: "100px",
					overflow: "scroll",
					position: "absolute",
					top: "-9999px"
				});
				document.body.appendChild(div);
				const scrollbarWidth = div.offsetWidth - div.clientWidth;
				document.body.removeChild(div);
				document.documentElement.style.setProperty("--scrollbar-width", `${scrollbarWidth}px`);
			} catch (e) {
				console.error("[FB Login Wall Remover] Failed to detect scrollbar width:", e);
				document.documentElement.style.setProperty("--scrollbar-width", "16px");
			}
			let css = "";
			if (settings.hideUselessElements) css += this.getHideUselessCss();
			if (css) {
				this.mainStyleElement = this.app.utils.createStyledElement("style", {}, { textContent: css });
				if (this.mainStyleElement) document.head.append(this.mainStyleElement);
			}
			this.updateStatsBarVisibility(settings.hidePostStats);
		}
		getHideUselessCss() {
			const C = this.app.config;
			const mediaLabels = C.CONSTANTS.MEDIA_CONTROL_LABELS || [];
			const exclusion = mediaLabels.map((l) => `:not([aria-label*="${l}"])`).join("");
			const toolbarRuleA = `div:has(> div > div > div[role="button"]:not([aria-haspopup])${exclusion} > div > div > i[data-visualcompletion="css-img"])`;
			const toolbarRuleB = `div:has(> div > div[role="button"]:not([aria-haspopup])${exclusion} > div > div > i[data-visualcompletion="css-img"])`;
			const threeDotMenuSelector = `div[role="button"][aria-haspopup="menu"]:has(svg circle + circle + circle)`;
			const mediaViewerProtection = [
				mediaLabels.map((l) => `:not(:has([aria-label*="${l}"]))`).join(""),
				":not([data-pagelet=\"MediaViewerPhoto\"])",
				":not(:has([data-pagelet=\"MediaViewerPhoto\"]))",
				":not([style*=\"position: absolute\"])"
			].join("");
			const stickyProfileTabs = "div[role=\"banner\"] + div div[style*=\"top\"][style*=\"z-index\"]" + mediaViewerProtection;
			const stickyLoginBanner = ["div[style*=\"z-index\"]:has(a[href*=\"/login/\"], form[action*=\"/login/\"])", "div[role=\"banner\"] > div:not(:first-child):has([aria-label=\"Facebook\"])"].map((s) => s + mediaViewerProtection).join(", ");
			const genericLoginPrompt = "div[id^=\"mount\"] div:not([id]):not([class]):not([style]) > div[data-nosnippet]";
			const loginPopupSelector = "div[role=\"dialog\"]:has(form[action*=\"/login/\"], #login_popup_cta_form)" + mediaViewerProtection;
			return [
				`${[
					"div:has(> div > span > a[aria-label=\"Close reels viewer and return to feed\"])",
					"div:has(> div > span > a[aria-label=\"關閉 Reel 檢視畫面並返回動態消息\"])",
					"div:has(> div > span > a[aria-label=\"リール動画のビューアーを閉じてフィードに戻る\"])",
					"div:has(> div > span > a > i[style*=\"background-position: 0px -402px\"])"
				].join(", ")} { display: none !important; }`,
				`div[role="banner"]:has(${C.SELECTORS.GLOBAL.LOGIN_FORM}) { display: none !important; }`,
				`${toolbarRuleA}, ${toolbarRuleB} { display: none !important; }`,
				`${threeDotMenuSelector} { display: none !important; }`,
				`${genericLoginPrompt}, ${loginPopupSelector} { display: none !important; }`,
				`${stickyProfileTabs} { position: static !important; }`,
				`${stickyLoginBanner} { position: absolute !important; }`
			].join("\n");
		}
		updateStatsBarVisibility(shouldHide) {
			if (shouldHide) {
				if (!this.statsStyleElement) {
					const css = `div:has(> div > span[role="toolbar"]) { display: none !important; }`;
					this.statsStyleElement = this.app.utils.createStyledElement("style", {}, { textContent: css });
					if (this.statsStyleElement) document.head.append(this.statsStyleElement);
				}
			} else if (this.statsStyleElement) {
				this.statsStyleElement.remove();
				this.statsStyleElement = null;
			}
		}
		destroy() {
			try {
				document.documentElement.style.removeProperty("--scrollbar-width");
			} catch (e) {}
			if (this.mainStyleElement) {
				this.mainStyleElement.remove();
				this.mainStyleElement = null;
			}
			if (this.statsStyleElement) {
				this.statsStyleElement.remove();
				this.statsStyleElement = null;
			}
		}
	};
	var ErrorRecovery = class {
		app;
		observer = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (!this.app.state.settings.errorRecoveryEnabled) return;
			const run = () => {
				const C = this.app.config.ERROR_RECOVERY;
				const selector = C.RELOAD_BUTTON_LABELS.map((label) => `div[role="button"][aria-label="${label}"]`).join(", ");
				const btn = document.querySelector(selector);
				if (!btn) return;
				const currentUrl = window.location.href;
				let state = {
					url: "",
					count: 0
				};
				try {
					const stored = sessionStorage.getItem(C.STORAGE_KEY);
					if (stored) state = JSON.parse(stored);
				} catch (e) {}
				if (state.url !== currentUrl) state = {
					url: currentUrl,
					count: 0
				};
				if (state.count >= C.MAX_RETRIES) {
					console.warn(`${this.app.config.LOG_PREFIX} [ErrorRecovery] Max retries reached for this URL.`);
					return;
				}
				console.log(`${this.app.config.LOG_PREFIX} [ErrorRecovery] Error page detected. Retrying...`);
				state.count++;
				sessionStorage.setItem(C.STORAGE_KEY, JSON.stringify(state));
				btn.click();
				setTimeout(() => {
					if (document.querySelector(selector)) window.location.reload();
				}, 1e3);
			};
			const throttledRun = this.app.utils.throttle(run, 1e3);
			this.observer = new MutationObserver(throttledRun);
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
			run();
		}
	};
	var ContentAutoLoader = class {
		app;
		state = {
			isRunning: false,
			targetCount: 0,
			retryCount: 0,
			lastScrollTime: 0,
			initialCount: 0,
			mode: "incremental",
			batchCopyMode: "file"
		};
		selectors = [
			{ selector: "a[href*=\"/more/\"][role=\"button\"]" },
			{ selector: "[role=\"progressbar\"]" },
			{ selector: "[data-visualcompletion=\"loading-state\"]" },
			{ selector: ".uiMorePagerLoader" },
			{ selector: "div[role=\"button\"]:not([aria-label*=\"Create\"]):not([aria-label*=\"Search\"])" }
		];
		constructor(app) {
			this.app = app;
		}
		init() {
			this.state.mode = GM_getValue("autoLoadMode", "incremental");
			this.state.batchCopyMode = GM_getValue("batchCopyMode", "file");
			if (this.app.state.settings.batchCopyMode) this.state.batchCopyMode = this.app.state.settings.batchCopyMode;
		}
		toggleMode() {
			this.state.mode = this.state.mode === "incremental" ? "target" : "incremental";
			GM_setValue("autoLoadMode", this.state.mode);
			const T = this.app.state.T;
			const batchSize = this.app.state.settings.autoLoadBatchSize || 20;
			const msg = this.state.mode === "incremental" ? T.autoLoad_mode_incremental.replace("{n}", String(batchSize)) : T.autoLoad_mode_target.replace("{n}", String(batchSize));
			this.app.modules.toastNotifier.show(msg, "info");
			if (this.app.modules.floatingNavigator) this.app.modules.floatingNavigator.updateButtonTooltip();
		}
		toggleBatchCopyMode() {
			const T = this.app.state.T;
			if (this.app.state.settings.batchExportFormat === "csv") {
				this.app.modules.toastNotifier.show(T.batchCopyMode_locked_csv || "CSV format requires Download mode.", "info");
				return;
			}
			let current = this.app.state.settings.batchCopyMode;
			if (current === "download") current = "file";
			const newMode = current === "clipboard" ? "file" : "clipboard";
			this.state.batchCopyMode = newMode;
			this.app.state.settings.batchCopyMode = newMode;
			GM_setValue("batchCopyMode", newMode);
			const msg = newMode === "clipboard" ? T.batchCopyMode_clipboard || "Clipboard Mode" : T.batchCopyMode_file || "File Mode";
			this.app.modules.toastNotifier.show(msg, "info");
			if (this.app.modules.floatingNavigator) this.app.modules.floatingNavigator.updateBatchCopyTooltip();
		}
		async start() {
			if (this.state.isRunning) return;
			const T = this.app.state.T;
			const currentPosts = (this.app.modules.postNavigatorCore?.getSortedPosts() || []).length;
			const batchSize = this.app.state.settings.autoLoadBatchSize || 20;
			if (this.state.mode === "target") {
				if (currentPosts >= batchSize) {
					this.app.modules.toastNotifier.show(T.autoLoad_target_reached.replace("{n}", String(batchSize)), "info");
					return;
				}
				this.state.targetCount = batchSize;
			} else this.state.targetCount = currentPosts + batchSize;
			this.state.isRunning = true;
			this.state.retryCount = 0;
			this.state.initialCount = currentPosts;
			if (this.app.modules.floatingNavigator) this.app.modules.floatingNavigator.updateButtonState("start");
			this.app.modules.toastNotifier.show(T.autoLoad_status_loading.replace("{current}", String(currentPosts)).replace("{target}", String(this.state.targetCount)), "success", 4e3, "autoLoadStatus");
			await this.loop();
		}
		stop(reasonKey = "") {
			this.state.isRunning = false;
			if (this.app.modules.floatingNavigator) this.app.modules.floatingNavigator.updateButtonState("stop");
			if (reasonKey) {
				const T = this.app.state.T;
				const type = reasonKey.includes("success") ? "success" : "failure";
				this.app.modules.toastNotifier.show(T[reasonKey] || reasonKey, type, 4e3, "autoLoadStatus");
			}
		}
		async loop() {
			const C = this.app.config.AUTO_LOADER;
			const T = this.app.state.T;
			while (this.state.isRunning) {
				if (this.isDeadlocked()) {
					this.stop("autoLoad_status_deadlock");
					return;
				}
				const currentCount = (this.app.modules.postNavigatorCore?.getSortedPosts() || []).length;
				const initial = this.state.initialCount || 0;
				const sessionTarget = this.state.targetCount;
				const progressCurrent = Math.max(0, currentCount - initial);
				const progressTotal = Math.max(1, sessionTarget - initial);
				if (this.app.modules.floatingNavigator) this.app.modules.floatingNavigator.updateProgress(progressCurrent, progressTotal);
				if (currentCount >= this.state.targetCount) {
					this.stop("autoLoad_status_success");
					return;
				}
				const timeSinceLastScroll = Date.now() - this.state.lastScrollTime;
				if (timeSinceLastScroll < C.MIN_COOLDOWN) await this.app.utils.delay(C.MIN_COOLDOWN - timeSinceLastScroll);
				this.app.modules.toastNotifier.show(T.autoLoad_status_loading.replace("{current}", String(currentCount)).replace("{target}", String(this.state.targetCount)), "success", 2e3, "autoLoadStatus");
				window.scrollTo({
					top: document.body.scrollHeight,
					behavior: "smooth"
				});
				this.state.lastScrollTime = Date.now();
				this.triggerLoad();
				const result = await this.waitForNewContent(currentCount);
				if (result === "loaded") this.state.retryCount = 0;
				else if (result === "timeout") {
					this.state.retryCount++;
					this.app.modules.toastNotifier.show(T.autoLoad_status_retrying.replace("{count}", String(this.state.retryCount)).replace("{max}", String(C.MAX_RETRIES)), "failure", 2e3, "autoLoadStatus");
					if (this.state.retryCount >= C.MAX_RETRIES) {
						this.stop("autoLoad_status_success");
						return;
					}
				}
			}
		}
		triggerLoad() {
			for (const target of this.selectors) {
				const elements = document.querySelectorAll(target.selector);
				const el = elements.length > 0 ? elements[elements.length - 1] : null;
				if (el && el.offsetParent !== null) {
					try {
						const mouseEvent = new MouseEvent("mouseover", {
							bubbles: true,
							cancelable: true
						});
						el.dispatchEvent(mouseEvent);
						el.click();
					} catch (e) {}
					return;
				}
			}
		}
		waitForNewContent(baselineCount) {
			const C = this.app.config.AUTO_LOADER;
			return new Promise((resolve) => {
				const startTime = Date.now();
				const poller = setInterval(() => {
					if (!this.state.isRunning) {
						clearInterval(poller);
						resolve("stopped");
						return;
					}
					if ((this.app.modules.postNavigatorCore?.getSortedPosts() || []).length > baselineCount) {
						clearInterval(poller);
						resolve("loaded");
					}
					if (Date.now() - startTime > C.MAX_WAIT_TIME) {
						clearInterval(poller);
						resolve("timeout");
					}
				}, C.POLL_INTERVAL);
			});
		}
		isDeadlocked() {
			const C = this.app.config.SELECTORS;
			const U = this.app.utils;
			const dialog = document.querySelector(C.GLOBAL.DIALOG);
			if (dialog && U.isVisible(dialog)) {
				if (dialog.querySelector(C.GLOBAL.LOGIN_FORM)) return true;
			}
			const noSnippet = document.querySelector("div[data-nosnippet]");
			if (noSnippet && U.isVisible(noSnippet)) return true;
			const forms = document.querySelectorAll(C.GLOBAL.LOGIN_FORM);
			for (const form of forms) if (U.isVisible(form) && !form.closest("[role=\"banner\"]")) return true;
			return false;
		}
		async copyAllPosts() {
			const T = this.app.state.T;
			const settings = this.app.state.settings;
			const posts = this.app.modules.postNavigatorCore?.getSortedPosts() || [];
			if (posts.length === 0) {
				this.app.modules.toastNotifier.show(T.batchCopy_empty, "failure");
				return;
			}
			let progressToast = null;
			const progressTimer = setTimeout(() => {
				progressToast = this.app.modules.toastNotifier.show(T.batchCopy_start.replace("{count}", String(posts.length)), "success");
			}, 500);
			const PHT = this.app.modules.postHeaderTools;
			const exportFormat = settings.batchExportFormat || "text";
			const collectedData = [];
			const textParts = [];
			let successCount = 0;
			const BATCH_SEPARATOR = "\n\n═══════════════════════════════════════════════════════════════\n\n";
			for (const post of posts) {
				if (!PHT) continue;
				const data = await PHT.extractPostData(post, {
					forceRawLink: true,
					includeOrder: settings.copy_meta_order,
					isBatch: true
				});
				if (exportFormat === "text") {
					const formatted = PHT.formatPostData(data, "text");
					if (formatted) {
						textParts.push(formatted);
						successCount++;
					}
				} else if (data) {
					if (exportFormat === "csv") collectedData.push(PHT.formatPostData(data, "csv"));
					else collectedData.push(data);
					successCount++;
				}
			}
			let finalContent = "";
			let mimeType = "text/plain;charset=utf-8";
			let extension = "txt";
			const pageTitle = document.title.replace(/ \| Facebook$/, "").replace(/^\(\d+\) /, "");
			const now = new Date();
			const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}-${String(now.getMinutes()).padStart(2, "0")}`;
			const filename = `${pageTitle.replace(/[\\/:*?"<>|]/g, "_").trim()}_Batch_${dateStr}`;
			if (exportFormat === "text") {
				const bodyText = textParts.join(BATCH_SEPARATOR);
				if (settings.batchCopy_includeHeader) {
					const cleanUrl = window.location.origin + window.location.pathname;
					const nowStr = now.toLocaleString(navigator.language, { hour12: false });
					finalContent = `═══════════════════════════════════════════════════════════════\n${T.batchCopy_summary_title}\n${T.batchCopy_summary_source}: ${pageTitle}\n${T.batchCopy_summary_url}:    ${cleanUrl}\n${T.batchCopy_summary_time}:   ${nowStr}\n${T.batchCopy_summary_count}:  ${successCount} ${T.batchCopy_summary_posts}\n═══════════════════════════════════════════════════════════════\n\n` + bodyText;
				} else finalContent = bodyText;
				extension = "txt";
				mimeType = "text/plain;charset=utf-8";
			} else if (exportFormat === "json") {
				finalContent = JSON.stringify(collectedData, null, 2);
				mimeType = "application/json;charset=utf-8";
				extension = "json";
			} else if (exportFormat === "csv") {
				if (collectedData.length > 0) {
					const headers = Object.keys(collectedData[0]);
					const rows = collectedData.map((row) => headers.map((fieldName) => {
						let val = row[fieldName] || "";
						if (typeof val === "string" && (val.includes(",") || val.includes("\"") || val.includes("\n"))) val = `"${val.replace(/"/g, "\"\"")}"`;
						return val;
					}).join(","));
					finalContent = "" + headers.join(",") + "\n" + rows.join("\n");
				} else finalContent = "";
				mimeType = "text/csv;charset=utf-8";
				extension = "csv";
			}
			try {
				clearTimeout(progressTimer);
				if (progressToast && typeof progressToast.remove === "function") progressToast.remove();
				if (settings.batchCopyMode === "file") {
					const BOM = exportFormat === "csv" || exportFormat === "json" || exportFormat === "text" ? "" : "";
					const contentBlob = finalContent.startsWith("") ? finalContent : BOM + finalContent;
					const blob = new Blob([contentBlob], { type: mimeType });
					const url = URL.createObjectURL(blob);
					const link = document.createElement("a");
					link.href = url;
					link.download = `${filename}.${extension}`;
					link.style.display = "none";
					document.body.appendChild(link);
					link.click();
					document.body.removeChild(link);
					setTimeout(() => URL.revokeObjectURL(url), 100);
					const msg = T.batchCopy_file_success || "Exported to file successfully.";
					this.app.modules.toastNotifier.show(msg, "success");
				} else {
					const contentToCopy = finalContent.startsWith("") ? finalContent.substring(1) : finalContent;
					if (typeof GM_setClipboard === "function") GM_setClipboard(contentToCopy);
					else navigator.clipboard.writeText(contentToCopy);
					const msg = T.batchCopy_success.replace("{count}", String(successCount)).replace("{chars}", String(finalContent.length));
					this.app.modules.toastNotifier.show(msg, "success");
				}
			} catch (error) {
				console.error(`${this.app.config.LOG_PREFIX} Batch Copy Error:`, error);
				this.app.modules.toastNotifier.show(T.batchCopy_failed, "failure");
			}
		}
	};
	var getGlobalWindow = () => {
		return typeof unsafeWindow !== "undefined" ? unsafeWindow : window;
	};
	var TransparencyActions = class {
		app;
		container = null;
		interval = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (!this.app.state.settings.transparencyButtonsEnabled) return;
			this.updateUI();
			this.interval = setInterval(() => {
				const currentPath = window.location.pathname;
				if (currentPath !== this.app.state.currentPath) {
					this.app.state.currentPath = currentPath;
					this.app.state.cachedPageID = null;
					this.updateUI();
				}
				if ([
					"/watch",
					"/marketplace",
					"/gaming",
					"/events",
					"/groups",
					"/messages",
					"/ads"
				].some((ex) => currentPath.startsWith(ex)) || currentPath === "/") return;
				if (this.app.state.cachedPageID) return;
				const id = this._extractPageID();
				if (id) {
					this.app.state.cachedPageID = id;
					this.updateUI();
				}
			}, 1e3);
		}
		deinit() {
			if (this.container) {
				this.container.remove();
				this.container = null;
			}
			if (this.interval) {
				clearInterval(this.interval);
				this.interval = null;
			}
		}
		_extractPageID() {
			const scripts = document.querySelectorAll("script[type=\"application/json\"]");
			const reAssociated = /"associated_page_id":"(\d+)"/;
			const reDelegate = /"delegate_page":\{[^{}]*"id":"(\d+)"/;
			for (const script of scripts) {
				const content = script.textContent;
				if (!content || content.includes("timeline_list_feed_units")) continue;
				const matchAssoc = content.match(reAssociated);
				if (matchAssoc && matchAssoc[1] && matchAssoc[1] !== "0") return matchAssoc[1];
				if (content.includes("profile_header_renderer") || content.includes("profile_tile_sections")) {
					const matchDel = content.match(reDelegate);
					if (matchDel && matchDel[1] && matchDel[1] !== "0") return matchDel[1];
				}
			}
			return null;
		}
		updateUI() {
			if (!this.container) {
				const T = this.app.state.T;
				const C = this.app.config.ADS_LIB;
				const U = this.app.utils;
				const btnAds = this._createBtn("📢", T.tooltipAds, (e) => {
					if (this.app.state.cachedPageID) {
						GM_setValue(C.KEY_TARGET_ID, this.app.state.cachedPageID);
						const url = `https://www.facebook.com/ads/library/?active_status=active&view_all_page_id=${this.app.state.cachedPageID}`;
						U.smartOpen(e, url);
					}
				});
				const btnInt = this._createBtn("🛡️", T.tooltipTransparency, (e) => {
					if (this.app.state.cachedPageID) {
						GM_setValue(C.KEY_INT_ACTION, "true");
						const loc = window.location;
						let targetUrl = "";
						if (loc.pathname.includes("profile.php")) {
							const params = new URLSearchParams(loc.search);
							targetUrl = `${loc.origin}${loc.pathname}?id=${params.get("id")}&sk=about_profile_transparency&fblwr_int_action=true`;
						} else if (loc.pathname.startsWith("/people/") || loc.pathname.startsWith("/p/")) {
							const cleanPath = loc.pathname.replace(/\/$/, "");
							targetUrl = `${loc.origin}${cleanPath}/?sk=about_profile_transparency&fblwr_int_action=true`;
						} else {
							const rootPath = `/${loc.pathname.split("/")[1]}`;
							targetUrl = `${loc.origin}${rootPath}/about_profile_transparency?fblwr_int_action=true`;
						}
						U.smartOpen(e, targetUrl);
					}
				});
				const _addContextBlock = (btn) => {
					btn.addEventListener("contextmenu", (e) => {
						e.preventDefault();
						e.stopPropagation();
					});
				};
				_addContextBlock(btnAds);
				_addContextBlock(btnInt);
				const container = U.createStyledElement("div", {}, {
					className: "gm-transparency-container",
					children: [btnInt, btnAds]
				});
				const opacityEnabled = !!this.app.state.settings.floatingNavOpacity;
				container.dataset.opacity = opacityEnabled ? "true" : "false";
				this.container = container;
				document.body.appendChild(container);
			}
			if (this.container) if (this.app.state.cachedPageID) this.container.style.display = "flex";
			else this.container.style.display = "none";
		}
		_createBtn(icon, title, onClick) {
			return this.app.utils.createStyledElement("button", {}, {
				className: "gm-transparency-btn",
				title,
				innerHTML: icon,
				on: {
					mouseup: (e) => {
						const currentTarget = e.currentTarget;
						if (currentTarget) currentTarget.style.transform = "scale(1)";
						onClick(e);
					},
					mousedown: (e) => {
						if (e.button === 1) e.preventDefault();
						const currentTarget = e.currentTarget;
						if (currentTarget) currentTarget.style.transform = "scale(0.95)";
					},
					mouseover: (e) => {
						const currentTarget = e.currentTarget;
						if (currentTarget) currentTarget.style.backgroundColor = "#f0f2f5";
					},
					mouseleave: (e) => {
						const currentTarget = e.currentTarget;
						if (currentTarget) currentTarget.style.backgroundColor = "white";
					}
				}
			});
		}
	};
	var AdsLibraryHandler = class {
		app;
		constructor(app) {
			this.app = app;
		}
		init() {
			this.deinit();
			if (sessionStorage.getItem("fblwr_ads_clicked") === "true") return;
			if (this.app.state.adsClicked) return;
			if (!window.location.pathname.includes("/ads/library/")) return;
			const C = this.app.config.ADS_LIB;
			const currentID = new URLSearchParams(window.location.search).get("view_all_page_id");
			const targetID = GM_getValue(C.KEY_TARGET_ID, "");
			if (currentID && targetID && currentID === targetID) {
				sessionStorage.setItem("fblwr_ads_clicked", "true");
				this.app.state.adsClicked = true;
				console.log(`${this.app.config.LOG_PREFIX} [AdsLib] ID Match. Auto-nav initiating...`);
				if (typeof GM_deleteValue === "function") GM_deleteValue(C.KEY_TARGET_ID);
				else GM_setValue(C.KEY_TARGET_ID, "");
				this._initAdBlockerRemover();
				const win = getGlobalWindow();
				win.fblwr_adsTimeout = setTimeout(() => {
					let attempts = 0;
					let clickCount = 0;
					const tick = () => {
						if (!getGlobalWindow().fblwr_adsClicker) return;
						attempts++;
						if (!window.location.pathname.includes("/ads/library/")) {
							this.deinit();
							return;
						}
						const allLinks = document.querySelectorAll("div[role=\"link\"]");
						const parentMap = new Map();
						allLinks.forEach((link) => {
							const parent = link.parentElement;
							if (!parentMap.has(parent)) parentMap.set(parent, []);
							parentMap.get(parent).push(link);
						});
						let targetGroup = null;
						for (const children of parentMap.values()) if (children.length >= 2) {
							targetGroup = children;
							break;
						}
						if (targetGroup) targetGroup.forEach((tab, index) => {
							if (index !== 1) {
								const htmlTab = tab;
								if (!htmlTab.dataset.fblwrTabListener) {
									htmlTab.dataset.fblwrTabListener = "true";
									htmlTab.addEventListener("click", () => {
										this.deinit();
									}, { once: true });
								}
							}
						});
						if (targetGroup && targetGroup[1]) {
							targetGroup[1].click();
							clickCount++;
							if (clickCount >= 2) this.deinit();
						} else if (attempts > C.MAX_ATTEMPTS) this.deinit();
					};
					win.fblwr_adsClicker = true;
					tick();
					if (win.fblwr_adsClicker) win.fblwr_adsClicker = setInterval(tick, C.POLL_INTERVAL);
				}, 50);
			}
		}
		deinit() {
			const win = getGlobalWindow();
			if (win.fblwr_adsClicker) {
				const clickerId = win.fblwr_adsClicker;
				win.fblwr_adsClicker = null;
				clearInterval(clickerId);
				if (win.clearInterval) try {
					win.clearInterval(clickerId);
				} catch (e) {}
			}
			if (win.fblwr_adsTimeout) {
				const timeoutId = win.fblwr_adsTimeout;
				win.fblwr_adsTimeout = null;
				clearTimeout(timeoutId);
				if (win.clearTimeout) try {
					win.clearTimeout(timeoutId);
				} catch (e) {}
			}
		}
		_initAdBlockerRemover() {
			let hasHandledWarning = false;
			let observer = null;
			const cleanDialogs = () => {
				if (hasHandledWarning) return;
				const dialogs = document.querySelectorAll("div[role=\"dialog\"]");
				for (const dialog of dialogs) {
					const dialogEl = dialog;
					if (dialogEl.dataset.gmProcessed) continue;
					if (!dialogEl.querySelector("input, select, textarea")) {
						const hasHeading = dialogEl.querySelector("[role=\"heading\"]");
						const buttons = dialogEl.querySelectorAll("[role=\"button\"]");
						if (hasHeading && buttons.length > 0) {
							console.log(`${this.app.config.LOG_PREFIX} [AdsLib] Removing blocking dialog.`);
							const lastBtn = buttons[buttons.length - 1];
							if (lastBtn) lastBtn.click();
							dialogEl.dataset.gmProcessed = "true";
							setTimeout(() => {
								if (document.body.contains(dialogEl) && dialogEl.style.display !== "none") {
									dialogEl.style.display = "none";
									const layer = dialogEl.closest(".x1n2onr6");
									if (layer) layer.style.display = "none";
								}
							}, 300);
							hasHandledWarning = true;
							if (observer) {
								observer.disconnect();
								observer = null;
							}
						}
					}
				}
			};
			observer = new MutationObserver(cleanDialogs);
			observer.observe(document.body, {
				childList: true,
				subtree: true
			});
			cleanDialogs();
		}
	};
	var InternalTransparencyHandler = class {
		app;
		historyChangeHandler = null;
		constructor(app) {
			this.app = app;
		}
		init() {
			this.deinit();
			this.historyChangeHandler = () => {
				setTimeout(() => this.process(), 100);
			};
			window.addEventListener("historyChange", this.historyChangeHandler);
			this.process();
		}
		process() {
			const hasUrlParam = new URLSearchParams(window.location.search).get("fblwr_int_action") === "true";
			const log = (msg, type = "info") => {
				console.log(`${this.app.config.LOG_PREFIX} [IntTrans] ${msg}`);
			};
			log(`process() triggered. urlParam: ${hasUrlParam}, sessionStorage: ${sessionStorage.getItem("fblwr_int_expanded")}`);
			if (hasUrlParam) {
				log("Explicit URL parameter detected. Forcing reset of session locks.");
				sessionStorage.removeItem("fblwr_int_expanded");
				this.app.state.intExpanded = false;
			}
			if (sessionStorage.getItem("fblwr_int_expanded") === "true") {
				log("Aborted: already expanded in this session.");
				return;
			}
			if (this.app.state.intExpanded) {
				log("Aborted: in-memory lock is true.");
				return;
			}
			if (!window.location.href.includes("about_profile_transparency")) {
				log("Aborted: not on about_profile_transparency page.");
				return;
			}
			const C = this.app.config.ADS_LIB;
			const hasStorageParam = GM_getValue(C.KEY_INT_ACTION, "") === "true";
			log(`Checking execution: hasUrlParam=${hasUrlParam}, hasStorageParam=${hasStorageParam}`);
			if (hasUrlParam || hasStorageParam) {
				sessionStorage.setItem("fblwr_int_expanded", "true");
				this.app.state.intExpanded = true;
				log("Locks set. Initiating automation timer...", "success");
				if (hasUrlParam) try {
					const newUrl = new URL(window.location.href);
					newUrl.searchParams.delete("fblwr_int_action");
					window.history.replaceState(null, "", newUrl.pathname + newUrl.search + newUrl.hash);
				} catch (e) {}
				if (typeof GM_deleteValue === "function") GM_deleteValue(C.KEY_INT_ACTION);
				else GM_setValue(C.KEY_INT_ACTION, "false");
				const win = getGlobalWindow();
				win.fblwr_intTimeout = setTimeout(() => {
					let attempts = 0;
					const maxAttempts = 60;
					log(`Interval started. Polling for 'See all' button (Max attempts: ${maxAttempts})...`);
					const tick = () => {
						if (!getGlobalWindow().fblwr_intExpander) return;
						attempts++;
						if (!window.location.href.includes("about_profile_transparency")) {
							log("Timer aborted: path changed.");
							this.clearAutomation();
							return;
						}
						if (Array.from(document.querySelectorAll("div[role=\"dialog\"]")).find((d) => {
							const htmlD = d;
							if (!(htmlD.offsetParent !== null && window.getComputedStyle(htmlD).display !== "none")) return false;
							return !htmlD.querySelector("form#login_form, form[id=\"login_popup_cta_form\"]");
						})) {
							log("Target dialog detected. Automation successfully complete!", "success");
							this.clearAutomation();
							return;
						}
						const section = document.querySelector("div[data-pagelet=\"ProfileAppSection_0\"] section");
						let btn = null;
						if (section) {
							const buttons = section.querySelectorAll("[role=\"button\"]");
							if (buttons.length > 0) btn = buttons[buttons.length - 1];
						}
						if (btn) {
							log(`Found target button! Attempting native click event (Attempt: ${attempts})...`, "success");
							const clickEvent = new MouseEvent("click", {
								bubbles: true,
								cancelable: true
							});
							btn.dispatchEvent(clickEvent);
							btn.click();
						} else if (attempts % 5 === 0) log(`Polling... (Attempt: ${attempts}/${maxAttempts}). Section found: ${!!section}`);
						const closeBtnSelector = this.app.config.SELECTORS.GLOBAL.CLOSE_BUTTON;
						document.querySelectorAll(closeBtnSelector).forEach((closeBtn) => {
							const htmlCloseBtn = closeBtn;
							if (!htmlCloseBtn.dataset.fblwrCloseListener) {
								htmlCloseBtn.dataset.fblwrCloseListener = "true";
								htmlCloseBtn.addEventListener("click", () => {
									log("Timer canceled: user closed the dialog.");
									this.clearAutomation();
								}, { once: true });
							}
						});
						if (attempts > maxAttempts) {
							log("Timer stopped: Max attempts reached without dialog opening.", "failure");
							this.clearAutomation();
						}
					};
					win.fblwr_intExpander = true;
					tick();
					if (win.fblwr_intExpander) win.fblwr_intExpander = setInterval(tick, C.POLL_INTERVAL);
				}, 50);
			}
		}
		clearAutomation() {
			const win = getGlobalWindow();
			if (win.fblwr_intExpander) {
				const expanderId = win.fblwr_intExpander;
				win.fblwr_intExpander = null;
				clearInterval(expanderId);
				if (win.clearInterval) try {
					win.clearInterval(expanderId);
				} catch (e) {}
			}
			if (win.fblwr_intTimeout) {
				const timeoutId = win.fblwr_intTimeout;
				win.fblwr_intTimeout = null;
				clearTimeout(timeoutId);
				if (win.clearTimeout) try {
					win.clearTimeout(timeoutId);
				} catch (e) {}
			}
		}
		deinit() {
			this.clearAutomation();
			if (this.historyChangeHandler) {
				window.removeEventListener("historyChange", this.historyChangeHandler);
				this.historyChangeHandler = null;
			}
		}
	};
	var IdBadgeComponent = ({ app, idRevealerInstance, signals }) => {
		const badgeRef = A(null);
		const T = app.state.T;
		const { isBadgeVisible, profileName, idMap, profileUrl } = signals;
		y$2(() => {
			if (badgeRef.current) if (isBadgeVisible.value) {
				idRevealerInstance.activeBadge = badgeRef.current;
				idRevealerInstance.updatePosition();
				badgeRef.current.offsetHeight;
				badgeRef.current.style.opacity = "1";
			} else {
				badgeRef.current.style.opacity = "0";
				idRevealerInstance.activeBadge = null;
			}
		}, [idRevealerInstance, isBadgeVisible.value]);
		const handleRowClick = (text, label) => {
			if (typeof GM_setClipboard === "function") GM_setClipboard(text);
			const msg = (T.copy_success_generic || "Copied {label} to clipboard.").replace("{label}", label);
			app.modules.toastNotifier.show(msg, "success");
		};
		const handleCopyAll = (e) => {
			e.stopPropagation();
			const lines = [];
			if (profileName.value) lines.push(`${T.profile_name_label || "Profile Name"}: ${profileName.value}`);
			idMap.value.forEach(([key, val]) => {
				lines.push(`${key}: ${val}`);
			});
			if (profileUrl.value) lines.push(`${T.profile_url_label || "Profile URL"}: ${profileUrl.value}`);
			if (typeof GM_setClipboard === "function") GM_setClipboard(lines.join("\n"));
			app.modules.toastNotifier.show(T.all_copied || "All info copied.", "success");
		};
		return u("div", {
			ref: badgeRef,
			className: "gm-id-revealer-badge",
			style: {
				position: "fixed",
				zIndex: app.config.UI.Z_INDEX.ID_BADGE,
				backgroundColor: "#FFFFFF",
				borderRadius: "8px",
				boxShadow: "0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1)",
				border: "1px solid rgba(0, 0, 0, 0.1)",
				padding: "12px",
				minWidth: app.config.UI.DIMENSIONS.BADGE_MIN_WIDTH,
				maxWidth: app.config.UI.DIMENSIONS.BADGE_MAX_WIDTH,
				display: "flex",
				flexDirection: "column",
				gap: "8px",
				fontFamily: "Segoe UI, Helvetica, Arial, sans-serif",
				fontSize: "13px",
				color: "#050505",
				opacity: "0",
				visibility: isBadgeVisible.value ? "visible" : "hidden",
				pointerEvents: isBadgeVisible.value ? "auto" : "none",
				transition: "opacity 0.1s ease-out, visibility 0.1s ease-out"
			},
			children: [
				u("div", {
					style: {
						display: "flex",
						justifyContent: "space-between",
						alignItems: "center",
						marginBottom: "4px",
						borderBottom: "1px solid #DADDE1",
						paddingBottom: "8px"
					},
					children: [u("span", {
						style: {
							fontWeight: "600",
							color: "#65676B"
						},
						children: "ID Revealer"
					}), u("div", {
						onClick: (e) => {
							e.stopPropagation();
							idRevealerInstance.closeBadge();
						},
						style: {
							cursor: "pointer",
							padding: "4px",
							borderRadius: "50%",
							display: "flex",
							alignItems: "center",
							justifyContent: "center",
							transition: "background-color 0.2s"
						},
						onMouseOver: (e) => {
							e.currentTarget.style.backgroundColor = "#F0F2F5";
						},
						onMouseOut: (e) => {
							e.currentTarget.style.backgroundColor = "transparent";
						},
						children: u("svg", {
							viewBox: "0 0 24 24",
							width: "16",
							height: "16",
							fill: "#65676B",
							children: u("path", { d: "M18.707 5.293a1 1 0 0 0-1.414 0L12 10.586 6.707 5.293a1 1 0 0 0-1.414 1.414L10.586 12l-5.293 5.293a1 1 0 0 0 1.414 1.414L12 13.414l5.293 5.293a1 1 0 0 0 1.414-1.414L13.414 12l5.293-5.293a1 1 0 0 0 0-1.414z" })
						})
					})]
				}),
				profileName.value && u("div", {
					onClick: () => handleRowClick(profileName.value, T.profile_name_label || "Profile Name"),
					className: "gm-revealer-row",
					style: rowStyle,
					onMouseOver: handleRowMouseOver,
					onMouseOut: handleRowMouseOut,
					children: [u("span", {
						style: labelStyle,
						children: T.profile_name_label || "Profile Name"
					}), u("span", {
						style: valueStyle,
						title: profileName.value,
						children: profileName.value
					})]
				}),
				idMap.value.map(([label, id]) => u("div", {
					onClick: () => handleRowClick(id, label),
					className: "gm-revealer-row",
					style: rowStyle,
					onMouseOver: handleRowMouseOver,
					onMouseOut: handleRowMouseOut,
					children: [u("span", {
						style: labelStyle,
						children: label
					}), u("span", {
						style: valueStyle,
						title: id,
						children: id
					})]
				}, label)),
				profileUrl.value && u("div", {
					onClick: () => handleRowClick(profileUrl.value, T.profile_url_label || "Profile URL"),
					className: "gm-revealer-row",
					style: rowStyle,
					onMouseOver: handleRowMouseOver,
					onMouseOut: handleRowMouseOut,
					children: [u("span", {
						style: labelStyle,
						children: T.profile_url_label || "Profile URL"
					}), u("span", {
						style: {
							...valueStyle,
							color: "#1877F2",
							fontWeight: "400"
						},
						title: profileUrl.value,
						children: profileUrl.value
					})]
				}),
				profileUrl.value && u("div", {
					style: {
						marginTop: "8px",
						paddingTop: "8px",
						borderTop: "1px solid #DADDE1",
						textAlign: "center"
					},
					children: u("button", {
						onClick: handleCopyAll,
						style: {
							border: "none",
							background: "none",
							color: "#1877F2",
							fontWeight: "600",
							cursor: "pointer",
							fontSize: "13px",
							width: "100%",
							padding: "4px"
						},
						onMouseOver: (e) => {
							e.currentTarget.style.textDecoration = "underline";
						},
						onMouseOut: (e) => {
							e.currentTarget.style.textDecoration = "none";
						},
						children: T.id_copy_all || "Copy All Info"
					})
				})
			]
		});
	};
	var rowStyle = {
		display: "flex",
		alignItems: "center",
		justifyContent: "space-between",
		padding: "4px 8px",
		borderRadius: "4px",
		cursor: "pointer",
		transition: "background-color 0.1s"
	};
	var labelStyle = {
		color: "#65676B",
		fontWeight: "500",
		marginRight: "8px"
	};
	var valueStyle = {
		color: "#050505",
		fontWeight: "600",
		whiteSpace: "nowrap",
		overflow: "hidden",
		textOverflow: "ellipsis",
		maxWidth: "200px",
		direction: "ltr"
	};
	var handleRowMouseOver = (e) => {
		e.currentTarget.style.backgroundColor = "#F0F2F5";
	};
	var handleRowMouseOut = (e) => {
		e.currentTarget.style.backgroundColor = "transparent";
	};
	var IdRevealer = class {
		app;
		rootEl = null;
		activeBadge = null;
		targetH1 = null;
		resizeListener = null;
		scrollListener = null;
		historyListener = null;
		clickListener = null;
		mouseoverListener = null;
		mouseoutListener = null;
		signals = {
			isBadgeVisible: y$1(false),
			profileName: y$1(""),
			idMap: y$1([]),
			profileUrl: y$1("")
		};
		constructor(app) {
			this.app = app;
		}
		init() {
			if (!this.app.state.settings.idRevealerEnabled) return;
			this.resizeListener = () => this.updatePosition();
			this.scrollListener = () => this.updatePosition();
			this.historyListener = () => this.closeBadge();
			window.addEventListener("resize", this.resizeListener);
			window.addEventListener("scroll", this.scrollListener, true);
			window.addEventListener("historyChange", this.historyListener);
			this.clickListener = (e) => {
				const target = e.target;
				if (!target) return;
				const h1 = target.closest("h1");
				if (h1) {
					const inDialog = h1.closest("[role=\"dialog\"]");
					const inSettings = h1.closest(".gm-settings-modal");
					if (inDialog || inSettings) return;
					e.stopPropagation();
					e.preventDefault();
					if (this.signals.isBadgeVisible.value && this.targetH1 === h1) this.closeBadge();
					else this.showBadge(h1);
				}
			};
			document.addEventListener("click", this.clickListener, true);
			this.mouseoverListener = (e) => {
				const target = e.target;
				if (!target) return;
				const h1 = target.closest("h1");
				if (h1 && !h1.closest("[role=\"dialog\"]") && !h1.closest(".gm-settings-modal")) {
					h1.style.cursor = "pointer";
					h1.style.textDecoration = "underline";
					h1.style.textDecorationColor = "rgba(0,0,0,0.3)";
					h1.title = this.app.state.T.idRevealerTooltip || "Click to reveal ID & Info";
				}
			};
			this.mouseoutListener = (e) => {
				const target = e.target;
				if (!target) return;
				const h1 = target.closest("h1");
				if (h1) h1.style.textDecoration = "none";
			};
			document.addEventListener("mouseover", this.mouseoverListener, true);
			document.addEventListener("mouseout", this.mouseoutListener, true);
			this.rootEl = document.createElement("div");
			this.rootEl.id = "gm-id-revealer-root";
			document.body.appendChild(this.rootEl);
			R(u(IdBadgeComponent, {
				app: this.app,
				idRevealerInstance: this,
				signals: this.signals
			}), this.rootEl);
		}
		deinit() {
			this.closeBadge();
			if (this.rootEl) {
				this.rootEl.remove();
				this.rootEl = null;
			}
			if (this.resizeListener) window.removeEventListener("resize", this.resizeListener);
			if (this.scrollListener) window.removeEventListener("scroll", this.scrollListener, true);
			if (this.historyListener) window.removeEventListener("historyChange", this.historyListener);
			if (this.clickListener) {
				document.removeEventListener("click", this.clickListener, true);
				this.clickListener = null;
			}
			if (this.mouseoverListener) {
				document.removeEventListener("mouseover", this.mouseoverListener, true);
				this.mouseoverListener = null;
			}
			if (this.mouseoutListener) {
				document.removeEventListener("mouseout", this.mouseoutListener, true);
				this.mouseoutListener = null;
			}
		}
		inject() {}
		extractIds() {
			const ids = {
				metaId: null,
				userId: null,
				pageId: null,
				groupId: null
			};
			for (const sel of ["meta[property=\"al:android:url\"]", "meta[property=\"al:ios:url\"]"]) {
				const meta = document.querySelector(sel);
				if (meta && meta.content) {
					const profileMatch = meta.content.match(/fb:\/\/profile\/(\d+)/);
					if (profileMatch && profileMatch[1]) ids.metaId = profileMatch[1];
					const groupMatch = meta.content.match(/fb:\/\/group\/(\d+)/) || meta.content.match(/fb:\/\/group\/\?id=(\d+)/);
					if (groupMatch && groupMatch[1]) ids.groupId = groupMatch[1];
				}
			}
			if (!ids.metaId && !ids.groupId) {
				const metaApp = document.querySelector("meta[name=\"apple-itunes-app\"]");
				if (metaApp && metaApp.content) {
					const profileMatch = metaApp.content.match(/app-argument=fb:\/\/profile\/(\d+)/);
					if (profileMatch && profileMatch[1]) ids.metaId = profileMatch[1];
					const groupMatch = metaApp.content.match(/app-argument=fb:\/\/group\/\?id=(\d+)/);
					if (groupMatch && groupMatch[1]) ids.groupId = groupMatch[1];
				}
			}
			const scripts = document.querySelectorAll("script[type=\"application/json\"]");
			const reUserID = /"userID":"(\d+)"/;
			const reDelegate = /"delegate_page":\{[^{}]*"id":"(\d+)"/;
			const reAssoc = /"associated_page_id":"(\d+)"/;
			for (const script of scripts) {
				const content = script.textContent;
				if (!content) continue;
				if (!ids.userId) {
					const mUser = content.match(reUserID);
					if (mUser && mUser[1] !== "0") ids.userId = mUser[1];
				}
				if (!ids.pageId) {
					const mDel = content.match(reDelegate);
					if (mDel && mDel[1] && mDel[1] !== "0") ids.pageId = mDel[1];
					else {
						const mAssoc = content.match(reAssoc);
						if (mAssoc && mAssoc[1] && mAssoc[1] !== "0") ids.pageId = mAssoc[1];
					}
				}
				if (ids.userId && ids.pageId) break;
			}
			const T = this.app.state.T;
			const result = new Map();
			if (ids.groupId) result.set(T.id_label_group || "Group ID", ids.groupId);
			if (ids.metaId) result.set(T.id_label_meta || "Profile ID", ids.metaId);
			if (ids.userId && ids.userId !== ids.metaId) result.set(T.id_label_user || "User ID", ids.userId);
			if (ids.pageId && ids.pageId !== ids.metaId && ids.pageId !== ids.userId) result.set(T.id_label_page || "Page ID", ids.pageId);
			return result;
		}
		generateLink(id, isGroup = false) {
			if (isGroup) return `https://www.facebook.com/groups/${id}`;
			const format = this.app.state.settings.idRevealerLinkFormat;
			if (format === "classic") return `https://www.facebook.com/profile.php?id=${id}`;
			if (format === "username") {
				const url = new URL(window.location.href);
				url.search = "";
				return url.href.replace(/\/$/, "");
			}
			return `https://www.facebook.com/${id}`;
		}
		showBadge(h1) {
			const idMap = this.extractIds();
			if (idMap.size === 0) return;
			this.targetH1 = h1;
			this.signals.profileName.value = this._extractText(h1);
			this.signals.idMap.value = Array.from(idMap.entries());
			const isGroup = window.location.pathname.includes("/groups/");
			const mainId = idMap.values().next().value;
			this.signals.profileUrl.value = mainId ? this.generateLink(mainId, isGroup) : "";
			this.signals.isBadgeVisible.value = true;
		}
		_extractText(node) {
			let text = "";
			for (const child of node.childNodes) if (child.nodeType === Node.TEXT_NODE) text += child.textContent;
			return text.trim();
		}
		updatePosition() {
			if (!this.activeBadge || !this.targetH1) return;
			const rect = this.targetH1.getBoundingClientRect();
			const badgeRect = this.activeBadge.getBoundingClientRect();
			let top = rect.bottom + 8;
			let left = rect.left;
			const viewportWidth = window.innerWidth;
			const viewportHeight = window.innerHeight;
			if (left + badgeRect.width > viewportWidth) left = viewportWidth - badgeRect.width - 20;
			if (left < 0) left = 10;
			if (top + badgeRect.height > viewportHeight) top = rect.top - badgeRect.height - 8;
			this.activeBadge.style.top = `${top}px`;
			this.activeBadge.style.left = `${left}px`;
		}
		closeBadge() {
			this.signals.isBadgeVisible.value = false;
			this.activeBadge = null;
			this.targetH1 = null;
		}
	};
	var PostNavigatorCore = class {
		app;
		currentPostIndex = -1;
		isRetrying = false;
		continuousNavInterval = null;
		constructor(app) {
			this.app = app;
		}
		init() {}
		getSortedPosts() {
			const posts = Array.from(document.querySelectorAll("[role=\"article\"][aria-posinset]"));
			const dialogSelector = this.app.config.SELECTORS.GLOBAL.DIALOG;
			const filtered = posts.filter((p) => !p.closest(dialogSelector));
			filtered.sort((a, b) => {
				return parseInt(a.getAttribute("aria-posinset") || "0", 10) - parseInt(b.getAttribute("aria-posinset") || "0", 10);
			});
			return filtered;
		}
		startContinuousNavigation(direction) {
			this.stopContinuousNavigation();
			this.updateActivePost(direction === "next" ? this.currentPostIndex + 1 : this.currentPostIndex - 1, "manual");
			const interval = this.app.state.settings.continuousNavInterval || 1e3;
			this.continuousNavInterval = setInterval(() => {
				this.updateActivePost(direction === "next" ? this.currentPostIndex + 1 : this.currentPostIndex - 1, "manual");
			}, interval);
		}
		stopContinuousNavigation() {
			if (this.continuousNavInterval) {
				clearInterval(this.continuousNavInterval);
				this.continuousNavInterval = null;
			}
		}
		updateActivePost(index, source = "manual", forceSmooth = null) {
			const posts = this.getSortedPosts();
			if (posts.length === 0) return;
			if (index >= posts.length) {
				if (source === "manual") {
					this.triggerLoadAndRetry();
					return;
				}
				index = posts.length - 1;
			}
			if (index < 0) index = 0;
			if (index === this.currentPostIndex && source !== "manual") return;
			this.currentPostIndex = index;
			const targetPost = posts[this.currentPostIndex];
			this.app.state.lastActivePost = targetPost;
			const C = this.app.config;
			const settings = this.app.state.settings;
			const currentHighlighted = document.querySelector(`.${C.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS}`);
			if (currentHighlighted && currentHighlighted !== targetPost) currentHighlighted.classList.remove(C.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS);
			if (targetPost && settings.navHighlighterEnabled) {
				targetPost.classList.add(C.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS);
				if (settings.heatmapBorderEnabled && this.app.modules.timelineNavigator) {
					const heat = this.app.modules.timelineNavigator.getHeatLevel(targetPost);
					if (heat > 0) targetPost.dataset.heat = String(heat);
					else delete targetPost.dataset.heat;
				} else delete targetPost.dataset.heat;
			}
			if (this.app.modules.timelineNavigator) this.app.modules.timelineNavigator.setActive(index);
			if (source === "manual" || source === "timeline") this.app.utils.scrollToElement(targetPost, forceSmooth, null, this.app);
		}
		triggerLoadAndRetry() {
			if (this.isRetrying) return;
			this.isRetrying = true;
			const initialPostCount = this.getSortedPosts().length;
			window.scrollTo({
				top: document.body.scrollHeight,
				behavior: "smooth"
			});
			const startTime = Date.now();
			const retryInterval = setInterval(() => {
				if (this.getSortedPosts().length > initialPostCount) {
					clearInterval(retryInterval);
					this.isRetrying = false;
					this.updateActivePost(initialPostCount, "manual");
					return;
				}
				if (Date.now() - startTime > this.app.config.TIMEOUTS.MAX_RETRY_DURATION) {
					clearInterval(retryInterval);
					this.isRetrying = false;
					console.log(`${this.app.config.LOG_PREFIX} Failed to load new posts.`);
				}
			}, this.app.config.TIMEOUTS.RETRY_INTERVAL);
		}
		navigateToPost(direction) {
			this.updateActivePost(direction === "next" ? this.currentPostIndex + 1 : this.currentPostIndex - 1, "manual");
		}
	};
	var ScreenshotHandler = class {
		app;
		constructor(app) {
			this.app = app;
		}
		async toDataURLWithCORS(imgUrl) {
			return new Promise((resolve) => {
				if (!imgUrl) return resolve("");
				if (imgUrl.startsWith("data:") || imgUrl.startsWith("blob:")) return resolve(imgUrl);
				const fallbackFetch = () => {
					fetch(imgUrl).then((res) => res.blob()).then((blob) => {
						const reader = new FileReader();
						reader.onloadend = () => resolve(reader.result);
						reader.onerror = () => resolve("");
						reader.readAsDataURL(blob);
					}).catch(() => resolve(""));
				};
				if (typeof GM_xmlhttpRequest === "undefined") {
					fallbackFetch();
					return;
				}
				try {
					GM_xmlhttpRequest({
						method: "GET",
						url: imgUrl,
						responseType: "blob",
						onload: (response) => {
							if (response.status >= 200 && response.status < 300 && response.response) {
								const reader = new FileReader();
								reader.onloadend = () => resolve(reader.result);
								reader.onerror = () => resolve("");
								reader.readAsDataURL(response.response);
							} else fallbackFetch();
						},
						onerror: () => {
							fallbackFetch();
						}
					});
				} catch (e) {
					fallbackFetch();
				}
			});
		}
		findTimestampLinksInCloned(clonedEl) {
			const candidates = Array.from(clonedEl.querySelectorAll("a[role=\"link\"]"));
			const tk = this.app.config.TIME_KEYWORDS;
			return candidates.filter((link) => isTimestampLink(link, tk));
		}
		async capture(postEl) {
			if (!postEl) return false;
			try {
				const C_TOOLS = this.app.config.SELECTORS.POST_TOOLS;
				const expandBtn = Array.from(postEl.querySelectorAll(C_TOOLS?.EXPAND_BTN || "div[role=\"button\"]")).find((btn) => isSeeMoreButton(btn) && btn.offsetParent !== null);
				if (expandBtn) {
					expandBtn.click();
					await delay(200);
				}
			} catch (e) {
				console.warn("[FB Login Wall Remover] [Screenshot] Failed to auto-expand post:", e);
			}
			try {
				const PHT = this.app.modules.postHeaderTools;
				const settings = this.app.state.settings;
				let url = "";
				let useSmartFetch = false;
				let contentType = "";
				if (PHT) {
					contentType = PHT.determinePostContentType(postEl);
					useSmartFetch = settings.copier_useSmartLink && contentType === "standard";
				}
				const permalinkPromise = (async () => {
					if (PHT && useSmartFetch) try {
						const result = await PHT.fetchPermalinkInBackground(postEl);
						if (result && result.url) return result.url;
					} catch (e) {
						console.error("[FB Login Wall Remover] [Screenshot] Smart permalink fetch failed:", e);
					}
					return null;
				})();
				const imagesPromise = (async () => {
					const base64Map = new Map();
					try {
						const images = Array.from(postEl.querySelectorAll("img"));
						const svgImages = Array.from(postEl.querySelectorAll("image"));
						const allElements = Array.from(postEl.querySelectorAll("*"));
						const allImageUrls = new Set();
						images.forEach((img) => {
							if (img.src) allImageUrls.add(img.src);
						});
						svgImages.forEach((img) => {
							const href = img.getAttribute("href") || img.getAttribute("xlink:href");
							if (href) allImageUrls.add(href);
						});
						allElements.forEach((el) => {
							const bg = el.style.backgroundImage || window.getComputedStyle(el).backgroundImage;
							if (bg && bg !== "none") {
								const match = bg.match(/url\(['"]?(.*?)['"]?\)/);
								if (match && match[1] && !match[1].startsWith("data:")) allImageUrls.add(match[1]);
							}
						});
						Array.from(postEl.querySelectorAll("video")).forEach((video) => {
							const poster = video.getAttribute("poster") || video.poster;
							if (poster) allImageUrls.add(poster);
							let current = video.parentElement;
							for (let i = 0; i < 3; i++) {
								if (!current) break;
								const bg = current.style.backgroundImage || window.getComputedStyle(current).backgroundImage;
								if (bg && bg !== "none") {
									const match = bg.match(/url\(['"]?(.*?)['"]?\)/);
									if (match && match[1] && !match[1].startsWith("data:")) {
										allImageUrls.add(match[1]);
										break;
									}
								}
								current = current.parentElement;
							}
						});
						const downloadPromises = Array.from(allImageUrls).map(async (url) => {
							const base64 = await this.toDataURLWithCORS(url);
							if (base64) base64Map.set(url, base64);
						});
						await Promise.all(downloadPromises);
					} catch (e) {
						console.error("[FB Login Wall Remover] [Screenshot] Error pre-fetching images:", e);
					}
					return base64Map;
				})();
				const [resolvedUrl, base64Map] = await Promise.all([permalinkPromise, imagesPromise]);
				let postId = "";
				let username = "";
				let postDateStr = "";
				if (PHT) {
					let authorEl = postEl.querySelector("div[data-ad-rendering-role=\"profile_name\"] a[role=\"link\"], div[data-ad-rendering-role=\"profile_name\"] a, h2 a[role=\"link\"], h2 a, h3 a[role=\"link\"], h3 a");
					if (!authorEl) {
						const anchors = Array.from(postEl.querySelectorAll("a[role=\"link\"], a[href]"));
						for (const a of anchors) {
							if (a.closest("[data-ad-rendering-role=\"story_message\"]") || a.closest(".gm-tools-wrapper") || a.querySelector("i[data-visualcompletion=\"css-img\"]")) continue;
							const href = a.href || "";
							try {
								const pathname = new URL(href, window.location.origin).pathname;
								if (pathname.includes("/posts/") || pathname.includes("/videos/") || pathname.includes("/reel/") || pathname.includes("/photos/") || pathname.includes("fbid=") || pathname.includes("story_fbid=") || pathname.includes("permalink.php")) continue;
								authorEl = a;
								break;
							} catch (e) {}
						}
					}
					let domUsername = "";
					let domDisplayName = "";
					let domIsNumeric = false;
					if (authorEl) {
						domDisplayName = (authorEl.textContent || "").trim();
						if (authorEl.href) try {
							const u = new URL(authorEl.href);
							const searchParams = u.searchParams;
							if (u.pathname === "/profile.php" && searchParams.has("id")) {
								domUsername = searchParams.get("id") || "";
								domIsNumeric = true;
							} else {
								const pathParts = u.pathname.split("/").filter(Boolean);
								if (pathParts.length > 0) if (pathParts[0] === "groups") {
									if (pathParts.length > 2 && pathParts[1] === "user") domUsername = pathParts[2];
									else if (pathParts[0] === "groups" && pathParts.length > 1) domUsername = pathParts[1];
								} else if (pathParts[0] === "posts" || pathParts[0] === "videos" || pathParts[0] === "reel" || pathParts[0] === "watch") {} else domUsername = pathParts[0];
							}
							if (domUsername && /^\d+$/.test(domUsername)) domIsNumeric = true;
						} catch (e) {
							console.error("[FB Login Wall Remover] [Screenshot] Error parsing author DOM link href:", e);
						}
					}
					url = resolvedUrl || PHT.getPermalinkDirectlyFromElement(postEl).url || PHT.getSourceUrlForWorker(postEl) || window.location.href;
					let urlUsername = "";
					let urlIsNumeric = false;
					if (url) {
						postId = extractPostIdFromUrl(url) || "";
						try {
							const u = new URL(url);
							const searchParams = u.searchParams;
							if (u.pathname === "/profile.php" && searchParams.has("id")) {
								urlUsername = searchParams.get("id") || "";
								urlIsNumeric = true;
							} else {
								const pathParts = u.pathname.split("/").filter(Boolean);
								if (pathParts.length > 0) if (pathParts[0] === "groups") {
									if (pathParts.length > 2 && pathParts[1] === "user") urlUsername = pathParts[2];
									else if (pathParts[0] === "groups" && pathParts.length > 1) urlUsername = pathParts[1];
								} else if (pathParts[0] === "posts" || pathParts[0] === "videos" || pathParts[0] === "reel" || pathParts[0] === "watch") {} else urlUsername = pathParts[0];
							}
							if (urlUsername && /^\d+$/.test(urlUsername)) urlIsNumeric = true;
						} catch (e) {
							console.error("[FB Login Wall Remover] [Screenshot] Error parsing username from url:", e);
						}
					}
					if (domUsername && !domIsNumeric) username = domUsername;
					else if (urlUsername && !urlIsNumeric) username = urlUsername;
					else if (domDisplayName) username = domDisplayName;
					else if (domUsername) username = domUsername;
					else if (urlUsername) username = urlUsername;
					const timeLink = PHT.findTimestampLink(postEl);
					if (timeLink) {
						const rawTime = timeLink.getAttribute("aria-label") || (timeLink.textContent || "").trim();
						if (rawTime) {
							const dateMatch = convertToAbsoluteTimestamp(rawTime).match(/^(\d{4})\/(\d{2})\/(\d{2})/);
							if (dateMatch) postDateStr = `${dateMatch[1]}${dateMatch[2]}${dateMatch[3]}`;
						}
					}
				}
				if (!postDateStr) postDateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
				const sanitize = (str) => str.replace(/[\/\\:*?"<>|]/g, "_");
				let fileIdentifier = "";
				const safeUsername = username ? sanitize(username) : "";
				const safePostId = postId ? sanitize(postId) : "";
				if (safeUsername && safePostId) fileIdentifier = `${safeUsername}_${safePostId}`;
				else if (safeUsername) fileIdentifier = safeUsername;
				else if (safePostId) fileIdentifier = safePostId;
				else fileIdentifier = "screenshot";
				const isDarkMode = document.documentElement.classList.contains("__fb-dark-mode");
				const clonedEl = postEl.cloneNode(true);
				clonedEl.querySelectorAll(".gm-tools-wrapper, .gm-post-number").forEach((el) => el.remove());
				const originalStyle = window.getComputedStyle(postEl);
				clonedEl.style.fontFamily = originalStyle.fontFamily;
				clonedEl.style.fontSize = originalStyle.fontSize;
				clonedEl.style.fontWeight = originalStyle.fontWeight;
				clonedEl.style.lineHeight = originalStyle.lineHeight;
				const computedStyle = window.getComputedStyle(document.documentElement);
				for (let i = 0; i < computedStyle.length; i++) {
					const prop = computedStyle[i];
					if (prop.startsWith("--")) {
						const val = computedStyle.getPropertyValue(prop);
						if (val) clonedEl.style.setProperty(prop, val);
					}
				}
				Array.from(clonedEl.querySelectorAll("img")).forEach((img) => {
					img.removeAttribute("srcset");
					const originalSrc = img.src;
					const base64Src = base64Map.get(originalSrc);
					if (base64Src) img.src = base64Src;
				});
				Array.from(clonedEl.querySelectorAll("image")).forEach((img) => {
					const originalHref = img.getAttribute("href") || img.getAttribute("xlink:href") || "";
					const base64Src = base64Map.get(originalHref);
					if (base64Src) {
						img.setAttribute("href", base64Src);
						img.setAttribute("xlink:href", base64Src);
					}
				});
				Array.from(clonedEl.querySelectorAll("*")).forEach((el) => {
					const bg = el.style.backgroundImage || window.getComputedStyle(el).backgroundImage;
					if (bg && bg !== "none") {
						const match = bg.match(/url\(['"]?(.*?)['"]?\)/);
						if (match && match[1]) {
							const originalUrl = match[1];
							const base64 = base64Map.get(originalUrl);
							if (base64) el.style.setProperty("background-image", `url("${base64}")`, "important");
						}
					}
				});
				const videos = Array.from(postEl.querySelectorAll("video"));
				Array.from(clonedEl.querySelectorAll("video")).forEach((video, index) => {
					const originalVideo = videos[index];
					if (!originalVideo) return;
					const poster = originalVideo.getAttribute("poster") || originalVideo.poster;
					let base64Poster = poster ? base64Map.get(poster) : null;
					if (!base64Poster) {
						let current = originalVideo.parentElement;
						for (let i = 0; i < 3; i++) {
							if (!current) break;
							const bg = current.style.backgroundImage || window.getComputedStyle(current).backgroundImage;
							if (bg && bg !== "none") {
								const match = bg.match(/url\(['"]?(.*?)['"]?\)/);
								if (match && match[1]) {
									base64Poster = base64Map.get(match[1]) || null;
									if (base64Poster) break;
								}
							}
							current = current.parentElement;
						}
					}
					if (base64Poster) {
						const imgReplacement = document.createElement("img");
						imgReplacement.src = base64Poster;
						imgReplacement.className = originalVideo.className;
						if (originalVideo.hasAttribute("style")) imgReplacement.setAttribute("style", originalVideo.getAttribute("style") || "");
						const videoStyle = window.getComputedStyle(originalVideo);
						imgReplacement.style.width = originalVideo.style.width || videoStyle.width || "100%";
						imgReplacement.style.height = originalVideo.style.height || videoStyle.height || "100%";
						const originalObjectFit = originalVideo.style.objectFit || videoStyle.objectFit;
						imgReplacement.style.objectFit = originalObjectFit && originalObjectFit !== "none" && originalObjectFit !== "fill" ? originalObjectFit : "contain";
						imgReplacement.style.position = originalVideo.style.position || videoStyle.position || "relative";
						imgReplacement.style.top = originalVideo.style.top || videoStyle.top || "0px";
						imgReplacement.style.left = originalVideo.style.left || videoStyle.left || "0px";
						imgReplacement.style.transform = originalVideo.style.transform || videoStyle.transform || "none";
						const widthAttr = originalVideo.getAttribute("width");
						const heightAttr = originalVideo.getAttribute("height");
						if (widthAttr) imgReplacement.setAttribute("width", widthAttr);
						if (heightAttr) imgReplacement.setAttribute("height", heightAttr);
						video.replaceWith(imgReplacement);
					}
				});
				clonedEl.style.boxShadow = "none";
				clonedEl.style.border = "none";
				clonedEl.style.borderRadius = "8px";
				clonedEl.style.padding = "12px 16px";
				clonedEl.style.boxSizing = "border-box";
				clonedEl.style.overflow = "hidden";
				if (isDarkMode) {
					clonedEl.style.backgroundColor = "#242526";
					clonedEl.style.color = "#E4E6EB";
				} else {
					clonedEl.style.backgroundColor = "#FFFFFF";
					clonedEl.style.color = "#050505";
				}
				if (settings.screenshotEmbedLink && url) {
					const watermark = document.createElement("div");
					watermark.className = "gm-screenshot-watermark";
					watermark.style.setProperty("margin-top", "16px", "important");
					watermark.style.setProperty("padding-top", "8px", "important");
					watermark.style.setProperty("border-top", isDarkMode ? "1px solid #3e4042" : "1px solid #e5e5e5", "important");
					watermark.style.setProperty("font-size", "13px", "important");
					watermark.style.setProperty("color", isDarkMode ? "#E4E6EB" : "#050505", "important");
					watermark.style.setProperty("text-align", "left", "important");
					watermark.style.setProperty("white-space", "pre-wrap", "important");
					watermark.style.setProperty("word-break", "break-all", "important");
					watermark.style.setProperty("line-height", "1.4", "important");
					watermark.style.setProperty("display", "block", "important");
					watermark.style.setProperty("opacity", "1.0", "important");
					watermark.style.setProperty("font-family", originalStyle.fontFamily, "important");
					watermark.textContent = `🔗 ${url}`;
					clonedEl.appendChild(watermark);
				}
				let cssText = "";
				document.querySelectorAll("style").forEach((styleNode) => {
					try {
						const sheet = styleNode.sheet;
						if (sheet) {
							const rules = sheet.cssRules || sheet.rules;
							if (rules && rules.length > 0) {
								for (let j = 0; j < rules.length; j++) cssText += rules[j].cssText + "\n";
								return;
							}
						}
					} catch (e) {}
					cssText += (styleNode.textContent || styleNode.innerHTML || "") + "\n";
				});
				if (cssText.trim()) {
					const injectedStyle = document.createElement("style");
					injectedStyle.textContent = cssText;
					clonedEl.insertBefore(injectedStyle, clonedEl.firstChild);
				}
				const originalWidth = postEl.getBoundingClientRect().width || postEl.offsetWidth || 680;
				clonedEl.style.width = `${originalWidth}px`;
				this.findTimestampLinksInCloned(clonedEl).forEach((clonedTimeLink) => {
					clonedTimeLink.style.setProperty("white-space", "nowrap", "important");
					clonedTimeLink.style.setProperty("display", "inline-block", "important");
					if (clonedTimeLink.parentElement) {
						clonedTimeLink.parentElement.style.setProperty("white-space", "nowrap", "important");
						clonedTimeLink.parentElement.style.setProperty("display", "inline-flex", "important");
						clonedTimeLink.parentElement.style.setProperty("align-items", "center", "important");
						clonedTimeLink.parentElement.style.setProperty("flex-wrap", "nowrap", "important");
						Array.from(clonedTimeLink.parentElement.children).forEach((child) => {
							child.style.setProperty("display", "inline-block", "important");
							child.style.setProperty("white-space", "nowrap", "important");
							child.style.setProperty("vertical-align", "middle", "important");
						});
					}
				});
				Array.from(clonedEl.querySelectorAll("a[href*=\"comment_id=\"]")).forEach((link) => {
					link.style.setProperty("white-space", "nowrap", "important");
					link.style.setProperty("display", "inline-block", "important");
					if (link.parentElement) {
						link.parentElement.style.setProperty("white-space", "nowrap", "important");
						link.parentElement.style.setProperty("display", "inline-block", "important");
					}
				});
				Array.from(clonedEl.querySelectorAll("a")).forEach((a) => {
					const href = a.getAttribute("href") || "";
					const text = (a.textContent || "").trim();
					if (!text || text.length > 50) return;
					if (href.includes("comment_id=")) return;
					if (href.includes("l.facebook.com")) return;
					if (href.includes("/hashtag/")) return;
					if (/^(https?:\/\/|www\.)/i.test(text)) return;
					let isProfile = false;
					try {
						if (href.startsWith("/") || href.includes("facebook.com")) {
							const url = new URL(href, window.location.origin);
							const path = url.pathname;
							const pathParts = path.split("/").filter(Boolean);
							if (url.searchParams.has("id") && path === "/profile.php") isProfile = true;
							else if (pathParts.length === 1) {
								const p = pathParts[0];
								if (![
									"posts",
									"videos",
									"reel",
									"photos",
									"groups",
									"events",
									"watch",
									"stories",
									"pages",
									"marketplace"
								].includes(p.toLowerCase())) isProfile = true;
							} else if (pathParts[0] === "groups" && pathParts.includes("user")) isProfile = true;
						}
					} catch (e) {}
					const authorHeading = a.closest("h2, h3, [data-ad-rendering-role=\"profile_name\"]");
					if (isProfile || authorHeading !== null) {
						if (authorHeading) {
							if ((authorHeading.textContent || "").trim().length > 45) {
								a.style.setProperty("white-space", "normal", "important");
								a.style.setProperty("display", "inline", "important");
								return;
							}
						}
						a.style.setProperty("white-space", "nowrap", "important");
						a.style.setProperty("display", "inline-block", "important");
					}
				});
				const nameWrapperSelector = this.app.config.SELECTORS.SCREENSHOT?.NAME_WRAPPER || ".x3nfvp2";
				let nameWrappers = Array.from(clonedEl.querySelectorAll(nameWrapperSelector));
				if (nameWrappers.length === 0) clonedEl.querySelectorAll("div[data-ad-rendering-role=\"profile_name\"], h2 a, h3 a").forEach((el) => {
					if ((el.getAttribute("href") || "").includes("comment_id=")) return;
					const htmlEl = el;
					if (htmlEl.tagName === "A") nameWrappers.push(htmlEl);
					else if (htmlEl.tagName === "DIV") nameWrappers.push(htmlEl);
				});
				nameWrappers.forEach((el) => {
					const text = (el.textContent || "").trim();
					if (text && text.length > 45) {
						el.style.setProperty("white-space", "normal", "important");
						el.style.setProperty("display", "inline", "important");
						Array.from(el.querySelectorAll("span, a")).forEach((child) => {
							child.style.setProperty("white-space", "normal", "important");
							child.style.setProperty("display", "inline", "important");
						});
						return;
					}
					el.style.setProperty("white-space", "nowrap", "important");
					el.style.setProperty("display", "inline-block", "important");
					Array.from(el.querySelectorAll("span, a")).forEach((child) => {
						child.style.setProperty("white-space", "nowrap", "important");
						child.style.setProperty("display", "inline-block", "important");
					});
				});
				Array.from(clonedEl.querySelectorAll("[role=\"button\"]")).forEach((btn) => {
					const text = (btn.textContent || "").trim();
					if (text.includes("comment") || text.includes("留言") || text.includes("回覆") || text.includes("返信") || text.includes("reply") || text.includes("replied") || text.includes("replies")) {
						btn.style.setProperty("white-space", "nowrap", "important");
						btn.style.setProperty("max-width", "none", "important");
						btn.style.setProperty("overflow", "visible", "important");
						Array.from(btn.querySelectorAll("span, div")).forEach((child) => {
							child.style.setProperty("white-space", "nowrap", "important");
							child.style.setProperty("text-overflow", "clip", "important");
							child.style.setProperty("overflow", "visible", "important");
							child.style.setProperty("max-width", "none", "important");
						});
					}
				});
				Array.from(clonedEl.querySelectorAll("[data-ad-preview=\"message\"], [data-ad-rendering-role=\"story_message\"]")).forEach((el) => {
					el.style.setProperty("white-space", "pre-wrap", "important");
					el.style.setProperty("margin-top", "12px", "important");
					el.style.setProperty("line-height", "1.3", "important");
					Array.from(el.querySelectorAll("*")).forEach((child) => {
						child.style.setProperty("line-height", "1.3", "important");
					});
				});
				Array.from(clonedEl.querySelectorAll("span[dir=\"auto\"]")).forEach((span) => {
					if (!span.closest(".x3nfvp2") && !span.querySelector("a")) span.style.setProperty("white-space", "pre-wrap", "important");
				});
				clonedEl.querySelectorAll("div[data-ad-rendering-role=\"story_message\"] [role=\"button\"], div[data-ad-comet-preview=\"message\"] [role=\"button\"]").forEach((btn) => btn.remove());
				if (this.app.state.settings.screenshotExcludeComments) {
					const postMarkers = [
						"[data-ad-preview=\"message\"]",
						"[data-ad-rendering-role=\"story_message\"]",
						"[data-ad-rendering-role=\"profile_name\"]",
						"[role=\"toolbar\"]",
						"h2 a[role=\"link\"]",
						"h3 a[role=\"link\"]"
					];
					const isPostContent = (el) => {
						return postMarkers.some((selector) => el.querySelector(selector) !== null);
					};
					const removeCommentComponent = (compEl) => {
						let current = compEl;
						let toRemove = compEl;
						while (current && current !== clonedEl) {
							const parent = current.parentElement;
							if (!parent || parent === clonedEl) break;
							if (isPostContent(parent)) break;
							toRemove = parent;
							current = parent;
						}
						toRemove.remove();
					};
					Array.from(clonedEl.querySelectorAll("[role=\"article\"]")).forEach((art) => {
						if (art === clonedEl) return;
						if (!(art.querySelector("div[data-ad-rendering-role=\"story_message\"], div[data-ad-comet-preview=\"message\"]") !== null) && clonedEl.contains(art)) removeCommentComponent(art);
					});
					Array.from(clonedEl.querySelectorAll("[role=\"textbox\"], [contenteditable=\"true\"]")).forEach((box) => {
						if (clonedEl.contains(box)) removeCommentComponent(box);
					});
					Array.from(clonedEl.querySelectorAll(".x1hx0egp, [data-commentid]")).forEach((el) => {
						if (clonedEl.contains(el)) removeCommentComponent(el);
					});
					const allButtons = Array.from(clonedEl.querySelectorAll("[role=\"button\"]"));
					allButtons.forEach((btn) => {
						const text = (btn.textContent || "").trim();
						if (!text || !clonedEl.contains(btn)) return;
						const hasActionWord = /查看|檢視|回覆|View|Reply|reply|replies|replied/i.test(text);
						if (/^\d+/.test(text) && !hasActionWord) return;
						const lowerText = text.toLowerCase();
						if (lowerText === "comment" || text === "留言" || text === "コメント" || lowerText === "share" || text === "分享" || text === "シェア" || lowerText === "like" || text === "讚" || text === "いいね!") return;
						if (lowerText.includes("comment") || lowerText.includes("留言") || lowerText.includes("reply") || lowerText.includes("replies") || lowerText.includes("replied") || lowerText.includes("回覆") || lowerText.includes("返信")) removeCommentComponent(btn);
					});
					Array.from(clonedEl.querySelectorAll("[role=\"button\"]")).forEach((btn) => {
						const text = (btn.textContent || "").trim();
						if (text === "Interested" || text === "Not interested" || text === "感興趣" || text === "不感興趣" || text === "興味がある" || text === "興味がない") {
							if (clonedEl.contains(btn)) removeCommentComponent(btn);
						}
					});
					const likeBtn = allButtons.find((btn) => {
						const txt = (btn.textContent || "").trim().toLowerCase();
						return txt === "like" || txt === "讚" || txt === "超いいね!" || txt === "いいね!" || txt === "me gusta";
					});
					if (likeBtn) {
						let buttonsRow = likeBtn.parentElement;
						while (buttonsRow && buttonsRow !== clonedEl) {
							if (buttonsRow.querySelectorAll("[role=\"button\"]").length >= 2) break;
							buttonsRow = buttonsRow.parentElement;
						}
						if (buttonsRow && buttonsRow !== clonedEl) {
							let sibling = buttonsRow.nextElementSibling;
							if (!sibling && buttonsRow.parentElement) sibling = buttonsRow.parentElement.nextElementSibling;
							if (sibling && sibling.isConnected) {
								if (sibling.querySelector("[data-commentid]") || sibling.querySelector(".x1hx0egp") || sibling.textContent?.includes("comments") || sibling.textContent?.includes("留言") || sibling.textContent?.includes("Reply") || sibling.textContent?.includes("Replies") || sibling.querySelector("[role=\"button\"]")) sibling.remove();
							}
						}
					}
				}
				let parent = postEl.parentElement;
				const chain = [];
				while (parent && parent !== document.body) {
					chain.push({
						tag: parent.tagName,
						cls: parent.className,
						style: parent.getAttribute("style") || ""
					});
					parent = parent.parentElement;
				}
				const outermost = document.createElement("div");
				Object.assign(outermost.style, {
					position: "absolute",
					left: "-9999px",
					top: "-9999px",
					width: `${originalWidth}px`,
					height: "auto",
					overflow: "hidden",
					zIndex: "-9999",
					pointerEvents: "none"
				});
				let currentParent = outermost;
				for (let i = chain.length - 1; i >= 0; i--) {
					const nodeInfo = chain[i];
					const wrapperNode = document.createElement(nodeInfo.tag);
					wrapperNode.className = nodeInfo.cls;
					if (nodeInfo.style) wrapperNode.setAttribute("style", nodeInfo.style);
					wrapperNode.style.position = "static";
					wrapperNode.style.width = "auto";
					wrapperNode.style.height = "auto";
					wrapperNode.style.margin = "0";
					wrapperNode.style.padding = "0";
					currentParent.appendChild(wrapperNode);
					currentParent = wrapperNode;
				}
				currentParent.appendChild(clonedEl);
				document.body.appendChild(outermost);
				let canvas;
				try {
					const activeSnapdom = window.snapdom;
					const scaleVal = this.app.state.settings.screenshotScale || 2;
					canvas = await activeSnapdom.toCanvas(clonedEl, {
						scale: Number(scaleVal),
						exclude: [
							".gm-tools-wrapper",
							".gm-post-number",
							"div[data-ad-rendering-role=\"story_message\"] [role=\"button\"]",
							"div[data-ad-comet-preview=\"message\"] [role=\"button\"]"
						],
						backgroundColor: isDarkMode ? "#242526" : "#FFFFFF"
					});
				} finally {
					outermost.remove();
				}
				const format = this.app.state.settings.screenshotFormat || "png";
				const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
				const fileExt = format === "jpeg" ? "jpg" : "png";
				const quality = format === "jpeg" ? .9 : void 0;
				return new Promise((resolve) => {
					canvas.toBlob((blob) => {
						if (!blob) {
							resolve(false);
							return;
						}
						const url = URL.createObjectURL(blob);
						const a = document.createElement("a");
						a.href = url;
						a.download = `facebook_post_${fileIdentifier}_${postDateStr}.${fileExt}`;
						document.body.appendChild(a);
						a.click();
						setTimeout(() => {
							a.remove();
							URL.revokeObjectURL(url);
							resolve(true);
						}, 150);
					}, mimeType, quality);
				});
			} catch (e) {
				console.error("[FB Login Wall Remover] [Screenshot] Capture failed:", e);
				return false;
			}
		}
	};
	var PostHeaderTools = class {
		app;
		isProcessingClick = false;
		isModalOpening = false;
		observer = null;
		icons = {
			smart: `<svg viewBox="0 0 32 32" width="16" height="16"><path fill="#F5C33B" d="M18,11a1,1,0,0,1-1,1,5,5,0,0,0-5,5,1,1,0,0,1-2,0,5,5,0,0,0-5-5,1,1,0,0,1,0-2,5,5,0,0,0,5-5,1,1,0,0,1,2,0,5,5,0,0,0,5,5A1,1,0,0,1,18,11Z"/><path fill="#F5C33B" d="M19,24a1,1,0,0,1-1,1,2,2,0,0,0-2,2,1,1,0,0,1-2,0,2,2,0,0,0-2-2,1,1,0,0,1,0-2,2,2,0,0,0,2-2,1,1,0,0,1,2,0,2,2,0,0,0,2,2A1,1,0,0,1,19,24Z"/><path fill="#F5C33B" d="M28,17a1,1,0,0,1-1,1,4,4,0,0,0-4,4,1,1,0,0,1-2,0,4,4,0,0,0-4-4,1,1,0,0,1,0-2,4,4,0,0,0,4-4,1,1,0,0,1,2,0,4,4,0,0,0,4,4A1,1,0,0,1,28,17Z"/></svg>`,
			direct: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#1877F2" d="M13.29 9.29l-4 4a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l4-4a1 1 0 0 0-1.42-1.42z"/><path fill="#1877F2" d="M12.28 17.4L11 18.67a4.2 4.2 0 0 1-5.58.4 4 4 0 0 1-.27-5.93l1.42-1.43a1 1 0 0 0 0-1.42 1 1 0 0 0-1.42 0l-1.27 1.28a6.15 6.15 0 0 0-.67 8.07 6.06 6.06 0 0 0 9.07.6l1.42-1.42a1 1 0 0 0-1.42-1.42z"/><path fill="#1877F2" d="M19.66 3.22a6.18 6.18 0 0 0-8.13.68L10.45 5a1.09 1.09 0 0 0-.17 1.61 1 1 0 0 0 1.42 0L13 5.3a4.17 4.17 0 0 1 5.57-.4 4 4 0 0 1 .27 5.95l-1.42 1.43a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l1.42-1.42a6.06 6.06 0 0 0-.6-9.06z"/></svg>`,
			processing: `<svg viewBox="0 0 24 24" width="16" height="16" class="gm-spin"><path fill="#1877F2" d="M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z"></path></svg>`,
			success: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#42B72A" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></svg>`,
			failure: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#FA383E" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>`,
			copy: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#65676B" d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>`,
			bookmark: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#65676B" d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>`,
			bookmarkFilled: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#F5C33B" d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>`,
			screenshot: `<svg viewBox="0 0 24 24" width="16" height="16"><path fill="#65676B" d="M4 4h3l2-2h6l2 2h3a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm8 3a5 5 0 1 0 0 10 5 5 0 0 0 0-10zm0 2a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"/></svg>`
		};
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.observer) return;
			this.startObserver();
		}
		deinit() {
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			this.cleanupButtons();
		}
		async handlePermalinkClick(event, button) {
			if (this.isProcessingClick) return;
			event.preventDefault();
			event.stopPropagation();
			const C_TOOLS = this.app.config.SELECTORS.POST_TOOLS;
			const postEl = button.closest(`[data-${C_TOOLS.PROCESSED_MARKER}]`);
			if (!postEl) return;
			this.isProcessingClick = true;
			button.style.pointerEvents = "none";
			const originalContent = button.innerHTML;
			const T = this.app.state.T;
			const settings = this.app.state.settings;
			const iconWrapper = button.querySelector(".gm-icon-wrapper");
			if (iconWrapper) iconWrapper.innerHTML = this.icons.processing;
			try {
				const contentType = this.determinePostContentType(postEl);
				const timeLink = this.findTimestampLink(postEl);
				const isPeopleHome = timeLink?.href && this.app.utils.isPeopleHomeUrl ? this.app.utils.isPeopleHomeUrl(timeLink.href) : false;
				const { url: dataToCopy, method } = await (settings.copier_useSmartLink && contentType === "standard" && !isPeopleHome ? this.fetchPermalinkInBackground(postEl) : Promise.resolve(this.getPermalinkDirectlyFromElement(postEl))) || {
					url: null,
					method: "unknown_failure"
				};
				if (dataToCopy) {
					if (typeof GM_setClipboard === "function") GM_setClipboard(dataToCopy);
					const linkHTML = `<a href="${dataToCopy}" target="_blank" rel="noopener noreferrer">${dataToCopy}</a>`;
					const successMessage = (T.copier_notificationPermalinkCopied || "Copied: {url}").replace("{url}", linkHTML).replace(/\n/g, "<br>");
					this.app.modules.toastNotifier.show(successMessage, "success", 5e3);
					await this.animateButtonFeedback(button, "success", originalContent);
				} else {
					const msg = T[method.includes("no_source") ? "copier_notificationErrorNoSourceUrl" : method.includes("timeout") ? "copier_notificationErrorTimeout" : "copier_notificationErrorGeneric"] || "Failed to copy permalink.";
					this.app.modules.toastNotifier.show(msg, "failure");
					await this.animateButtonFeedback(button, "failure", originalContent);
				}
			} catch (error) {
				console.error(`${this.app.config.LOG_PREFIX} [Tools] Error:`, error);
				this.app.modules.toastNotifier.show(T.copier_notificationErrorGeneric || "An error occurred.", "failure");
				await this.animateButtonFeedback(button, "failure", originalContent);
			} finally {
				this.isProcessingClick = false;
			}
		}
		async handleCopyContentClick(event, button) {
			if (this.isProcessingClick) return;
			event.preventDefault();
			event.stopPropagation();
			const C_GLOBAL = this.app.config.SELECTORS.GLOBAL;
			const postEl = button.closest(C_GLOBAL.POST_CONTAINER);
			if (!postEl) return;
			const T = this.app.state.T;
			this.isProcessingClick = true;
			button.style.pointerEvents = "none";
			const originalContent = button.innerHTML;
			const iconWrapper = button.querySelector(".gm-icon-wrapper");
			if (iconWrapper) iconWrapper.innerHTML = this.icons.processing;
			try {
				const data = await this.extractPostData(postEl, { includeOrder: false });
				const text = this.formatPostData(data, "text");
				if (text) {
					if (typeof GM_setClipboard === "function") GM_setClipboard(text);
					const msg = (T.copier_copyContentSuccess || "Copied post content ({count} characters)").replace("{count}", String(text.length));
					this.app.modules.toastNotifier.show(msg, "success");
					await this.animateButtonFeedback(button, "success", originalContent);
				} else {
					this.app.modules.toastNotifier.show(T.copier_notificationContentNotFound || "Content not found.", "failure");
					await this.animateButtonFeedback(button, "failure", originalContent);
				}
			} catch (error) {
				console.error(`${this.app.config.LOG_PREFIX} [Tools] Copy Content Error:`, error);
				this.app.modules.toastNotifier.show(T.copier_copyContentFailed || "Failed to copy content.", "failure");
				await this.animateButtonFeedback(button, "failure", originalContent);
			} finally {
				this.isProcessingClick = false;
			}
		}
		async extractPostMetadata(postEl, options = {}) {
			const data = await this.extractPostData(postEl, options);
			return this.formatPostData(data, "text");
		}
		async extractPostData(postEl, options = {}) {
			if (!postEl) return null;
			const settings = this.app.state.settings;
			this.app.state.T;
			this.app.config.SELECTORS.POST_TOOLS;
			const sharedContainer = this.getSharedPostContainer(postEl);
			const allStoryMessages = Array.from(postEl.querySelectorAll("div[data-ad-rendering-role=\"story_message\"]"));
			let mainContentEl = allStoryMessages.find((el) => !sharedContainer || !sharedContainer.contains(el));
			const lifeEventHeader = Array.from(postEl.querySelectorAll("h3, h4")).find((header) => {
				if (header.closest("[data-commentid], .comment, .x1hx0egp")) return false;
				const a = header.querySelector("a");
				if (!a) return false;
				const href = a.getAttribute("href") || a.href || "";
				return href.includes("/posts/") || href.includes("/videos/") || href.includes("/reel/") || href.includes("/photos/") || href.includes("fbid=") || href.includes("story_fbid=") || href.includes("permalink.php");
			});
			if (!mainContentEl && lifeEventHeader) {
				const parent4 = lifeEventHeader.parentElement?.parentElement?.parentElement?.parentElement;
				if (parent4 && postEl.contains(parent4)) mainContentEl = parent4;
				else {
					const grandParent = lifeEventHeader.parentElement?.parentElement?.parentElement;
					if (grandParent && postEl.contains(grandParent)) mainContentEl = grandParent;
				}
			}
			if (mainContentEl) await this._expandReadMore(mainContentEl);
			const data = {
				meta: {
					id: null,
					url: null,
					order: options.includeOrder ? postEl.getAttribute("aria-posinset") : null,
					author: [],
					timestamp: null,
					location: null,
					group: null
				},
				content: "",
				stats: {
					reactions: {
						total: null,
						detailed: []
					},
					comments: null,
					shares: null
				},
				media: {
					imageCount: 0,
					videoDuration: null,
					videoDurations: [],
					linkPreview: null
				},
				sharedPost: null
			};
			let mainUrlPromise = Promise.resolve(null);
			if (!options.forceRawLink && settings.copier_useSmartLink) {
				if (this.determinePostContentType(postEl) === "standard") mainUrlPromise = this.fetchPermalinkInBackground(postEl);
			}
			let sharedUrlPromise = Promise.resolve(null);
			if (sharedContainer && !options.forceRawLink && settings.copier_useSmartLink) {
				if (this.determinePostContentType(sharedContainer) === "standard") sharedUrlPromise = this.fetchPermalinkInBackground(sharedContainer);
			}
			let linkUrl = null;
			const mainResult = await mainUrlPromise;
			if (mainResult && mainResult.url) linkUrl = mainResult.url;
			if (!linkUrl) linkUrl = this.getPermalinkDirectlyFromElement(postEl).url;
			data.meta.url = linkUrl;
			if (linkUrl) data.meta.id = extractPostIdFromUrl(linkUrl);
			const mainProfileRoot = Array.from(postEl.querySelectorAll("h2, h3, h4")).find((el) => !sharedContainer || !sharedContainer.contains(el));
			if (mainProfileRoot) {
				const headerData = this.extractAuthorsFromHeader(mainProfileRoot, sharedContainer);
				data.meta.author = headerData.authors;
				data.meta.location = headerData.location;
				data.meta.group = headerData.group;
				const isReviewPage = window.location.pathname.includes("/reviews");
				const hasReviewIcon = Array.from(mainProfileRoot.querySelectorAll("img")).some((img) => {
					const alt = img.getAttribute("alt") || "";
					return !(img.closest("a") !== null) && alt === "";
				});
				if ((isReviewPage || hasReviewIcon) && data.meta.author.length === 2) data.meta.isRecommendation = true;
			}
			if (mainProfileRoot) {
				const otherBtn = mainProfileRoot.querySelector("[role=\"button\"]:not(a)");
				if (otherBtn && (!sharedContainer || !sharedContainer.contains(otherBtn))) {
					const otherText = (otherBtn.textContent || "").trim();
					if (otherText) data.meta.author.push({
						name: otherText,
						link: ""
					});
				}
			}
			const timeLink = this.findTimestampLink(postEl);
			if (timeLink && (!sharedContainer || !sharedContainer.contains(timeLink))) {
				const rawTime = timeLink.getAttribute("aria-label") || (timeLink.textContent || "").trim();
				if (rawTime && rawTime.length > 50 && !/\d/.test(rawTime)) data.meta.timestamp = null;
				else data.meta.timestamp = settings.copy_meta_absolute_date ? convertToAbsoluteTimestamp(rawTime) : rawTime;
			}
			const toolbar = postEl.querySelector("[role=\"toolbar\"]");
			if (toolbar) {
				const directContainer = toolbar.parentElement;
				const footerArea = toolbar.closest("div[role=\"article\"] > div > div > div > div > div") || directContainer;
				const unitGroup = this.app.config.CONSTANTS.REGEX_PARTS.UNIT_GROUP;
				const numberPatternStr = `[\\d,.]+\\s*(${unitGroup})?(?:人)?`;
				const numberRegex = new RegExp(numberPatternStr);
				let totalReactionText = null;
				if (toolbar) {
					const allSpans = Array.from(toolbar.querySelectorAll("span"));
					const metricRegex = new RegExp(`^[\\d.,\\s]+(${unitGroup})?$`);
					for (const span of allSpans) {
						if (span.closest("[role=\"button\"]")) continue;
						const txt = (span.textContent || "").trim();
						if (txt && metricRegex.test(txt)) {
							totalReactionText = txt;
							break;
						}
					}
				}
				if (!totalReactionText) {
					const reactionKeywords = this.app.config.STATS_PATTERNS.REACTION_ALL_KEYWORDS;
					const findTotalByLabel = (container) => {
						if (!container) return null;
						const label = Array.from(container.children).find((el) => reactionKeywords.some((kw) => (el.textContent || "").includes(kw)));
						if (label && label.nextElementSibling) return (label.nextElementSibling.textContent || "").trim();
						return null;
					};
					totalReactionText = findTotalByLabel(directContainer) || findTotalByLabel(footerArea);
					if (!totalReactionText && footerArea) {
						const reactionIcon = footerArea.querySelector("[aria-label*=\"reaction\"], [aria-label*=\"心情\"], [aria-label*=\"リアクション\"]");
						if (reactionIcon && !reactionIcon.closest("div[role=\"article\"] div[role=\"article\"]")) {
							const m = (reactionIcon.closest("div")?.textContent || "").match(numberRegex);
							if (m) totalReactionText = m[0].replace(/\s+|人/g, "");
						}
					}
				}
				data.stats.reactions.total = totalReactionText;
				if (toolbar) {
					const reactionButtons = toolbar.querySelectorAll("[aria-label]");
					const reactionRegex = new RegExp(`(${[
						"Like",
						"Love",
						"Care",
						"Haha",
						"Wow",
						"Sad",
						"Angry",
						"讚",
						"大心",
						"加油",
						"哈",
						"哇",
						"嗚",
						"怒",
						"超いいね!",
						"いいね!",
						"大切だね",
						"うけるね",
						"すごいね",
						"悲しいね",
						"ひどいね"
					].join("|")})[::]\\s*(${numberPatternStr})`, "i");
					const emojiMap = {
						"like": "👍",
						"讚": "讚",
						"love": "❤️",
						"大心": "❤️",
						"care": "🫂",
						"加油": "🫂",
						"haha": "😆",
						"哈": "😆",
						"wow": "😮",
						"哇": "😮",
						"sad": "😢",
						"嗚": "😢",
						"angry": "😡",
						"怒": "😡",
						"いいね!": "👍",
						"超いいね!": "❤️",
						"大切だね": "🫂",
						"うけるね": "😆",
						"すごいね": "😮",
						"悲しいね": "😢",
						"ひどいね": "😡"
					};
					reactionButtons.forEach((btn) => {
						const label = btn.getAttribute("aria-label");
						if (!label) return;
						let type = null;
						const img = btn.querySelector("img");
						if (img) {
							const src = img.getAttribute("src") || "";
							if (src.startsWith("data:image/svg+xml")) {
								const decodedSvg = decodeURIComponent(src);
								const signatures = this.app.config.STATS_PATTERNS.REACTION_SIGNATURES;
								for (const [t, regex] of Object.entries(signatures)) if (regex.test(decodedSvg)) {
									type = t;
									break;
								}
							}
						}
						let count = "";
						if (type) {
							const m = label.match(numberRegex);
							if (m) count = m[0].replace(/\s+|人/g, "");
							else type = null;
						} else {
							const match = label.match(reactionRegex);
							if (match) {
								type = match[1];
								count = match[2].replace(/\s+|人/g, "");
							}
						}
						if (type && count !== "") {
							const emoji = emojiMap[type] || emojiMap[type.toLowerCase()];
							if (emoji) data.stats.reactions.detailed.push(`${emoji} ${count}`);
						}
					});
				}
				if (footerArea) {
					const icons = Array.from(footerArea.querySelectorAll("i[data-visualcompletion=\"css-img\"]"));
					let commentCount = "", shareCount = "";
					let commentButtonEl = null;
					let shareButtonEl = null;
					const extractCountFromIcon = (icon) => {
						let current = icon.parentElement;
						for (let i = 0; i < 4; i++) {
							if (!current) break;
							const text = (current.textContent || "").trim();
							if (text && new RegExp(`^${numberPatternStr}$`).test(text)) return text.replace(/\s+|人/g, "");
							const m = text.match(numberRegex);
							if (m) return m[0].replace(/\s+|人/g, "");
							const numberSpan = current.querySelector("span:not(:has(*))");
							if (numberSpan) {
								const mSpan = (numberSpan.textContent || "").trim().match(numberRegex);
								if (mSpan) return mSpan[0].replace(/\s+|人/g, "");
							}
							current = current.parentElement;
						}
						return null;
					};
					const yCoords = [];
					for (const icon of icons) {
						const bgPos = icon.style.backgroundPosition;
						if (bgPos) {
							const m = bgPos.match(/0px\s+(-?\d+)px/);
							if (m) yCoords.push(parseInt(m[1], 10));
						}
					}
					if (yCoords.length >= 2) {
						const y1 = yCoords[0];
						const y2 = yCoords[1];
						if (Math.abs(y1 - y2) === this.app.config.CONSTANTS.SPRITES.RELATIVE_OFFSET) if (y1 > y2) {
							this.app.state.activeCommentY = y1;
							this.app.state.activeShareY = y2;
						} else {
							this.app.state.activeCommentY = y2;
							this.app.state.activeShareY = y1;
						}
					}
					for (const icon of icons) {
						const bgPos = icon.style.backgroundPosition;
						if (!bgPos) continue;
						const match = bgPos.match(/0px\s+(-?\d+)px/);
						if (!match) continue;
						const yPos = parseInt(match[1], 10);
						const SPRITES = this.app.config.CONSTANTS.SPRITES;
						const activeCommentY = this.app.state.activeCommentY;
						const activeShareY = this.app.state.activeShareY;
						const isCommentIcon = activeCommentY != null ? yPos === activeCommentY : Math.abs(yPos - SPRITES.COMMENT) < SPRITES.TOLERANCE;
						const isShareIcon = activeShareY != null ? yPos === activeShareY : Math.abs(yPos - SPRITES.SHARE) < SPRITES.TOLERANCE;
						if (isCommentIcon && !commentCount) {
							commentCount = extractCountFromIcon(icon) || "";
							if (commentCount) commentButtonEl = icon.closest("[role=\"button\"], a");
						} else if (isShareIcon && !shareCount) {
							shareCount = extractCountFromIcon(icon) || "";
							if (shareCount) shareButtonEl = icon.closest("[role=\"button\"], a");
						}
					}
					if (!commentCount || !shareCount) {
						const footerButtons = Array.from(footerArea.querySelectorAll("[role=\"button\"]"));
						for (const btn of footerButtons) {
							if (btn.closest("div[role=\"article\"] div[role=\"article\"]")) continue;
							if (btn === commentButtonEl || btn === shareButtonEl) continue;
							const txt = (btn.textContent || "").trim();
							if (!txt) continue;
							const commentPattern = new RegExp(`(\\d+(?:[.,]\\d+)?\\s*${unitGroup}?)\\s*(?:${this.app.config.STATS_PATTERNS.COMMENT_KEYWORDS})`, "i");
							const commentMatch = txt.match(commentPattern);
							if (commentMatch && !commentCount) {
								commentCount = commentMatch[1].trim();
								commentButtonEl = btn;
								continue;
							}
							const commentPatternRev = new RegExp(`(?:${this.app.config.STATS_PATTERNS.COMMENT_KEYWORDS})\\s*(\\d+(?:[.,]\\d+)?\\s*${unitGroup}?)(?:\\s*개)?`, "i");
							const commentMatchRev = txt.match(commentPatternRev);
							if (commentMatchRev && !commentCount) {
								commentCount = commentMatchRev[1].trim();
								commentButtonEl = btn;
								continue;
							}
							const sharePattern = new RegExp(`(\\d+(?:[.,]\\d+)?\\s*${unitGroup}?)\\s*(?:${this.app.config.STATS_PATTERNS.SHARE_KEYWORDS})`, "i");
							const shareMatch = txt.match(sharePattern);
							if (shareMatch && !shareCount) {
								shareCount = shareMatch[1].trim();
								shareButtonEl = btn;
								continue;
							}
							const sharePatternRev = new RegExp(`(?:${this.app.config.STATS_PATTERNS.SHARE_KEYWORDS})\\s*(\\d+(?:[.,]\\d+)?\\s*${unitGroup}?)(?:\\s*[개회])?`, "i");
							const shareMatchRev = txt.match(sharePatternRev);
							if (shareMatchRev && !shareCount) {
								shareCount = shareMatchRev[1].trim();
								shareButtonEl = btn;
								continue;
							}
							if (new RegExp(`^${numberPatternStr}$`).test(txt)) {
								if (!commentCount) {
									commentCount = txt.replace(/\s+|人/g, "");
									commentButtonEl = btn;
								} else if (!shareCount) {
									shareCount = txt.replace(/\s+|人/g, "");
									shareButtonEl = btn;
								}
							}
						}
					}
					data.stats.comments = commentCount;
					data.stats.shares = shareCount;
				}
			}
			const uniqueImageIds = new Set();
			let extraHiddenImages = 0;
			(sharedContainer ? [] : Array.from(postEl.querySelectorAll("a[href*=\"/photo/\"][href*=\"fbid=\"], a[href*=\"photo.php\"][href*=\"fbid=\"]"))).forEach((link) => {
				if (link.closest("[role=\"article\"]") !== postEl) return;
				if (link.querySelector("img")) {
					const fbidMatch = (link.getAttribute("href") || "").match(/fbid=(\d+)/);
					if (fbidMatch) uniqueImageIds.add(fbidMatch[1]);
					const candidates = link.querySelectorAll("div");
					for (const cand of candidates) {
						const txt = (cand.textContent || "").trim();
						if (/^\+\d+$/.test(txt)) {
							const num = parseInt(txt.substring(1), 10);
							if (!isNaN(num)) extraHiddenImages = num;
							break;
						}
					}
				}
			});
			const totalImages = uniqueImageIds.size + extraHiddenImages - (extraHiddenImages > 0 ? 1 : 0);
			data.media.imageCount = totalImages;
			const mainMediaDurations = sharedContainer ? [] : this.extractVideoDurations(postEl);
			data.media.videoDurations = mainMediaDurations;
			data.media.videoDuration = mainMediaDurations[0] || null;
			data.media.linkPreview = sharedContainer ? null : this._extractLinkPreviewData(postEl);
			data.content = this._processContentBody(mainContentEl || null);
			if (!data.content) data.content = "";
			if (sharedContainer) {
				data.sharedPost = {
					meta: {
						id: null,
						url: null,
						author: [],
						timestamp: null,
						location: null,
						group: null
					},
					content: "",
					stats: {
						reactions: {
							total: null,
							detailed: []
						},
						comments: null,
						shares: null
					},
					media: {
						imageCount: 0,
						videoDuration: null,
						videoDurations: [],
						linkPreview: null
					}
				};
				const sharedProfileRoot = Array.from(sharedContainer.querySelectorAll("h2, h3, h4"))[0];
				if (sharedProfileRoot) {
					const sharedHeaderData = this.extractAuthorsFromHeader(sharedProfileRoot);
					data.sharedPost.meta.author = sharedHeaderData.authors;
					data.sharedPost.meta.location = sharedHeaderData.location;
					data.sharedPost.meta.group = sharedHeaderData.group;
				}
				const sharedTimeLink = this.findTimestampLink(sharedContainer);
				if (sharedTimeLink) {
					const rawTime = sharedTimeLink.getAttribute("aria-label") || (sharedTimeLink.textContent || "").trim();
					data.sharedPost.meta.timestamp = settings.copy_meta_absolute_date ? convertToAbsoluteTimestamp(rawTime) : rawTime;
				}
				const sharedContentEl = allStoryMessages.find((el) => sharedContainer.contains(el));
				if (sharedContentEl) {
					await this._expandReadMore(sharedContentEl);
					data.sharedPost.content = this._processContentBody(sharedContentEl);
				}
				const sharedMediaDurations = this.extractVideoDurations(sharedContainer);
				data.sharedPost.media.videoDurations = sharedMediaDurations;
				data.sharedPost.media.videoDuration = sharedMediaDurations[0] || null;
				const sharedImages = Array.from(sharedContainer.querySelectorAll("a[href*=\"/photo/\"][href*=\"fbid=\"], a[href*=\"photo.php\"][href*=\"fbid=\"]"));
				const uniqueSharedImageIds = new Set();
				let extraHiddenSharedImages = 0;
				sharedImages.forEach((link) => {
					if (link.closest("[role=\"article\"]") !== postEl) return;
					if (link.querySelector("img")) {
						const fbidMatch = (link.getAttribute("href") || "").match(/fbid=(\d+)/);
						if (fbidMatch) uniqueSharedImageIds.add(fbidMatch[1]);
						const cands = link.querySelectorAll("div");
						for (const cand of cands) {
							const txt = (cand.textContent || "").trim();
							if (/^\+\d+$/.test(txt)) {
								const num = parseInt(txt.substring(1), 10);
								if (!isNaN(num)) extraHiddenSharedImages = num;
								break;
							}
						}
					}
				});
				data.sharedPost.media.imageCount = uniqueSharedImageIds.size + extraHiddenSharedImages - (extraHiddenSharedImages > 0 ? 1 : 0);
				data.sharedPost.media.linkPreview = this._extractLinkPreviewData(sharedContainer);
				let sharedLinkUrl = null;
				const sharedResult = await sharedUrlPromise;
				if (sharedResult && sharedResult.url) sharedLinkUrl = sharedResult.url;
				if (!sharedLinkUrl) sharedLinkUrl = this.getPermalinkDirectlyFromElement(sharedContainer).url;
				data.sharedPost.meta.url = sharedLinkUrl;
				if (sharedLinkUrl) data.sharedPost.meta.id = extractPostIdFromUrl(sharedLinkUrl);
			}
			return data;
		}
		formatPostData(data, format = "text") {
			if (!data) return "";
			const settings = this.app.state.settings;
			const T = this.app.state.T;
			if (format === "json") return data;
			if (format === "csv") return {
				"Order": data.meta.order || "",
				"ID": data.meta.id || "",
				"URL": data.meta.url || "",
				"Author": data.meta.author.map((a) => a.name).join("; "),
				"Author Link": data.meta.author.map((a) => a.link).join("; "),
				"Location": data.meta.location ? data.meta.location.name : "",
				"Location Link": data.meta.location ? data.meta.location.link : "",
				"Group": data.meta.group ? data.meta.group.name : "",
				"Group Link": data.meta.group ? data.meta.group.link : "",
				"Time": data.meta.timestamp || "",
				"Content": data.content,
				"Reactions": data.stats.reactions.total || "0",
				"Reactions (Details)": data.stats.reactions.detailed ? data.stats.reactions.detailed.join("; ") : "",
				"Comments": data.stats.comments || "0",
				"Shares": data.stats.shares || "0",
				"Image Count": data.media.imageCount || "0",
				"Video Duration": data.media.videoDurations ? data.media.videoDurations.join("; ") : data.media.videoDuration || "",
				"Link Preview Title": data.media.linkPreview && data.media.linkPreview.title ? data.media.linkPreview.title : "",
				"Link Preview URL": data.media.linkPreview && data.media.linkPreview.url ? data.media.linkPreview.url : ""
			};
			const decodeUrlSafe = (url) => {
				if (!url) return "";
				try {
					return decodeURIComponent(url);
				} catch (e) {
					return url;
				}
			};
			const parts = [];
			if (settings.copy_includeMetadata && settings.copy_meta_url && data.meta.url) parts.push(data.meta.url + "\n");
			if (settings.copy_includeMetadata) {
				let headerLine = "";
				if (data.meta.order) headerLine += `[#${data.meta.order}] `;
				if (settings.copy_meta_author_name && data.meta.author.length > 0) {
					const authorStrings = data.meta.author.map((a) => {
						let s = a.name;
						if (settings.copy_meta_author_link && a.link) s += ` (${decodeUrlSafe(a.link)})`;
						return s;
					});
					let baseHeader = "";
					if (data.meta.isRecommendation && authorStrings.length === 2) baseHeader = (T.copier_relation_recommends || "{author1} recommends {author2}").replace("{author1}", authorStrings[0]).replace("{author2}", authorStrings[1]);
					else baseHeader = authorStrings.join(" & ");
					if (data.meta.group) {
						let groupStr = ` ➔ ${data.meta.group.name}`;
						if (settings.copy_meta_author_link && data.meta.group.link) groupStr += ` (${decodeUrlSafe(data.meta.group.link)})`;
						baseHeader += groupStr;
					}
					if (data.meta.location) {
						let locStr = ` @ ${data.meta.location.name}`;
						if (settings.copy_meta_author_link && data.meta.location.link) locStr += ` (${decodeUrlSafe(data.meta.location.link)})`;
						baseHeader += locStr;
					}
					headerLine += baseHeader;
				}
				if (headerLine) parts.push(headerLine);
			}
			if (settings.copy_includeMetadata) {
				let infoLine = "";
				if (settings.copy_meta_date && data.meta.timestamp) infoLine += data.meta.timestamp;
				const stats = [];
				if (settings.copy_meta_stats) {
					if (settings.copy_meta_stats_total && data.stats.reactions.total) {
						let s = `${data.stats.reactions.total} ${T.stats_label_reaction || "Reactions"}`;
						if (settings.copy_meta_stats_detailed && data.stats.reactions.detailed.length > 0) s += ` (${data.stats.reactions.detailed.join(" | ")})`;
						stats.push(s);
					} else if (data.stats.reactions.detailed.length > 0) stats.push(data.stats.reactions.detailed.join(" | "));
					if (data.stats.comments) stats.push(`💬 ${data.stats.comments}`);
					if (data.stats.shares) stats.push(`↗️ ${data.stats.shares}`);
				}
				if (stats.length > 0) infoLine += (infoLine ? " • " : "") + stats.join(" | ");
				if (settings.copy_meta_image_count && data.media.imageCount > 0) infoLine += (infoLine ? " • " : "") + `[${T.image_count_label || "Images"}: ${data.media.imageCount}]`;
				if (settings.copy_meta_video_duration && data.media.videoDurations && data.media.videoDurations.length > 0) {
					const typeLabel = T.label_video || "Video";
					const labelVideos = T.label_videos_plural || "Videos";
					const durations = data.media.videoDurations;
					const durStr = durations.length > 1 ? `${durations.length} ${labelVideos} (${durations.join(", ")})` : durations[0];
					infoLine += (infoLine ? " • " : "") + `[${typeLabel}: ${durStr}]`;
				}
				if (infoLine) parts.push(infoLine);
			}
			parts.push(data.content ? "\n-----------------------------------\n" : "");
			if (data.content) parts.push(data.content);
			else parts.push(T.label_no_text_content || "[No Text Content]");
			if (data.media.linkPreview) {
				const lp = data.media.linkPreview;
				parts.push("\n-----------------------------------\n");
				if (lp.title) parts.push(`➤ ${T.preview_label_title || "Title"}: ${lp.title}`);
				if (lp.source) parts.push(`➤ ${T.preview_label_source || "Source"}: ${lp.source}`);
				if (lp.desc) parts.push(`➤ ${T.preview_label_desc || "Description"}: ${lp.desc}`);
				if (lp.url) parts.push(`➤ ${T.preview_label_link || "Link"}: ${lp.url}`);
			}
			if (data.sharedPost) {
				parts.push("\n═══════════════════════════════════");
				parts.push(`🔄 ${T.copier_shared_post_label || "Shared Post"}`);
				let sharedHeader = "";
				if (data.sharedPost.meta.author.length > 0) {
					let baseShared = data.sharedPost.meta.author.map((a) => {
						let s = a.name;
						if (settings.copy_meta_author_link && a.link) s += ` (${decodeUrlSafe(a.link)})`;
						return s;
					}).join(" & ");
					if (data.sharedPost.meta.group) {
						let groupStr = ` ➔ ${data.sharedPost.meta.group.name}`;
						if (settings.copy_meta_author_link && data.sharedPost.meta.group.link) groupStr += ` (${decodeUrlSafe(data.sharedPost.meta.group.link)})`;
						baseShared += groupStr;
					}
					if (data.sharedPost.meta.location) {
						let locStr = ` @ ${data.sharedPost.meta.location.name}`;
						if (settings.copy_meta_author_link && data.sharedPost.meta.location.link) locStr += ` (${decodeUrlSafe(data.sharedPost.meta.location.link)})`;
						baseShared += locStr;
					}
					sharedHeader += baseShared;
				}
				if (data.sharedPost.meta.timestamp) sharedHeader += (sharedHeader ? " • " : "") + data.sharedPost.meta.timestamp;
				if (data.sharedPost.media.videoDurations && data.sharedPost.media.videoDurations.length > 0) {
					const typeLabel = T.label_video || "Video";
					const labelVideos = T.label_videos_plural || "Videos";
					const durations = data.sharedPost.media.videoDurations;
					const durStr = durations.length > 1 ? `${durations.length} ${labelVideos} (${durations.join(", ")})` : durations[0];
					sharedHeader += ` • [${typeLabel}: ${durStr}]`;
				}
				if (data.sharedPost.media.imageCount > 0) sharedHeader += ` • [${T.image_count_label || "Images"}: ${data.sharedPost.media.imageCount}]`;
				if (sharedHeader) parts.push(sharedHeader);
				if (settings.copy_meta_url && data.sharedPost.meta.url) parts.push(data.sharedPost.meta.url);
				parts.push("-----------------------------------");
				if (data.sharedPost.content) parts.push(data.sharedPost.content);
				else parts.push(T.label_no_text_content || "[No Text Content]");
				if (data.sharedPost.media.linkPreview) {
					const lp = data.sharedPost.media.linkPreview;
					parts.push("\n-----------------------------------");
					if (lp.title) parts.push(`➤ ${T.preview_label_title || "Title"}: ${lp.title}`);
					if (lp.source) parts.push(`➤ ${T.preview_label_source || "Source"}: ${lp.source}`);
					if (lp.desc) parts.push(`➤ ${T.preview_label_desc || "Description"}: ${lp.desc}`);
					if (lp.url) parts.push(`➤ ${T.preview_label_link || "Link"}: ${lp.url}`);
				}
			}
			return parts.join("\n");
		}
		_extractLinkPreviewData(postEl) {
			const settings = this.app.state.settings;
			if (!settings.copy_includeMetadata || !settings.copy_meta_link_preview) return null;
			this.app.state.T;
			const C_TOOLS = this.app.config.SELECTORS.POST_TOOLS;
			const previewLinks = Array.from(postEl.querySelectorAll("a[role=\"link\"]"));
			let previewLink = null;
			const titleEl = postEl.querySelector("[data-ad-rendering-role=\"title\"]");
			if (titleEl) {
				const contentContainer = titleEl.closest("div[id]");
				if (contentContainer) {
					const linkedAnchor = postEl.querySelector(`a[aria-labelledby="${contentContainer.id}"]`);
					if (linkedAnchor) previewLink = linkedAnchor;
				}
			}
			if (!previewLink && titleEl) {
				const container = titleEl.closest("div[class*=\"x\"]");
				if (container && container.parentElement) {
					const overlay = container.parentElement.querySelector("a[href][role=\"link\"]");
					if (overlay && overlay.getAttribute("href")) previewLink = overlay;
				}
			}
			if (!previewLink) previewLink = previewLinks.find((a) => a.querySelector("[data-ad-rendering-role=\"title\"]") && !a.closest(C_TOOLS.CONTENT_BODY)) || null;
			if (!previewLink) previewLink = previewLinks.find((a) => {
				if (a.closest(C_TOOLS.CONTENT_BODY)) return false;
				return a.querySelector("[style*=\"webkit-line-clamp\"]");
			}) || null;
			if (!previewLink) previewLink = previewLinks.find((a) => {
				if (a.closest(C_TOOLS.CONTENT_BODY)) return false;
				const labelId = a.getAttribute("aria-labelledby");
				if (!labelId) return false;
				const labelEl = postEl.querySelector(`#${labelId}`) || document.getElementById(labelId);
				return labelEl && labelEl.querySelector("[style*=\"webkit-line-clamp\"]");
			}) || null;
			if (titleEl || previewLink) {
				let title = "";
				if (titleEl) title = (titleEl.textContent || "").trim();
				else if (previewLink) {
					const labelId = previewLink.getAttribute("aria-labelledby");
					const styledTitle = ((labelId ? postEl.querySelector(`#${labelId}`) || document.getElementById(labelId) : null) || previewLink).querySelector("[style*=\"webkit-line-clamp\"]");
					if (styledTitle) title = (styledTitle.textContent || "").trim();
				}
				let meta = "";
				const metaNode = postEl.querySelector("[data-ad-rendering-role=\"meta\"]");
				if (metaNode) meta = (metaNode.textContent || "").trim();
				else if (titleEl) {
					let curr = titleEl;
					for (let i = 0; i < 5; i++) {
						if (!curr || curr === postEl) break;
						const prev = curr.previousElementSibling;
						if (prev && (prev.textContent || "").trim().length > 0 && !prev.querySelector("img")) {
							meta = (prev.textContent || "").trim();
							break;
						}
						curr = curr.parentElement;
					}
				}
				if (!meta && previewLink) {
					const labelId = previewLink.getAttribute("aria-labelledby");
					const labelEl = labelId ? postEl.querySelector(`#${labelId}`) || document.getElementById(labelId) : null;
					if (labelEl) {
						const leafNodes = Array.from(labelEl.querySelectorAll("span, div")).filter((node) => node.children.length === 0).map((node) => (node.textContent || "").trim()).filter((t) => t.length > 0 && t !== title && !title.includes(t));
						if (leafNodes.length > 0) meta = leafNodes[0];
					}
				}
				if (meta.length > 30) meta = "";
				const descNode = postEl.querySelector("[data-ad-rendering-role=\"description\"]");
				let desc = descNode ? (descNode.textContent || "").trim() : "";
				let href = previewLink ? previewLink.getAttribute("href") : "";
				if (href) try {
					const urlObj = new URL(href, window.location.origin);
					if (urlObj.hostname.includes("facebook.com") && urlObj.searchParams.has("u")) href = decodeURIComponent(urlObj.searchParams.get("u") || "");
					const cleanUrlObj = new URL(href, window.location.origin);
					this.app.utils.cleanUrlParams(cleanUrlObj);
					href = cleanUrlObj.toString();
				} catch (e) {}
				if (href && href.includes("/events/") && previewLink) {
					const texts = Array.from(previewLink.querySelectorAll("span[dir=\"auto\"], span[class*=\"x1lliihq\"]")).map((s) => (s.textContent || "").trim()).filter((t) => t.length > 0);
					const uniqueTexts = [];
					texts.forEach((t) => {
						if (!uniqueTexts.includes(t) && !uniqueTexts.some((existing) => existing.includes(t)) && !t.includes("\n")) uniqueTexts.push(t);
					});
					const descTexts = uniqueTexts.filter((t) => t !== title);
					if (descTexts.length > 0) desc = descTexts.join(" • ");
				}
				return {
					title,
					source: meta,
					desc,
					url: href
				};
			}
			return null;
		}
		async _expandReadMore(contentContainer) {
			if (!contentContainer) return;
			const C_TOOLS = this.app.config.SELECTORS.POST_TOOLS;
			const expandBtn = Array.from(contentContainer.querySelectorAll(C_TOOLS.EXPAND_BTN)).find((btn) => isSeeMoreButton(btn) && btn.offsetParent !== null);
			if (expandBtn) {
				expandBtn.click();
				await delay(150);
			}
		}
		_processContentBody(contentContainer) {
			if (!contentContainer) return "";
			const settings = this.app.state.settings;
			const targetContainer = contentContainer.cloneNode(true);
			targetContainer.querySelectorAll("[role=\"button\"]").forEach((btn) => {
				if (btn.tagName !== "A") btn.remove();
			});
			if (settings.copier_includeEmojis) targetContainer.querySelectorAll("img[src*=\"emoji\"][alt], img[alt]").forEach((img) => {
				const src = img.getAttribute("src") || "";
				const alt = img.getAttribute("alt");
				if (alt && (src.includes("emoji") || img.className.includes("emoji") || src.includes("fbcdn.net"))) img.replaceWith(document.createTextNode(alt));
			});
			targetContainer.querySelectorAll("a[href]").forEach((link) => {
				const anchor = link;
				const href = anchor.getAttribute("href");
				if (!href) return;
				let fullUrl = href;
				if (href.includes("l.facebook.com/l.php")) try {
					const uParam = new URL(href, window.location.origin).searchParams.get("u");
					if (uParam) fullUrl = decodeURIComponent(uParam);
				} catch (e) {}
				try {
					const urlObj = new URL(fullUrl, window.location.origin);
					this.app.utils.cleanUrlParams(urlObj);
					fullUrl = urlObj.href;
				} catch (e) {}
				const isHashtag = href.includes("/hashtag/");
				if (isHashtag) try {
					fullUrl = decodeURIComponent(fullUrl);
				} catch (e) {}
				const originalText = (anchor.textContent || "").trim();
				const isUrlText = /^(https?:\/\/|www\.|[a-z0-9.-]+\.[a-z]{2,})/i.test(originalText) || originalText.includes("...");
				const isMention = !isHashtag && !isUrlText;
				if (isHashtag) {
					if (settings.copier_expandHashtags) anchor.textContent = `${originalText} (${fullUrl})`;
					return;
				}
				if (isMention) {
					if (settings.copier_expandMentions) anchor.textContent = `${originalText} (${fullUrl})`;
					return;
				}
				anchor.textContent = fullUrl;
			});
			return this.app.utils.smartTextExtract(targetContainer);
		}
		async animateButtonFeedback(button, status, originalContent) {
			const iconWrapper = button.querySelector(".gm-icon-wrapper");
			if (iconWrapper) iconWrapper.innerHTML = status === "success" ? this.icons.success : this.icons.failure;
			button.style.backgroundColor = status === "success" ? "var(--positive-background)" : "var(--negative-background)";
			await delay(1200);
			button.style.pointerEvents = "auto";
			button.style.backgroundColor = "transparent";
			button.innerHTML = originalContent;
		}
		reEvaluateAllButtons() {
			this.cleanupButtons();
			this.scanNodeForPosts(document.body);
		}
		cleanupButtons() {
			const C = this.app.config.SELECTORS.POST_TOOLS;
			document.querySelectorAll(`[data-${C.PROCESSED_MARKER}]`).forEach((el) => {
				el.removeAttribute(`data-${C.PROCESSED_MARKER}`);
				el.querySelectorAll(`.gm-tools-wrapper`).forEach((wrapper) => wrapper.remove());
			});
		}
		scanNodeForPosts(node) {
			if (node.nodeType !== Node.ELEMENT_NODE) return;
			const pathname = window.location.pathname;
			if (pathname.includes("/photo/") || pathname.includes("/photo.php")) return;
			const element = node;
			const C_GLOBAL = this.app.config.SELECTORS.GLOBAL;
			const C_TOOLS = this.app.config.SELECTORS.POST_TOOLS;
			const SCAN_TARGETS = `${C_GLOBAL.POST_CONTAINER}, ${C_GLOBAL.DIALOG}`;
			const targets = element.matches(SCAN_TARGETS) ? [element] : [];
			element.querySelectorAll(SCAN_TARGETS).forEach((el) => targets.push(el));
			new Set(targets).forEach((target) => {
				if (target.hasAttribute(`data-${C_TOOLS.PROCESSED_MARKER}`)) return;
				if (target.matches(C_GLOBAL.POST_CONTAINER) && !target.parentElement?.closest(C_GLOBAL.POST_CONTAINER)) {
					let headerEl = target.querySelector(C_TOOLS.FEED_POST_HEADER);
					if (!headerEl) headerEl = target.querySelector(C_TOOLS.DIALOG_POST_HEADER);
					if (headerEl) this.addButtonsToPost(target, headerEl, false);
				} else if (target.matches(C_GLOBAL.DIALOG)) this.processDialogPost(target);
			});
		}
		processDialogPost(dialogEl) {
			this.isModalOpening = true;
			let observer = null;
			const C_GLOBAL = this.app.config.SELECTORS.GLOBAL;
			const C_TOOLS = this.app.config.SELECTORS.POST_TOOLS;
			const cleanup = () => {
				if (observer) observer.disconnect();
				clearTimeout(timeoutId);
				setTimeout(() => {
					this.isModalOpening = false;
				}, 200);
			};
			const timeoutId = setTimeout(cleanup, 3e3);
			const findAndProcessHeader = () => {
				const postEl = dialogEl.querySelector(C_GLOBAL.POST_CONTAINER);
				if (postEl) {
					const headerEl = postEl.querySelector(C_TOOLS.DIALOG_POST_HEADER);
					if (headerEl) {
						this.addButtonsToPost(postEl, headerEl, true);
						cleanup();
						return true;
					}
				}
				return false;
			};
			if (findAndProcessHeader()) return;
			observer = new MutationObserver(findAndProcessHeader);
			observer.observe(dialogEl, {
				childList: true,
				subtree: true
			});
		}
		addButtonsToPost(postEl, headerEl, isDialog = false) {
			const settings = this.app.state.settings;
			const C = this.app.config.SELECTORS.POST_TOOLS;
			if (!settings.permalinkCopierEnabled && !settings.enableCopyContentButton) return;
			const isSinglePage = !this.app.utils.isFeedPage();
			const useFixedDisplay = isDialog || isSinglePage;
			if (useFixedDisplay) {
				if (!headerEl?.parentElement || headerEl.parentElement.querySelector(`.gm-tools-wrapper`)) return;
			} else if (postEl.querySelector(`:scope > .gm-tools-wrapper`)) return;
			postEl.setAttribute(`data-${C.PROCESSED_MARKER}`, "true");
			const wrapper = this.app.utils.createStyledElement("div", {}, { className: "gm-tools-wrapper" });
			if (useFixedDisplay) {
				wrapper.classList.add("gm-in-dialog");
				if (isDialog) wrapper.style.marginRight = "16px";
			} else if (postEl.style.position !== "absolute" && postEl.style.position !== "fixed") postEl.style.position = "relative";
			if (settings.toolsPosition === "outer-right") wrapper.classList.add("gm-tools-wrapper--outer-right");
			if (settings.permalinkCopierEnabled) {
				const contentType = this.determinePostContentType(postEl);
				const timeLink = this.findTimestampLink(postEl);
				const isPeopleHome = timeLink?.href && this.app.utils.isPeopleHomeUrl ? this.app.utils.isPeopleHomeUrl(timeLink.href) : false;
				const isSmart = settings.copier_useSmartLink && contentType === "standard" && !isPeopleHome;
				const icon = isSmart ? this.icons.smart : this.icons.direct;
				const title = isSmart ? this.app.state.T.copier_fetchPermalinkSmart || "Copy Link (Smart)" : this.app.state.T.copier_fetchPermalinkDirect || "Copy Link (Direct)";
				const permalinkBtn = this.createButton("permalink", icon, title);
				wrapper.appendChild(permalinkBtn);
			}
			if (settings.enableCopyContentButton) {
				const copyBtn = this.createButton("copy-content", this.icons.copy, this.app.state.T.copier_copyContent || "Copy Post Content");
				wrapper.appendChild(copyBtn);
			}
			if (settings.enableBookmarks) {
				const url = this.getSourceUrlForWorker(postEl) || this.getPermalinkDirectlyFromElement(postEl).url;
				const bookmarks = BookmarkStorage.getAll();
				const postId = extractPostIdFromUrl(url);
				const icon = bookmarks.some((b) => b.url === url || postId && b.id === postId) ? this.icons.bookmarkFilled : this.icons.bookmark;
				const title = this.app.state.T.bookmark_action_title || "Bookmark Post";
				const bookmarkBtn = this.createButton("bookmark", icon, title);
				wrapper.appendChild(bookmarkBtn);
			}
			if (settings.screenshotEnabled) {
				const screenshotBtn = this.createButton("screenshot", this.icons.screenshot, this.app.state.T.copier_screenshot || "Capture Post Screenshot");
				wrapper.appendChild(screenshotBtn);
			}
			if (useFixedDisplay) {
				const insertionPoint = headerEl.parentElement;
				if (insertionPoint) {
					Object.assign(insertionPoint.style, {
						display: "flex",
						justifyContent: "space-between",
						alignItems: "center",
						width: "100%"
					});
					insertionPoint.appendChild(wrapper);
				}
			} else postEl.appendChild(wrapper);
		}
		createButton(action, svgIcon, title) {
			const C = this.app.config.SELECTORS.POST_TOOLS;
			const clickHandler = (e) => {
				const currentTarget = e.currentTarget;
				if (!currentTarget) return;
				if (action === "permalink") this.handlePermalinkClick(e, currentTarget);
				else if (action === "copy-content") this.handleCopyContentClick(e, currentTarget);
				else if (action === "bookmark") this.handleBookmarkClick(e, currentTarget);
				else if (action === "screenshot") this.handleScreenshotClick(e, currentTarget);
			};
			return this.app.utils.createStyledElement("div", {
				cursor: "pointer",
				backgroundColor: "transparent",
				color: "var(--secondary-text)",
				lineHeight: "1",
				border: "1px solid var(--media-inner-border)",
				transition: "all 0.15s ease-out",
				userSelect: "none",
				width: "28px",
				height: "28px",
				borderRadius: "50%",
				display: "flex",
				alignItems: "center",
				justifyContent: "center"
			}, {
				className: C.BUTTON_CLASS,
				role: "button",
				tabIndex: 0,
				title,
				"data-action": action,
				innerHTML: `<span class="gm-icon-wrapper">${svgIcon}</span>`,
				on: {
					click: clickHandler,
					mouseover: (e) => {
						const btn = e.currentTarget;
						if (btn && btn.style.pointerEvents !== "none") btn.style.backgroundColor = "var(--hover-overlay)";
					},
					mouseout: (e) => {
						const btn = e.currentTarget;
						if (btn && btn.style.pointerEvents !== "none") btn.style.backgroundColor = "transparent";
					}
				}
			});
		}
		determinePostContentType(container) {
			if (!container) return "unknown";
			const timeLink = this.findTimestampLink(container);
			if (timeLink?.href && this.app.utils.isPeopleHomeUrl && this.app.utils.isPeopleHomeUrl(timeLink.href)) return "people_home";
			const timestampUrl = this.getPermalinkFromTimestamp(container);
			if (!timestampUrl) {
				if (container.querySelector("a[href*=\"/reel/\"], video")) return "reel";
				if (container.querySelector("a[href*=\"/videos/\"], a[href*=\"/watch/\"]")) return "video";
				return "standard";
			}
			try {
				const { pathname } = new URL(timestampUrl, window.location.origin);
				if (pathname.includes("/reel/")) return "reel";
				if (pathname.includes("/videos/") || pathname.includes("/watch/")) return "video";
				if (pathname.includes("/events/")) return "event";
				return "standard";
			} catch (e) {
				return "standard";
			}
		}
		findTimestampLink(container) {
			if (!container) return null;
			const candidates = Array.from(container.querySelectorAll("a[role=\"link\"]"));
			const tk = this.app.config.TIME_KEYWORDS;
			return candidates.find((link) => isTimestampLink(link, tk)) || null;
		}
		getPermalinkFromTimestamp(container) {
			try {
				const timeLink = this.findTimestampLink(container);
				if (!timeLink?.href) return null;
				const rawUrl = new URL(timeLink.href, window.location.origin);
				const searchParams = rawUrl.searchParams;
				const basePath = `${rawUrl.protocol}//${rawUrl.host}${rawUrl.pathname}`;
				if (rawUrl.pathname.includes("/watch/")) {
					const videoId = searchParams.get("v");
					if (videoId) return `${basePath}?v=${videoId}`;
				} else if (rawUrl.pathname.includes("permalink.php") || rawUrl.search.includes("story_fbid=")) {
					const storyFbid = searchParams.get("story_fbid");
					const id = searchParams.get("id");
					if (storyFbid && id) return `${basePath}?story_fbid=${storyFbid}&id=${id}`;
				} else if (rawUrl.pathname.includes("photo.php") || searchParams.has("fbid")) {
					const fbid = searchParams.get("fbid");
					const setId = searchParams.get("set");
					if (fbid && setId) return `${basePath}?fbid=${fbid}&set=${setId}`;
					if (fbid) return `${basePath}?fbid=${fbid}`;
				} else if (rawUrl.search.includes("multi_permalinks=")) {
					const permalinkId = searchParams.get("multi_permalinks");
					return basePath.replace(/\/$/, "") + `/posts/${permalinkId}/`;
				}
				if (!(rawUrl.pathname.includes("/posts/") || rawUrl.pathname.includes("/videos/") || rawUrl.pathname.includes("/reel/") || rawUrl.pathname.includes("/photos/") || rawUrl.pathname.includes("/permalink/") || rawUrl.pathname.includes("/events/") || searchParams.has("fbid") || searchParams.has("story_fbid") || searchParams.has("v"))) return null;
				return basePath;
			} catch (e) {
				return null;
			}
		}
		getAnyPostUrl(container) {
			if (!container) return null;
			for (const selector of [
				"a[href*=\"/photo/\"]",
				"a[href*=\"fbid=\"]",
				"a[href*=\"/reel/\"]",
				"a[href*=\"/videos/\"]",
				"a[href*=\"/watch/\"]",
				"a[href*=\"/events/\"]"
			]) {
				const linkEl = container.querySelector(selector);
				if (linkEl?.href && !linkEl.href.includes("/profile.php")) return linkEl.href;
			}
			const timeElement = this.findTimestampLink(container);
			if (timeElement?.href) return timeElement.href;
			return null;
		}
		getSourceUrlForWorker(container) {
			return this.getPermalinkFromTimestamp(container) || this.getAnyPostUrl(container);
		}
		startObserver() {
			this.observer = new MutationObserver((mutations) => {
				mutations.forEach((m) => {
					m.addedNodes.forEach((n) => this.scanNodeForPosts(n));
				});
			});
			this.scanNodeForPosts(document.body);
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
		}
		fetchPermalinkInBackground(container) {
			return new Promise((resolve) => {
				const sourceUrl = this.getSourceUrlForWorker(container);
				if (!sourceUrl) return resolve({
					url: null,
					method: "worker_no_source_url"
				});
				const taskId = `fpc_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
				const workerUrl = new URL(sourceUrl);
				workerUrl.searchParams.set(this.app.config.WORKER_PARAM, taskId);
				let listenerId;
				const timeoutId = setTimeout(() => {
					if (listenerId && typeof GM_removeValueChangeListener === "function") GM_removeValueChangeListener(listenerId);
					resolve({
						url: null,
						method: "worker_timeout"
					});
				}, 8e3);
				if (typeof GM_addValueChangeListener === "function") listenerId = GM_addValueChangeListener(taskId, (name, oldVal, newVal, remote) => {
					if (remote && typeof newVal.permalink !== "undefined") {
						clearTimeout(timeoutId);
						if (typeof GM_removeValueChangeListener === "function") GM_removeValueChangeListener(listenerId);
						if (typeof GM_setValue === "function") {
							GM_setValue(taskId, { resolved: true });
							setTimeout(() => {
								try {
									if (typeof GM_deleteValue === "function") GM_deleteValue(taskId);
								} catch (e) {}
							}, 2e3);
						}
						resolve({
							url: newVal.permalink,
							method: "worker_" + newVal.method
						});
					}
				});
				if (typeof GM_openInTab === "function") GM_openInTab(workerUrl.href, {
					active: false,
					insert: true,
					setParent: true
				});
			});
		}
		getPermalinkDirectlyFromElement(container) {
			const timeLink = this.findTimestampLink(container);
			const dirtyUrl = timeLink?.href && this.app.utils.isPeopleHomeUrl && this.app.utils.isPeopleHomeUrl(timeLink.href) ? timeLink.href : this.getSourceUrlForWorker(container);
			if (!dirtyUrl) return {
				url: null,
				method: "direct_no_url"
			};
			try {
				if (this.app.utils.isPeopleHomeUrl && this.app.utils.isPeopleHomeUrl(dirtyUrl)) {
					const urlObj = new URL(dirtyUrl, window.location.origin);
					this.app.utils.cleanUrlParams(urlObj);
					try {
						return {
							url: decodeURIComponent(urlObj.href.replace(/\/$/, "")) + "/",
							method: "direct_cleaned_people_home"
						};
					} catch (e) {
						return {
							url: urlObj.href.replace(/\/$/, "") + "/",
							method: "direct_cleaned_people_home"
						};
					}
				}
				const urlObj = new URL(dirtyUrl, window.location.origin);
				this.app.utils.cleanUrlParams(urlObj);
				return {
					url: urlObj.href.replace(/\/$/, ""),
					method: "direct_cleaned"
				};
			} catch (e) {
				return {
					url: null,
					method: "direct_parse_error"
				};
			}
		}
		async handleScreenshotClick(event, button) {
			if (this.isProcessingClick) return;
			event.preventDefault();
			event.stopPropagation();
			const C_GLOBAL = this.app.config.SELECTORS.GLOBAL;
			const postEl = button.closest(C_GLOBAL.POST_CONTAINER);
			if (!postEl) return;
			const T = this.app.state.T;
			this.isProcessingClick = true;
			button.style.pointerEvents = "none";
			const originalContent = button.innerHTML;
			const iconWrapper = button.querySelector(".gm-icon-wrapper");
			if (iconWrapper) iconWrapper.innerHTML = this.icons.processing;
			try {
				if (!this.app.modules.screenshotHandler) this.app.modules.screenshotHandler = new ScreenshotHandler(this.app);
				if (await this.app.modules.screenshotHandler.capture(postEl)) {
					this.app.modules.toastNotifier.show(T.screenshot_success || "Screenshot downloaded successfully", "success");
					await this.animateButtonFeedback(button, "success", originalContent);
				} else {
					this.app.modules.toastNotifier.show(T.screenshot_failed || "Failed to capture screenshot", "failure");
					await this.animateButtonFeedback(button, "failure", originalContent);
				}
			} catch (error) {
				console.error(`${this.app.config.LOG_PREFIX} [Tools] Screenshot Capture Error:`, error);
				this.app.modules.toastNotifier.show(T.screenshot_failed || "Failed to capture screenshot", "failure");
				await this.animateButtonFeedback(button, "failure", originalContent);
			} finally {
				this.isProcessingClick = false;
			}
		}
		async handleBookmarkClick(event, button) {
			event.preventDefault();
			event.stopPropagation();
			const C_GLOBAL = this.app.config.SELECTORS.GLOBAL;
			const postEl = button.closest(C_GLOBAL.POST_CONTAINER);
			if (!postEl) return;
			const T = this.app.state.T;
			const settings = this.app.state.settings;
			const url = this.getSourceUrlForWorker(postEl) || this.getPermalinkDirectlyFromElement(postEl).url;
			if (!url) {
				this.app.modules.toastNotifier.show(T.copier_notificationErrorNoSourceUrl || "No source URL.", "failure");
				return;
			}
			button.style.pointerEvents = "none";
			const originalContent = button.innerHTML;
			const iconWrapper = button.querySelector(".gm-icon-wrapper");
			if (iconWrapper) iconWrapper.innerHTML = this.icons.processing;
			const postId = extractPostIdFromUrl(url);
			const bookmarks = BookmarkStorage.getAll();
			const index = bookmarks.findIndex((b) => b.url === url || postId && b.id === postId);
			const isAdded = index === -1;
			try {
				if (isAdded) {
					const useSmartFetch = settings.permalinkCopierEnabled && settings.copier_useSmartLink;
					const data = await this.extractPostData(postEl, {
						includeOrder: false,
						forceRawLink: !useSmartFetch
					});
					const finalUrl = data.meta.url || url;
					let authorName = "";
					if (data.meta.isRecommendation && data.meta.author.length === 2) authorName = (T.copier_relation_recommends || "{author1} recommends {author2}").replace("{author1}", data.meta.author[0].name).replace("{author2}", data.meta.author[1].name);
					else authorName = data.meta.author.map((a) => a.name).join(" & ") || "Unknown Author";
					const authorLink = data.meta.author.map((a) => a.link).join("; ") || "";
					const excerpt = data.content ? data.content.substring(0, 100) + (data.content.length > 100 ? "..." : "") : T.label_no_text_content || "[No Text Content]";
					const bookmarked = {
						id: data.meta.id || postId || `bm_${Date.now()}`,
						url: finalUrl,
						authorName,
						authorLink,
						timestamp: convertToAbsoluteTimestamp(data.meta.timestamp),
						excerpt,
						content: data.content || "",
						stats: data.stats,
						media: data.media,
						sharedPost: data.sharedPost,
						savedAt: Date.now()
					};
					bookmarks.push(bookmarked);
					BookmarkStorage.save(bookmarks);
					this.app.modules.toastNotifier.show(T.bookmark_post_added || "Post added to bookmarks.", "success");
					const successContent = `<span class="gm-icon-wrapper">${this.icons.bookmarkFilled}</span>`;
					await this.animateButtonFeedback(button, "success", successContent);
				} else {
					bookmarks.splice(index, 1);
					BookmarkStorage.save(bookmarks);
					this.app.modules.toastNotifier.show(T.bookmark_post_removed || "Post removed from bookmarks.", "success");
					const successContent = `<span class="gm-icon-wrapper">${this.icons.bookmark}</span>`;
					await this.animateButtonFeedback(button, "success", successContent);
				}
			} catch (error) {
				console.error(`${this.app.config.LOG_PREFIX} [Bookmark] Click Error:`, error);
				this.app.modules.toastNotifier.show(T.operation_failed, "failure");
				button.style.pointerEvents = "auto";
				button.innerHTML = originalContent;
			}
		}
		getSharedPostContainer(postEl) {
			const toolbar = postEl.querySelector("[role=\"toolbar\"]");
			const allHeaders = Array.from(postEl.querySelectorAll("h2, h3, h4")).filter((h) => {
				if (h.closest("[data-commentid], .comment, .x1hx0egp")) return false;
				if (toolbar) {
					if ((toolbar.compareDocumentPosition(h) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0) return false;
				}
				if (!(h.querySelector("a[role=\"link\"], a[href], b, [role=\"button\"]") !== null)) return false;
				const anchors = Array.from(h.querySelectorAll("a[href]"));
				if (anchors.length > 0 && anchors.every((a) => {
					const href = a.getAttribute("href") || "";
					return href.includes("/posts/") || href.includes("/videos/") || href.includes("/watch") || href.includes("/permalink/") || href.includes("/reel/") || href.includes("fbid=") || href.includes("story_fbid=") || href.includes("/events/");
				})) return false;
				return true;
			});
			if (allHeaders.length <= 1) return null;
			const firstProf = allHeaders[0];
			const secondProf = allHeaders[1];
			const firstMsg = Array.from(postEl.querySelectorAll("div[data-ad-rendering-role=\"story_message\"]")).find((msg) => {
				return (msg.compareDocumentPosition(secondProf) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
			});
			let curr = secondProf;
			while (curr && curr.parentElement && curr.parentElement !== postEl) {
				const parent = curr.parentElement;
				const containsFirstProf = parent.contains(firstProf);
				const containsFirstMsg = firstMsg ? parent.contains(firstMsg) : false;
				if (containsFirstProf || containsFirstMsg) break;
				curr = parent;
			}
			return curr;
		}
		extractAuthorsFromHeader(profileRoot, filterContainer = null) {
			const authors = [];
			let location = null;
			let group = null;
			if (!profileRoot) return {
				authors,
				location,
				group
			};
			const seenNames = new Set();
			let accumulatedText = "";
			const LOCATION_INDICATORS = [
				"is at",
				"was at",
				"were at",
				"at",
				" 在 ",
				" 在",
				"在 ",
				"in",
				"にいます",
				"にいました",
				"에 있습니다",
				"에 있었습니다",
				"está en",
				"estuvo en",
				"est à",
				"était à",
				"ist in",
				"war in",
				"đang ở",
				"presso",
				"está em",
				"esteve em",
				" di ",
				" di"
			];
			const walk = (node) => {
				if (node.nodeType === 3) {
					accumulatedText += node.textContent || "";
					return;
				}
				if (node.nodeType !== 1) return;
				const el = node;
				if (filterContainer && filterContainer.contains(el)) return;
				if (el.tagName === "A") {
					const name = cleanDomText(el);
					let link = el.href || el.getAttribute("href") || "";
					const isContentLink = link.includes("/events/") || link.includes("/posts/") || link.includes("/videos/") || link.includes("/watch") || link.includes("/permalink/") || link.includes("/photos/") || link.includes("/hashtag/");
					const isGroupLink = link.includes("/groups/");
					const isLocation = LOCATION_INDICATORS.some((indicator) => {
						const cleanedLast = accumulatedText.trim().toLowerCase();
						const cleanedInd = indicator.trim().toLowerCase();
						return cleanedLast.endsWith(cleanedInd);
					});
					if (name && !seenNames.has(name)) {
						try {
							const u = new URL(link, window.location.origin);
							this.app.utils.cleanUrlParams(u);
							link = u.href.replace(/\/$/, "");
						} catch (e) {}
						if (isGroupLink) {
							if (!group) group = {
								name,
								link
							};
						} else if (isLocation) {
							if (!location) location = {
								name,
								link
							};
						} else if (!isContentLink) {
							authors.push({
								name,
								link
							});
							seenNames.add(name);
						}
					}
					accumulatedText += el.textContent || "";
					return;
				}
				if (el.tagName === "B") {
					const hasAnchorInside = el.querySelector("a");
					const isInsideAnchor = el.closest("a");
					if (!hasAnchorInside && !isInsideAnchor) {
						const text = cleanDomText(el);
						const C = this.app.config;
						const isFoldButton = /\d/.test(text);
						const isConjunction = C.COAUTHOR_CONJUNCTIONS.some((conj) => text.toLowerCase().includes(conj.toLowerCase()));
						if (text && !isFoldButton && !isConjunction && !seenNames.has(text)) {
							authors.push({
								name: text,
								link: ""
							});
							seenNames.add(text);
						}
						accumulatedText += el.textContent || "";
						return;
					}
				}
				if (el.getAttribute("role") === "button" && el.tagName !== "A") {
					const hasAnchorInside = el.querySelector("a");
					const isInsideAnchor = el.closest("a");
					if (!hasAnchorInside && !isInsideAnchor) {
						const text = cleanDomText(el);
						const C = this.app.config;
						const isFoldButton = /\d/.test(text);
						const isConjunction = C.COAUTHOR_CONJUNCTIONS.some((conj) => text.toLowerCase().includes(conj.toLowerCase()));
						if (text && !isFoldButton && !isConjunction && !seenNames.has(text)) {
							authors.push({
								name: text,
								link: ""
							});
							seenNames.add(text);
						}
						accumulatedText += el.textContent || "";
						return;
					}
				}
				for (let i = 0; i < el.childNodes.length; i++) walk(el.childNodes[i]);
			};
			walk(profileRoot);
			if (authors.length === 0 && !location && !group) {
				const text = cleanDomText(profileRoot);
				if (text) authors.push({
					name: text,
					link: ""
				});
			}
			return {
				authors,
				location,
				group
			};
		}
		extractVideoDurations(container) {
			const durations = [];
			if (!container) return durations;
			const candidates = Array.from(container.querySelectorAll("div, span"));
			const playerTimePattern = /(\d+(?::\d+)+)\s*\/\s*(\d+(?::\d+)+)/;
			const badgePattern = /^(\d+(?::\d+)+)$/;
			const processedContainers = new Set();
			for (const el of candidates) {
				if (el.closest("div[data-ad-rendering-role=\"story_message\"]")) continue;
				const txt = (el.textContent || "").trim();
				if (!txt || !txt.includes("/")) continue;
				if ((txt.match(/\//g) || []).length === 1) {
					const m = txt.match(playerTimePattern);
					if (m) {
						durations.push(m[2]);
						processedContainers.add(el);
					}
				}
			}
			for (const el of candidates) {
				if (el.closest("div[data-ad-rendering-role=\"story_message\"]")) continue;
				if (el.children.length > 0) continue;
				let isInsideProcessed = false;
				for (const proc of processedContainers) if (proc.contains(el)) {
					isInsideProcessed = true;
					break;
				}
				if (isInsideProcessed) continue;
				const txt = (el.textContent || "").trim();
				if (badgePattern.test(txt)) durations.push(txt);
			}
			return Array.from(new Set(durations)).filter((d) => d);
		}
	};
	var TimelineRow = ({ post, originalIndex, displayIndex, isActive, score, logScore, sortMode, app, timelineInstance, onDotClick, maxLogScore }) => {
		const rowRef = A(null);
		const settings = app.state.settings;
		y$2(() => {
			if (isActive && rowRef.current && sortMode === "time") {
				const container = document.getElementById("gm-timeline-container");
				const scrollArea = container?.querySelector(".gm-timeline-scroll-area");
				if (container && scrollArea && !container.matches(":hover")) {
					const cRect = scrollArea.getBoundingClientRect();
					const rRect = rowRef.current.getBoundingClientRect();
					if (rRect.top < cRect.top + 20 || rRect.bottom > cRect.bottom - 20) rowRef.current.scrollIntoView({
						behavior: "smooth",
						block: "center"
					});
				}
			}
		}, [isActive, sortMode]);
		const idxLabel = displayIndex + 1;
		let isMilestone = false;
		let labelContent = "";
		if (sortMode === "heat") {
			labelContent = `<span class="gm-label-time" style="font-weight:600;color:#E41E3F">${timelineInstance.formatMetric(score)}</span>`;
			isMilestone = idxLabel <= 3;
		} else {
			labelContent = `<span class="gm-label-time">${timelineInstance.extractTime(post)}</span>`;
			isMilestone = idxLabel % 10 === 0;
		}
		let heatLevel = 0;
		if (settings.timelineHeatmapEnabled && maxLogScore > 1 && score > 0) {
			const ratio = logScore / maxLogScore;
			const thresholds = app.config.UI.HEATMAP_THRESHOLDS;
			for (let i = 0; i < thresholds.length; i++) if (ratio > thresholds[i]) {
				heatLevel = 9 - i;
				break;
			}
		}
		const handleClick = (e) => {
			e.preventDefault();
			e.stopPropagation();
			onDotClick(originalIndex);
		};
		return u("div", {
			ref: rowRef,
			className: `gm-timeline-row ${isMilestone ? "milestone" : ""} ${isActive ? "active" : ""}`,
			onClick: handleClick,
			children: [u("div", {
				className: "gm-timeline-info",
				dangerouslySetInnerHTML: { __html: `${labelContent}<span class="gm-label-idx ${isMilestone ? "milestone-text" : ""}">#${idxLabel}</span>` }
			}), u("div", {
				className: "gm-timeline-dot",
				"data-heat": heatLevel > 0 ? heatLevel.toString() : void 0
			})]
		});
	};
	var TimelineComponent = ({ app, timelineInstance, signals }) => {
		const T = app.state.T;
		const { sortMode, currentPostIndex, postsList, isBarVisible, heatmapMaxScore } = signals;
		const [activeHeatIndex, setActiveHeatIndex] = d$2(null);
		const toggleSortMode = () => {
			sortMode.value = sortMode.value === "time" ? "heat" : "time";
			timelineInstance.refresh(true);
		};
		const handleRowClick = (originalIndex) => {
			setActiveHeatIndex(originalIndex);
			timelineInstance.handleDotClick(originalIndex);
		};
		const displayItems = g$1(() => {
			const useHeatmap = app.state.settings.timelineHeatmapEnabled;
			const items = postsList.value.map((post, index) => {
				const score = useHeatmap ? timelineInstance.getPostScore(post) : 0;
				return {
					post,
					originalIndex: index,
					score,
					logScore: score > 0 ? Math.log10(score + 1) : 0
				};
			});
			if (sortMode.value === "heat") items.sort((a, b) => b.score - a.score);
			return items;
		});
		return u("div", {
			id: "gm-timeline-container",
			style: { display: isBarVisible.value ? "flex" : "none" },
			children: [u("div", {
				className: "gm-timeline-header",
				children: u("button", {
					className: "gm-timeline-sort-btn",
					title: T.timelineSortTooltip || "Switch Sort Mode",
					onClick: toggleSortMode,
					children: sortMode.value === "time" ? "⏱️" : "🔥"
				})
			}), u("div", {
				className: "gm-timeline-scroll-area",
				children: displayItems.value.map((item, idx) => {
					const isActive = sortMode.value === "heat" ? item.originalIndex === activeHeatIndex : item.originalIndex === currentPostIndex.value;
					return u(TimelineRow, {
						post: item.post,
						originalIndex: item.originalIndex,
						displayIndex: idx,
						isActive,
						score: item.score,
						logScore: item.logScore,
						sortMode: sortMode.value,
						app,
						timelineInstance,
						onDotClick: handleRowClick,
						maxLogScore: heatmapMaxScore.value
					}, `${sortMode.value}-${item.originalIndex}`);
				})
			})]
		});
	};
	var TimelineNavigator = class {
		app;
		rootEl = null;
		observer = null;
		watcher = null;
		isManualScrolling = false;
		scrollTimeout = null;
		lastUrl = "";
		signals = {
			sortMode: y$1("time"),
			currentPostIndex: y$1(-1),
			postsList: y$1([]),
			isBarVisible: y$1(false),
			heatmapMaxScore: y$1(0)
		};
		constructor(app) {
			this.app = app;
		}
		init() {
			this.lastUrl = window.location.href;
			if (!this.checkScope()) return;
			this.rootEl = document.createElement("div");
			this.rootEl.id = "gm-timeline-root";
			document.body.appendChild(this.rootEl);
			R(u(TimelineComponent, {
				app: this.app,
				timelineInstance: this,
				signals: this.signals
			}), this.rootEl);
			this.initObserver();
			this.startWatcher();
			this.refresh();
		}
		deinit() {
			if (this.rootEl) {
				R(null, this.rootEl);
				this.rootEl.remove();
				this.rootEl = null;
			}
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			if (this.watcher) {
				this.watcher.disconnect();
				this.watcher = null;
			}
			if (this.scrollTimeout) {
				clearTimeout(this.scrollTimeout);
				this.scrollTimeout = null;
			}
		}
		checkScope() {
			const path = window.location.pathname;
			const U = this.app.utils;
			if (path === "/" || path === "/home.php") return false;
			if (!U.isFeedPage()) return false;
			if ([
				"/search",
				"/ad_center",
				"/notes",
				"/ads",
				"/help",
				"/privacy",
				"/settings",
				"/saved",
				"/bookmarks"
			].some((p) => path.startsWith(p))) return false;
			return true;
		}
		refresh(force = false) {
			if (!this.checkScope()) {
				this.signals.isBarVisible.value = false;
				return;
			}
			this.signals.isBarVisible.value = true;
			if (this.lastUrl !== window.location.href) {
				this.signals.heatmapMaxScore.value = 0;
				this.lastUrl = window.location.href;
			}
			const Core = this.app.modules.postNavigatorCore;
			if (!Core) return;
			const posts = Core.getSortedPosts();
			this.signals.postsList.value = posts;
			if (this.app.state.settings.timelineHeatmapEnabled) {
				let currentBatchMax = 0;
				posts.forEach((post) => {
					const score = this.getPostScore(post);
					const logVal = score > 0 ? Math.log10(score + 1) : 0;
					if (logVal > currentBatchMax) currentBatchMax = logVal;
				});
				if (currentBatchMax > this.signals.heatmapMaxScore.value) this.signals.heatmapMaxScore.value = currentBatchMax;
			}
			if (this.observer) {
				this.observer.disconnect();
				if (this.signals.sortMode.value === "time") posts.forEach((post) => {
					this.observer?.observe(post);
				});
			}
		}
		setActive(index) {
			this.signals.currentPostIndex.value = index;
		}
		handleDotClick(index) {
			const Core = this.app.modules.postNavigatorCore;
			if (!Core) return;
			this.isManualScrolling = true;
			const forceSmooth = this.signals.sortMode.value === "heat" ? false : null;
			Core.updateActivePost(index, "timeline", forceSmooth);
			if (this.scrollTimeout) clearTimeout(this.scrollTimeout);
			this.scrollTimeout = setTimeout(() => {
				this.isManualScrolling = false;
			}, this.app.config.TIMEOUTS.SCROLL_LOCK);
		}
		getHeatLevel(post) {
			if (!this.app.state.settings.timelineHeatmapEnabled) return 0;
			const maxLog = this.signals.heatmapMaxScore.value;
			if (maxLog <= 1) return 0;
			const score = this.getPostScore(post);
			if (score <= 0) return 0;
			const ratio = Math.log10(score + 1) / maxLog;
			const thresholds = this.app.config.UI.HEATMAP_THRESHOLDS;
			for (let i = 0; i < thresholds.length; i++) if (ratio > thresholds[i]) return 9 - i;
			return 1;
		}
		getPostScore(postEl) {
			if (postEl.dataset.gmScore) return parseInt(postEl.dataset.gmScore, 10);
			let score = 0;
			const weights = this.app.config.UI.HEATMAP_WEIGHTS || {
				REACTION: 1,
				COMMENT: 2,
				SHARE: 3
			};
			const totalReactions = this.extractTotalReactions(postEl);
			if (totalReactions > 0) score += totalReactions * weights.REACTION;
			else {
				const ariaNodes = postEl.querySelectorAll("[aria-label]");
				for (const node of ariaNodes) {
					if (node.tagName === "A") continue;
					const label = node.getAttribute("aria-label");
					if (label && /[::]\s*[\d,.]+/.test(label)) {
						score += this.parseMetric(label) * weights.REACTION;
						break;
					}
				}
			}
			const deepStats = this.extractIconStats(postEl);
			score += deepStats.comments * weights.COMMENT;
			score += deepStats.shares * weights.SHARE;
			postEl.dataset.gmScore = score.toString();
			return score;
		}
		extractTotalReactions(postEl) {
			let maxVal = 0;
			postEl.querySelectorAll("[role=\"button\"], span[dir=\"auto\"], div[dir=\"auto\"], span[aria-hidden=\"true\"] span").forEach((div) => {
				const element = div;
				if (element.childElementCount > 0) return;
				if (element.closest("[data-ad-rendering-role=\"story_message\"]")) return;
				const closestArticle = element.closest("[role=\"article\"]");
				if (closestArticle && closestArticle !== postEl) return;
				const btn = element.closest("[role=\"button\"]");
				if (btn) {
					const icon = btn.querySelector("i[data-visualcompletion=\"css-img\"]");
					if (icon && icon.style.backgroundPosition) {
						const match = icon.style.backgroundPosition.match(/0px\s+(-?\d+)px/);
						if (match) {
							const yPos = parseInt(match[1], 10);
							const SPRITES = this.app.config.CONSTANTS.SPRITES;
							const isCommentY = yPos === this.app.state.activeCommentY || Math.abs(yPos - SPRITES.COMMENT) < SPRITES.TOLERANCE;
							const isShareY = yPos === this.app.state.activeShareY || Math.abs(yPos - SPRITES.SHARE) < SPRITES.TOLERANCE || Math.abs(yPos - SPRITES.SHARE_ALT) < SPRITES.TOLERANCE;
							if (isCommentY || isShareY) return;
						}
					}
				}
				const text = element.textContent;
				if (!text || text.length > 20) return;
				const unitGroup = this.app.config.CONSTANTS.REGEX_PARTS.UNIT_GROUP;
				if (new RegExp(`^[\\d.,${unitGroup.slice(1, -1)}\\s]+$`).test(text)) {
					const val = this.parseMetric(text);
					if (val > maxVal) maxVal = val;
				}
			});
			return maxVal;
		}
		extractIconStats(postEl) {
			let comments = 0;
			let shares = 0;
			const statButtons = Array.from(postEl.querySelectorAll("[role=\"button\"]")).filter((btn) => {
				if (btn.closest("[role=\"toolbar\"]")) return false;
				const text = btn.textContent?.trim();
				if (!text || text.length > 10) return false;
				const unitGroup = this.app.config.CONSTANTS.REGEX_PARTS.UNIT_GROUP;
				if (!new RegExp(`^[\\d.,${unitGroup.slice(1, -1)}\\s]+$`).test(text)) return false;
				return btn.querySelector("i[data-visualcompletion=\"css-img\"], svg") !== null;
			});
			const getYPos = (btn) => {
				const icon = btn.querySelector("i[data-visualcompletion=\"css-img\"]");
				if (!icon || !icon.style.backgroundPosition) return null;
				const match = icon.style.backgroundPosition.match(/0px\s+(-?\d+)px/);
				return match ? parseInt(match[1], 10) : null;
			};
			if (statButtons.length >= 2) {
				const y1 = getYPos(statButtons[0]);
				const y2 = getYPos(statButtons[1]);
				if (y1 !== null && y2 !== null && Math.abs(y1 - y2) === this.app.config.CONSTANTS.SPRITES.RELATIVE_OFFSET) if (y1 > y2) {
					this.app.state.activeCommentY = y1;
					this.app.state.activeShareY = y2;
				} else {
					this.app.state.activeCommentY = y2;
					this.app.state.activeShareY = y1;
				}
				const y1Pos = getYPos(statButtons[0]);
				if (y1Pos !== null && this.app.state.activeCommentY != null) if (y1Pos === this.app.state.activeCommentY) {
					comments = this.parseMetric(statButtons[0].textContent || "");
					shares = this.parseMetric(statButtons[1].textContent || "");
				} else {
					shares = this.parseMetric(statButtons[0].textContent || "");
					comments = this.parseMetric(statButtons[1].textContent || "");
				}
				else {
					comments = this.parseMetric(statButtons[0].textContent || "");
					shares = this.parseMetric(statButtons[1].textContent || "");
				}
			} else if (statButtons.length === 1) {
				const y = getYPos(statButtons[0]);
				if (y !== null && this.app.state.activeCommentY != null && this.app.state.activeShareY != null) if (y === this.app.state.activeCommentY) comments = this.parseMetric(statButtons[0].textContent || "");
				else if (y === this.app.state.activeShareY) shares = this.parseMetric(statButtons[0].textContent || "");
				else comments = this.parseMetric(statButtons[0].textContent || "");
				else comments = this.parseMetric(statButtons[0].textContent || "");
			}
			return {
				comments,
				shares
			};
		}
		formatMetric(num) {
			if (num >= 1e6) return (num / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
			if (num >= 1e3) return (num / 1e3).toFixed(1).replace(/\.0$/, "") + "k";
			return num.toString();
		}
		parseMetric(str) {
			if (!str) return 0;
			const unitGroup = this.app.config.CONSTANTS.REGEX_PARTS.UNIT_GROUP;
			const match = str.match(new RegExp(`(\\d+(?:[.,]\\d+)?)\\s*(${unitGroup}?)`));
			if (!match) return 0;
			let num = parseFloat(match[1].replace(/,/g, ""));
			const unit = match[2].toLowerCase();
			if (unit === "k") num *= 1e3;
			else if (unit === "m") num *= 1e6;
			else if (unit === "萬" || unit === "万") num *= 1e4;
			else if (unit === "億") num *= 1e8;
			return Math.floor(num);
		}
		extractTime(postEl) {
			const PHT = this.app.modules.postHeaderTools;
			if (PHT) {
				const link = PHT.findTimestampLink(postEl);
				if (link) return link.textContent?.trim() || "";
			}
			return "";
		}
		initObserver() {
			const CONF = this.app.config.CONSTANTS.OBSERVER;
			const options = {
				root: null,
				rootMargin: CONF.ROOT_MARGIN,
				threshold: CONF.THRESHOLD
			};
			this.observer = new IntersectionObserver((entries) => {
				if (this.isManualScrolling) return;
				entries.forEach((entry) => {
					if (entry.isIntersecting) {
						const Core = this.app.modules.postNavigatorCore;
						if (!Core) return;
						const idx = Core.getSortedPosts().indexOf(entry.target);
						if (idx !== -1) Core.updateActivePost(idx, "scroll");
					}
				});
			}, options);
		}
		startWatcher() {
			this.watcher = new MutationObserver(this.app.utils.throttle(() => this.refresh(), 500));
			this.watcher.observe(document.body, {
				childList: true,
				subtree: true
			});
		}
	};
	var KeyboardNavigator = class {
		app;
		activeKey = null;
		handleKeyDownBound;
		handleKeyUpBound;
		constructor(app) {
			this.app = app;
			this.handleKeyDownBound = this.handleKeyDown.bind(this);
			this.handleKeyUpBound = this.handleKeyUp.bind(this);
		}
		init() {
			if (!this.app.state.settings.keyboardNavEnabled) return;
			document.addEventListener("keydown", this.handleKeyDownBound);
			document.addEventListener("keyup", this.handleKeyUpBound);
		}
		deinit() {
			document.removeEventListener("keydown", this.handleKeyDownBound);
			document.removeEventListener("keyup", this.handleKeyUpBound);
		}
		handleKeyDown(event) {
			if (event.key === this.activeKey) return;
			if (!this.app.utils.isFeedPage()) return;
			const target = event.target;
			if (!target) return;
			if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable) return;
			const settings = this.app.state.settings;
			let direction = null;
			if (event.key === settings.keyNavNextPrimary || event.key === settings.keyNavNextSecondary) direction = "next";
			else if (event.key === settings.keyNavPrevPrimary || event.key === settings.keyNavPrevSecondary) direction = "prev";
			if (direction) {
				event.preventDefault();
				this.activeKey = event.key;
				const core = this.app.modules.postNavigatorCore;
				if (core) core.startContinuousNavigation(direction);
			}
		}
		handleKeyUp(event) {
			if (event.key === this.activeKey) {
				this.activeKey = null;
				const core = this.app.modules.postNavigatorCore;
				if (core) core.stopContinuousNavigation();
			}
		}
	};
	var ScrollRestorer = class {
		app;
		handleInteractionBound;
		handleKeyDownBound;
		constructor(app) {
			this.app = app;
			this.handleInteractionBound = this.handleInteraction.bind(this);
			this.handleKeyDownBound = (e) => {
				if (e.key === "Escape") this.handleInteraction();
			};
		}
		init() {
			document.body.addEventListener("click", this.handleInteractionBound, true);
			document.addEventListener("keydown", this.handleKeyDownBound, true);
		}
		deinit() {
			document.body.removeEventListener("click", this.handleInteractionBound, true);
			document.removeEventListener("keydown", this.handleKeyDownBound, true);
		}
		triggerRestore() {
			const lastPost = this.app.state.lastActivePost;
			if (lastPost && document.body.contains(lastPost)) this.app.utils.scrollToElement(lastPost, false, this.app.state.settings.scrollRestorerAlignment, this.app);
		}
		handleInteraction() {
			const dialogSelector = this.app.config.SELECTORS.GLOBAL.DIALOG;
			const dialogBefore = document.querySelector(dialogSelector);
			if (dialogBefore && this.app.utils.isVisible(dialogBefore)) setTimeout(() => {
				const dialogAfter = document.querySelector(dialogSelector);
				if (!dialogAfter || !this.app.utils.isVisible(dialogAfter)) this.triggerRestore();
			}, 150);
		}
	};
	var AutoUnmuter = class {
		app;
		observer = null;
		checkInterval = null;
		playListenerBound = null;
		clickListenerBound = null;
		isInitialized = false;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.isInitialized) return;
			this.isInitialized = true;
			const volumeDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, "volume");
			const mutedDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, "muted");
			const nativeVolumeSetter = volumeDescriptor ? volumeDescriptor.set : null;
			const nativeMutedSetter = mutedDescriptor ? mutedDescriptor.set : null;
			const attemptUnmute = (video) => {
				if (!this.app.state.settings.autoUnmuteEnabled) return;
				if (video instanceof HTMLVideoElement && (video.muted || video.volume === 0)) {
					const targetVolume = this.app.state.settings.autoUnmuteVolume / 100;
					if (nativeMutedSetter) nativeMutedSetter.call(video, false);
					else video.muted = false;
					if (nativeVolumeSetter) nativeVolumeSetter.call(video, targetVolume);
					else video.volume = targetVolume;
					const anyVideo = video;
					if (anyVideo.audioTracks && anyVideo.audioTracks.length > 0) for (const track of anyVideo.audioTracks) track.enabled = true;
					video.dispatchEvent(new Event("volumechange", { bubbles: true }));
				}
			};
			if (/\/reel\/|\/watch\/|\/videos\//.test(window.location.pathname)) {
				const applyVolumePreset = () => {
					if (this.app.state.settings.autoUnmuteEnabled) {
						const targetVolume = this.app.state.settings.autoUnmuteVolume / 100;
						const video = document.querySelector("video");
						if (video && Math.abs(video.volume - targetVolume) > .01) if (nativeVolumeSetter) nativeVolumeSetter.call(video, targetVolume);
						else video.volume = targetVolume;
					}
				};
				[
					500,
					1500,
					3e3,
					5e3
				].forEach((delay) => {
					setTimeout(applyVolumePreset, delay);
				});
			} else {
				this.playListenerBound = (e) => attemptUnmute(e.target);
				document.addEventListener("play", this.playListenerBound, true);
				this.observer = new MutationObserver((mutations) => {
					mutations.forEach((mutation) => mutation.addedNodes.forEach((node) => {
						if (node.nodeName === "VIDEO") attemptUnmute(node);
						else if (node instanceof HTMLElement) node.querySelectorAll("video").forEach(attemptUnmute);
					}));
				});
				this.observer.observe(document.body, {
					childList: true,
					subtree: true
				});
				this.checkInterval = setInterval(() => {
					document.querySelectorAll("video").forEach(attemptUnmute);
				}, 2e3);
				this.clickListenerBound = (event) => {
					const target = event.target;
					if (target && target.closest("[aria-label*=\"mute\" i], [aria-label*=\"sound\" i], [role=\"button\"][aria-pressed]")) setTimeout(() => document.querySelectorAll("video").forEach(attemptUnmute), 150);
				};
				document.addEventListener("click", this.clickListenerBound, true);
			}
		}
		deinit() {
			if (!this.isInitialized) return;
			if (this.checkInterval) {
				clearInterval(this.checkInterval);
				this.checkInterval = null;
			}
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			if (this.playListenerBound) {
				document.removeEventListener("play", this.playListenerBound, true);
				this.playListenerBound = null;
			}
			if (this.clickListenerBound) {
				document.removeEventListener("click", this.clickListenerBound, true);
				this.clickListenerBound = null;
			}
			this.isInitialized = false;
		}
		updateVolume(volume) {
			if (!this.isInitialized) return;
			const targetVolume = volume / 100;
			const volumeDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, "volume");
			const nativeVolumeSetter = volumeDescriptor ? volumeDescriptor.set : null;
			document.querySelectorAll("video").forEach((video) => {
				if (!video.muted && video.volume !== 0) {
					if (nativeVolumeSetter) nativeVolumeSetter.call(video, targetVolume);
					else video.volume = targetVolume;
					video.dispatchEvent(new Event("volumechange", { bubbles: true }));
				}
			});
		}
	};
	var PostNumbering = class {
		app;
		observer = null;
		isInitialized = false;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.isInitialized) return;
			if (!this.app.state.settings.postNumberingEnabled) return;
			this.isInitialized = true;
			const processNewPosts = () => {
				if (!this.app.utils.isFeedPage()) return;
				document.querySelectorAll("[role=\"article\"][aria-posinset]:not([data-gm-numbered])").forEach((article) => {
					const articleElement = article;
					if (articleElement.closest(this.app.config.SELECTORS.GLOBAL.DIALOG)) return;
					const postNumber = articleElement.getAttribute("aria-posinset");
					if (!postNumber) return;
					articleElement.style.position = "relative";
					const numberTag = this.app.utils.createStyledElement("span", {}, {
						className: "gm-post-number",
						textContent: postNumber
					});
					articleElement.appendChild(numberTag);
					articleElement.dataset.gmNumbered = "true";
				});
			};
			const throttledProcess = this.app.utils.throttle(processNewPosts, 300);
			this.observer = new MutationObserver(throttledProcess);
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
			processNewPosts();
		}
		deinit() {
			if (!this.isInitialized) return;
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			this.isInitialized = false;
		}
	};
	var getPostCopyContent = (post, app) => {
		const PHT = app.modules.postHeaderTools;
		if (PHT && typeof PHT.formatPostData === "function") {
			const formattedData = {
				meta: {
					id: post.id,
					url: post.url,
					author: [{
						name: post.authorName,
						link: post.authorLink
					}],
					timestamp: post.timestamp
				},
				stats: post.stats || {
					reactions: {
						total: 0,
						detailed: []
					},
					comments: 0,
					shares: 0
				},
				media: post.media || {
					imageCount: 0,
					videoDuration: null,
					linkPreview: null
				},
				content: post.content,
				sharedPost: post.sharedPost
			};
			return PHT.formatPostData(formattedData, "text");
		}
		return post.content || post.excerpt || "";
	};
	var formatLastVisited = (timestamp, T) => {
		if (!timestamp) return T.bookmark_last_visited_never || "Last visited: Never";
		const date = new Date(timestamp);
		const yyyy = date.getFullYear();
		const mm = String(date.getMonth() + 1).padStart(2, "0");
		const dd = String(date.getDate()).padStart(2, "0");
		const hh = String(date.getHours()).padStart(2, "0");
		const min = String(date.getMinutes()).padStart(2, "0");
		return (T.bookmark_last_visited || "Last visited: {time}").replace("{time}", `${yyyy}/${mm}/${dd} ${hh}:${min}`);
	};
	var DeleteConfirmButton = ({ onDelete, title, T, isCompact = false }) => {
		const [confirming, setConfirming] = d$2(false);
		y$2(() => {
			if (!confirming) return;
			const timer = setTimeout(() => setConfirming(false), 3e3);
			return () => clearTimeout(timer);
		}, [confirming]);
		const handleClick = (e) => {
			e.preventDefault();
			e.stopPropagation();
			if (confirming) {
				onDelete();
				setConfirming(false);
			} else setConfirming(true);
		};
		const isZh = T.saveAndClose?.includes("儲存");
		const isJa = T.saveAndClose?.includes("保存");
		const confirmText = isZh ? "確定?" : isJa ? "確定?" : "Confirm?";
		return u("button", {
			className: `gm-delete-confirm-btn ${isCompact ? "gm-card-action-btn" : ""}`,
			onClick: handleClick,
			title: confirming ? T.bookmark_delete_confirm_title || "Click again to confirm delete" : title || T.bookmark_delete_title || "Delete",
			style: {
				background: "transparent",
				border: confirming ? "1px solid #FA383E" : "none",
				backgroundColor: confirming ? "#FFEBEB" : "transparent",
				cursor: "pointer",
				padding: isCompact ? "2px" : "4px 8px",
				display: "inline-flex",
				alignItems: "center",
				justifyContent: "center",
				borderRadius: isCompact ? "4px" : "6px",
				transition: "all 0.2s",
				height: isCompact ? void 0 : "28px",
				gap: isCompact ? void 0 : "4px",
				lineHeight: isCompact ? 1 : void 0
			},
			children: confirming ? u("span", {
				style: {
					fontSize: isCompact ? "9px" : "11px",
					color: "#FA383E",
					fontWeight: "bold",
					display: "inline-flex",
					alignItems: "center",
					gap: "2px"
				},
				children: ["⚠️", !isCompact && ` ${confirmText}`]
			}) : u("svg", {
				viewBox: "0 0 24 24",
				width: isCompact ? "13" : "14",
				height: isCompact ? "13" : "14",
				fill: "#FA383E",
				style: isCompact ? { display: "block" } : void 0,
				children: u("path", { d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" })
			})
		});
	};
	var copyContentIcon = u("svg", {
		viewBox: "0 0 24 24",
		width: "13",
		height: "13",
		fill: "#65676B",
		children: u("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" })
	});
	var copyLinkIcon = u("svg", {
		viewBox: "0 0 24 24",
		width: "13",
		height: "13",
		fill: "#65676B",
		children: u("path", { d: "M17 7h-4v2h4c1.65 0 3 1.35 3 3s-1.35 3-3 3h-4v2h4c2.76 0 5-2.24 5-5s-2.24-5-5-5zm-6 8H7c-1.65 0-3-1.35-3-3s1.35-3 3-3h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-2zm-3-4h8v2H8z" })
	});
	var CopyLinkButton = ({ url, app, T }) => {
		const [copied, setCopied] = d$2(false);
		y$2(() => {
			if (!copied) return;
			const timer = setTimeout(() => setCopied(false), 1500);
			return () => clearTimeout(timer);
		}, [copied]);
		const handleCopy = (e) => {
			e.preventDefault();
			e.stopPropagation();
			navigator.clipboard.writeText(url).then(() => {
				setCopied(true);
				if (app.modules.toastNotifier) app.modules.toastNotifier.show(T.bookmark_copied_notification || "Link copied to clipboard.", "success");
			});
		};
		return u("button", {
			className: "gm-card-action-btn",
			onClick: handleCopy,
			title: T.bookmark_copy_title || "Copy link",
			style: {
				background: "transparent",
				border: "none",
				cursor: "pointer",
				padding: "2px",
				display: "flex",
				alignItems: "center",
				justifyContent: "center",
				transition: "transform 0.15s ease"
			},
			onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.85)",
			onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)",
			children: copied ? u("span", {
				style: {
					fontSize: "11px",
					color: "#45BD62",
					fontWeight: "bold",
					display: "flex",
					alignItems: "center"
				},
				children: "✅"
			}) : copyLinkIcon
		});
	};
	var CopyContentButton = ({ post, app, T }) => {
		const [copied, setCopied] = d$2(false);
		y$2(() => {
			if (!copied) return;
			const timer = setTimeout(() => setCopied(false), 1500);
			return () => clearTimeout(timer);
		}, [copied]);
		const handleCopy = (e) => {
			e.preventDefault();
			e.stopPropagation();
			const textToCopy = getPostCopyContent(post, app);
			navigator.clipboard.writeText(textToCopy).then(() => {
				setCopied(true);
				if (app.modules.toastNotifier) app.modules.toastNotifier.show(T.bookmark_content_copied_notification || "Post content copied to clipboard.", "success");
			});
		};
		return u("button", {
			className: "gm-card-action-btn",
			onClick: handleCopy,
			title: T.bookmark_copy_content_title || "Copy post content",
			style: {
				background: "transparent",
				border: "none",
				cursor: "pointer",
				padding: "2px",
				display: "flex",
				alignItems: "center",
				justifyContent: "center",
				transition: "transform 0.15s ease"
			},
			onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.85)",
			onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)",
			children: copied ? u("span", {
				style: {
					fontSize: "11px",
					color: "#45BD62",
					fontWeight: "bold",
					display: "flex",
					alignItems: "center"
				},
				children: "✅"
			}) : copyContentIcon
		});
	};
	var showCustomConfirm = (app, message, onConfirm) => {
		const T = app.state.T;
		const container = document.createElement("div");
		document.body.appendChild(container);
		const close = () => {
			R(null, container);
			container.remove();
		};
		const handleConfirm = () => {
			onConfirm();
			close();
		};
		const isZh = T.saveAndClose?.includes("儲存") || T.saveAndClose?.includes("保存");
		R(u("div", {
			style: {
				position: "fixed",
				inset: "0",
				backgroundColor: "rgba(0,0,0,0.4)",
				backdropFilter: "blur(4px)",
				webkitBackdropFilter: "blur(4px)",
				zIndex: 999999,
				display: "flex",
				alignItems: "center",
				justifyContent: "center",
				animation: "gm-fade-in 0.2s ease-out"
			},
			onClick: close,
			children: u("div", {
				style: {
					backgroundColor: "#ffffff",
					borderRadius: "12px",
					padding: "20px",
					width: "360px",
					boxShadow: "0 8px 30px rgba(0,0,0,0.2)",
					display: "flex",
					flexDirection: "column",
					gap: "16px"
				},
				onClick: (e) => e.stopPropagation(),
				children: [u("div", {
					style: {
						fontSize: "15px",
						color: "#050505",
						fontWeight: 500,
						lineHeight: 1.4,
						whiteSpace: "pre-line",
						textAlign: "left"
					},
					children: message
				}), u("div", {
					style: {
						display: "flex",
						justifyContent: "flex-end",
						gap: "8px"
					},
					children: [u("button", {
						onClick: close,
						style: {
							padding: "6px 16px",
							border: "1px solid #CED0D4",
							background: "#ffffff",
							color: "#050505",
							borderRadius: "6px",
							cursor: "pointer",
							fontSize: "13px",
							fontWeight: 600,
							transition: "background 0.2s"
						},
						onMouseEnter: (e) => e.currentTarget.style.background = "#F0F2F5",
						onMouseLeave: (e) => e.currentTarget.style.background = "#ffffff",
						children: isZh ? "取消" : "Cancel"
					}), u("button", {
						onClick: handleConfirm,
						style: {
							padding: "6px 16px",
							border: "none",
							background: "#1877F2",
							color: "#ffffff",
							borderRadius: "6px",
							cursor: "pointer",
							fontSize: "13px",
							fontWeight: 600,
							transition: "background 0.2s"
						},
						onMouseEnter: (e) => e.currentTarget.style.background = "#166FE5",
						onMouseLeave: (e) => e.currentTarget.style.background = "#1877F2",
						children: isZh ? "確定" : "Confirm"
					})]
				})]
			})
		}), container);
	};
	var formatPostTooltip = (post, T) => {
		const lines = [];
		lines.push(`👤 ${post.authorName} (${post.timestamp})`);
		const statsParts = [];
		if (post.stats?.reactions?.total) statsParts.push(`👍 ${post.stats.reactions.total}`);
		if (post.stats?.comments) statsParts.push(`💬 ${post.stats.comments}`);
		if (post.stats?.shares) statsParts.push(`↗️ ${post.stats.shares}`);
		if (statsParts.length > 0) lines.push(statsParts.join("  "));
		const mediaParts = [];
		if (post.media?.imageCount > 0) mediaParts.push(`🖼️ ${post.media.imageCount} ${T.image_count_label || "Images"}`);
		if (post.media?.videoDuration) mediaParts.push(`🎥 ${post.media.videoDuration}`);
		if (mediaParts.length > 0) lines.push(mediaParts.join("  "));
		if (post.media?.linkPreview?.title) lines.push(`🔗 ${post.media.linkPreview.title}`);
		lines.push("────────────────────");
		lines.push(post.content || post.excerpt);
		if (post.sharedPost) {
			const shared = post.sharedPost;
			const authorList = shared.meta?.author || shared.author || [];
			const timestamp = shared.meta?.timestamp || shared.date || "";
			const postUrl = shared.meta?.url || shared.url || "";
			lines.push("═══════════════════════════════════");
			lines.push(`🔄 ${T.copier_shared_post_label || "Shared Post"}`);
			let metaLine = authorList.map((a) => {
				if (a.link) return `${a.name} (${a.link})`;
				return a.name;
			}).join(" & ") || "Unknown";
			if (timestamp) metaLine += ` • ${timestamp}`;
			lines.push(metaLine);
			if (postUrl) lines.push(postUrl);
			const sharedStatsParts = [];
			if (shared.stats?.reactions?.total) sharedStatsParts.push(`👍 ${shared.stats.reactions.total}`);
			if (shared.stats?.comments) sharedStatsParts.push(`💬 ${shared.stats.comments}`);
			if (shared.stats?.shares) sharedStatsParts.push(`↗️ ${shared.stats.shares}`);
			if (sharedStatsParts.length > 0) lines.push(sharedStatsParts.join("  "));
			const sharedMediaParts = [];
			if (shared.media?.imageCount > 0) sharedMediaParts.push(`🖼️ ${shared.media.imageCount} ${T.image_count_label || "Images"}`);
			if (shared.media?.videoDuration) sharedMediaParts.push(`🎥 ${shared.media.videoDuration}`);
			if (sharedMediaParts.length > 0) lines.push(sharedMediaParts.join("  "));
			if (shared.media?.linkPreview?.title) lines.push(`🔗 ${shared.media.linkPreview.title}`);
			lines.push("-----------------------------------");
			if (shared.content) lines.push(shared.content);
		}
		return lines.join("\n");
	};
	var BookmarksSidebar = ({ app, isOpen, onClose, position = "left", isPageBookmarked, onBookmarkPage }) => {
		const T = app.state.T;
		const [posts, setPosts] = d$2([]);
		const [pages, setPages] = d$2([]);
		const [folders, setFolders] = d$2([]);
		const [activeTab, setActiveTab] = d$2("posts");
		const [sortPostsBy, setSortPostsBy] = d$2(GM_getValue("bookmark_sort_posts_by", "savedAt"));
		const [sortPagesBy, setSortPagesBy] = d$2(GM_getValue("bookmark_sort_pages_by", "savedAt"));
		const [activeFolderId, setActiveFolderId] = d$2("all");
		const [filterText, setFilterText] = d$2("");
		const [editingTagsId, setEditingTagsId] = d$2(null);
		const [editingFolderId, setEditingFolderId] = d$2(null);
		const [newTagInput, setNewTagInput] = d$2("");
		const [showFolderAddInput, setShowFolderAddInput] = d$2(false);
		const [newFolderName, setNewFolderName] = d$2("");
		const loadBookmarks = () => {
			setPosts(BookmarkStorage.getAll());
			setPages(GM_getValue("bookmarked_pages", []));
			setFolders(GM_getValue("bookmarked_folders", []));
			setSortPostsBy(GM_getValue("bookmark_sort_posts_by", "savedAt"));
			setSortPagesBy(GM_getValue("bookmark_sort_pages_by", "savedAt"));
		};
		y$2(() => {
			loadBookmarks();
			window.addEventListener("gm-bookmarks-updated", loadBookmarks);
			return () => window.removeEventListener("gm-bookmarks-updated", loadBookmarks);
		}, []);
		if (!isOpen) return null;
		const handleManageClick = () => {
			onClose();
			app.modules.settingsModal.open("bookmarks");
		};
		const handleAddFolder = (name) => {
			const trimmed = name.trim();
			if (!trimmed) return;
			const currentFolders = GM_getValue("bookmarked_folders", []);
			if (currentFolders.some((f) => f.name.toLowerCase() === trimmed.toLowerCase())) {
				if (app.modules.toastNotifier) app.modules.toastNotifier.show("Folder name already exists.", "failure");
				return;
			}
			const newFolder = {
				id: "folder_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9),
				name: trimmed,
				createdAt: Date.now()
			};
			const updated = [...currentFolders, newFolder];
			GM_setValue("bookmarked_folders", updated);
			setFolders(updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const addPostTag = (post, tag) => {
			const trimmed = tag.trim();
			if (!trimmed) return;
			const updated = BookmarkStorage.getAll().map((p) => {
				if (p.id === post.id) {
					const tags = p.tags || [];
					if (!tags.includes(trimmed)) return {
						...p,
						tags: [...tags, trimmed]
					};
				}
				return p;
			});
			BookmarkStorage.save(updated);
		};
		const removePostTag = (post, tag) => {
			const updated = BookmarkStorage.getAll().map((p) => {
				if (p.id === post.id) {
					const tags = p.tags || [];
					return {
						...p,
						tags: tags.filter((t) => t !== tag)
					};
				}
				return p;
			});
			BookmarkStorage.save(updated);
		};
		const movePostToFolder = (post, folderId) => {
			const updated = BookmarkStorage.getAll().map((p) => {
				if (p.id === post.id) return {
					...p,
					folderId: folderId || null
				};
				return p;
			});
			BookmarkStorage.save(updated);
		};
		const addPageTag = (page, tag) => {
			const trimmed = tag.trim();
			if (!trimmed) return;
			const updated = GM_getValue("bookmarked_pages", []).map((p) => {
				if (p.url === page.url) {
					const tags = p.tags || [];
					if (!tags.includes(trimmed)) return {
						...p,
						tags: [...tags, trimmed]
					};
				}
				return p;
			});
			GM_setValue("bookmarked_pages", updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const removePageTag = (page, tag) => {
			const updated = GM_getValue("bookmarked_pages", []).map((p) => {
				if (p.url === page.url) {
					const tags = p.tags || [];
					return {
						...p,
						tags: tags.filter((t) => t !== tag)
					};
				}
				return p;
			});
			GM_setValue("bookmarked_pages", updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const movePageToFolder = (page, folderId) => {
			const updated = GM_getValue("bookmarked_pages", []).map((p) => {
				if (p.url === page.url) return {
					...p,
					folderId: folderId || null
				};
				return p;
			});
			GM_setValue("bookmarked_pages", updated);
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		const currentUrl = window.location.origin + window.location.pathname;
		const query = filterText.toLowerCase().trim();
		const getLocale = () => {
			const savedLang = GM_getValue("appLanguage", "auto");
			let lang = savedLang === "auto" ? navigator.language.toLowerCase() : savedLang;
			if (lang.startsWith("ja")) return "ja";
			if (lang.startsWith("zh")) return "zh-Hant";
			return "en";
		};
		const sortPosts = (items) => {
			const locale = getLocale();
			return [...items].sort((a, b) => {
				if (sortPostsBy === "publishTime") {
					const pA = a.timestamp ? Date.parse(a.timestamp) : 0;
					const pB = b.timestamp ? Date.parse(b.timestamp) : 0;
					return (isNaN(pB) ? 0 : pB) - (isNaN(pA) ? 0 : pA);
				}
				if (sortPostsBy === "name") return (a.authorName || "").localeCompare(b.authorName || "", locale, {
					numeric: true,
					sensitivity: "base"
				});
				return (b.savedAt || 0) - (a.savedAt || 0);
			});
		};
		const sortPages = (items) => {
			const locale = getLocale();
			return [...items].sort((a, b) => {
				if (sortPagesBy === "lastVisitedAt") return (b.lastVisitedAt || 0) - (a.lastVisitedAt || 0);
				if (sortPagesBy === "name") return (a.title || "").localeCompare(b.title || "", locale, {
					numeric: true,
					sensitivity: "base"
				});
				return (b.savedAt || 0) - (a.savedAt || 0);
			});
		};
		const filteredPosts = sortPosts(posts.filter((post) => {
			if (activeFolderId === "root") {
				if (post.folderId) return false;
			} else if (activeFolderId !== "all") {
				if (post.folderId !== activeFolderId) return false;
			}
			if (query) {
				const matchText = (post.authorName || "") + " " + (post.excerpt || "") + " " + (post.content || "");
				const matchTags = (post.tags || []).join(" ");
				return matchText.toLowerCase().includes(query) || matchTags.toLowerCase().includes(query);
			}
			return true;
		}));
		const filteredPages = sortPages(pages.filter((page) => {
			if (activeFolderId === "root") {
				if (page.folderId) return false;
			} else if (activeFolderId !== "all") {
				if (page.folderId !== activeFolderId) return false;
			}
			if (query) {
				const matchText = (page.title || "") + " " + (page.desc || "") + " " + (page.url || "");
				const matchTags = (page.tags || []).join(" ");
				return matchText.toLowerCase().includes(query) || matchTags.toLowerCase().includes(query);
			}
			return true;
		}));
		return u("div", {
			className: "gm-bookmarks-sidebar",
			style: {
				position: "fixed",
				top: "0",
				left: position === "left" ? "0" : void 0,
				right: position === "right" ? "0" : void 0,
				width: "320px",
				height: "100vh",
				backgroundColor: "var(--card-background, #fff)",
				borderLeft: position === "right" ? "1px solid var(--media-inner-border, #ddd)" : "none",
				borderRight: position === "left" ? "1px solid var(--media-inner-border, #ddd)" : "none",
				boxShadow: position === "right" ? "-4px 0 16px rgba(0,0,0,0.15)" : "4px 0 16px rgba(0,0,0,0.15)",
				zIndex: 5e4,
				display: "flex",
				flexDirection: "column",
				textAlign: "left",
				boxSizing: "border-box",
				padding: "0"
			},
			children: [
				u("div", {
					style: {
						display: "flex",
						justifyContent: "space-between",
						alignItems: "center",
						padding: "6px 10px",
						borderBottom: "1px solid var(--media-inner-border, #eee)",
						flexShrink: 0
					},
					children: [u("div", {
						style: {
							fontWeight: "bold",
							fontSize: "14px",
							color: "var(--primary-text)"
						},
						children: T.bookmark_menu_title || "My Bookmarks"
					}), u("div", {
						style: {
							display: "flex",
							gap: "8px",
							alignItems: "center"
						},
						children: [
							window.location.pathname !== "/" && u("button", {
								className: `gm-sidebar-star-btn ${isPageBookmarked.value ? "gm-pinned" : ""}`,
								title: isPageBookmarked.value ? T.bookmark_page_action_remove_title || "Remove page bookmark" : T.bookmark_page_action_title || "Bookmark Page",
								onClick: onBookmarkPage,
								style: {
									border: "none",
									background: "transparent",
									cursor: "pointer",
									padding: "2px",
									display: "flex",
									alignItems: "center",
									transition: "transform 0.15s ease"
								},
								onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.85)",
								onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)",
								children: u("span", {
									className: "gm-icon-wrapper",
									children: isPageBookmarked.value ? u("svg", {
										viewBox: "0 0 24 24",
										width: "18",
										height: "18",
										fill: "#F5C33B",
										children: u("path", { d: "M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" })
									}) : u("svg", {
										viewBox: "0 0 24 24",
										width: "18",
										height: "18",
										fill: "#65676B",
										children: u("path", { d: "M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" })
									})
								})
							}),
							u("button", {
								className: "gm-sidebar-manage-btn",
								onClick: handleManageClick,
								title: T.bookmark_manage_btn || "Manage Bookmarks...",
								style: {
									border: "none",
									background: "transparent",
									cursor: "pointer",
									fontSize: "15px",
									padding: "2px",
									display: "flex",
									alignItems: "center"
								},
								children: "⚙️"
							}),
							u("button", {
								className: "gm-sidebar-close-btn",
								onClick: onClose,
								style: {
									border: "none",
									background: "transparent",
									cursor: "pointer",
									fontSize: "18px",
									fontWeight: "bold",
									color: "#888",
									padding: "2px",
									display: "flex",
									alignItems: "center"
								},
								children: "×"
							})
						]
					})]
				}),
				u("div", {
					style: {
						display: "flex",
						borderBottom: "1px solid var(--media-inner-border, #eee)",
						backgroundColor: "#F7F8FA",
						flexShrink: 0
					},
					children: [u("button", {
						className: "gm-sidebar-tab-btn",
						style: {
							flex: 1,
							padding: "4px 0",
							border: "none",
							background: "transparent",
							cursor: "pointer",
							fontSize: "13px",
							fontWeight: activeTab === "posts" ? "bold" : "normal",
							borderBottom: activeTab === "posts" ? "2px solid #1877F2" : "none",
							color: activeTab === "posts" ? "#1877F2" : "#65676B"
						},
						onClick: () => setActiveTab("posts"),
						children: [
							T.bookmark_tab_posts || "Posts",
							" (",
							filteredPosts.length,
							")"
						]
					}), u("button", {
						className: "gm-sidebar-tab-btn",
						style: {
							flex: 1,
							padding: "4px 0",
							border: "none",
							background: "transparent",
							cursor: "pointer",
							fontSize: "13px",
							fontWeight: activeTab === "pages" ? "bold" : "normal",
							borderBottom: activeTab === "pages" ? "2px solid #1877F2" : "none",
							color: activeTab === "pages" ? "#1877F2" : "#65676B"
						},
						onClick: () => setActiveTab("pages"),
						children: [
							T.bookmark_tab_pages || "Pages",
							" (",
							filteredPages.length,
							")"
						]
					})]
				}),
				u("div", {
					style: {
						display: "flex",
						padding: "6px 8px",
						borderBottom: "1px solid var(--media-inner-border, #eee)",
						backgroundColor: "#FAFBFD",
						alignItems: "center",
						gap: "6px",
						flexShrink: 0
					},
					children: showFolderAddInput ? u("div", {
						style: {
							display: "flex",
							gap: "4px",
							alignItems: "center",
							width: "100%"
						},
						children: [u("input", {
							type: "text",
							placeholder: T.bookmark_add_folder || "New folder",
							value: newFolderName,
							onInput: (e) => setNewFolderName(e.target.value),
							onKeyDown: (e) => {
								if (e.key === "Enter") {
									handleAddFolder(newFolderName);
									setNewFolderName("");
									setShowFolderAddInput(false);
								} else if (e.key === "Escape") {
									setShowFolderAddInput(false);
									setNewFolderName("");
								}
							},
							onBlur: () => {
								setTimeout(() => {
									setShowFolderAddInput(false);
									setNewFolderName("");
								}, 200);
							},
							autoFocus: true,
							style: {
								fontSize: "11px",
								padding: "4px 8px",
								borderRadius: "6px",
								border: "1px solid #1877F2",
								outline: "none",
								flex: 1,
								height: "24px",
								boxSizing: "border-box"
							}
						}), u("button", {
							onClick: () => {
								setShowFolderAddInput(false);
								setNewFolderName("");
							},
							style: {
								border: "none",
								background: "transparent",
								cursor: "pointer",
								fontSize: "14px",
								color: "#888",
								padding: "0 4px"
							},
							children: "×"
						})]
					}) : u("div", {
						style: {
							display: "flex",
							gap: "6px",
							alignItems: "center",
							width: "100%"
						},
						children: [
							u("span", {
								style: {
									fontSize: "11px",
									color: "#65676B",
									fontWeight: "bold",
									flexShrink: 0
								},
								children: [
									"📂 ",
									T.bookmark_folder_label || "Folder",
									":"
								]
							}),
							u("select", {
								value: activeFolderId,
								onChange: (e) => {
									setActiveFolderId(e.target.value);
								},
								style: {
									flex: 1,
									padding: "2px 6px",
									borderRadius: "6px",
									border: "1px solid #ccc",
									backgroundColor: "#fff",
									fontSize: "11px",
									outline: "none",
									height: "24px",
									color: "#050505"
								},
								children: [
									u("option", {
										value: "all",
										children: T.bookmark_folder_all || "All"
									}),
									u("option", {
										value: "root",
										children: ["📂 ", T.bookmark_folder_root || "Uncategorized"]
									}),
									folders.map((f) => u("option", {
										value: f.id,
										children: ["📁 ", f.name]
									}, f.id))
								]
							}),
							u("button", {
								onClick: () => setShowFolderAddInput(true),
								title: T.bookmark_add_folder_title || "Add New Folder",
								style: {
									border: "1px solid #ccc",
									borderRadius: "6px",
									background: "#fff",
									cursor: "pointer",
									fontSize: "11px",
									height: "24px",
									width: "24px",
									display: "flex",
									alignItems: "center",
									justifyContent: "center",
									flexShrink: 0,
									color: "#555"
								},
								children: "➕"
							}),
							activeFolderId !== "all" && activeFolderId !== "root" && u("button", {
								onClick: () => {
									const currentFolder = folders.find((f) => f.id === activeFolderId);
									if (!currentFolder) return;
									showCustomConfirm(app, (T.bookmark_delete_folder_confirm || "Are you sure you want to delete this folder? Bookmarks inside will be moved to Uncategorized.").replace("{name}", currentFolder.name), () => {
										const updatedFolders = GM_getValue("bookmarked_folders", []).filter((x) => x.id !== activeFolderId);
										GM_setValue("bookmarked_folders", updatedFolders);
										setFolders(updatedFolders);
										const pList = BookmarkStorage.getAll();
										BookmarkStorage.save(pList.map((p) => p.folderId === activeFolderId ? {
											...p,
											folderId: null
										} : p));
										const pgList = GM_getValue("bookmarked_pages", []);
										GM_setValue("bookmarked_pages", pgList.map((pg) => pg.folderId === activeFolderId ? {
											...pg,
											folderId: null
										} : pg));
										setActiveFolderId("all");
										window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
									});
								},
								title: T.bookmark_delete_folder_title || "Delete Selected Folder",
								style: {
									border: "1px solid var(--negative-background, #fa383e)",
									borderRadius: "6px",
									background: "var(--negative-background, #fa383e)",
									color: "#fff",
									cursor: "pointer",
									fontSize: "11px",
									height: "24px",
									width: "24px",
									display: "flex",
									alignItems: "center",
									justifyContent: "center",
									flexShrink: 0
								},
								children: "🗑️"
							})
						]
					})
				}),
				(() => {
					const getShortSortLabel = (key, defaultText) => {
						const val = T[key];
						if (!val) return defaultText;
						const bracketIdx = val.indexOf("(");
						const fullBracketIdx = val.indexOf("(");
						const idx = bracketIdx !== -1 ? bracketIdx : fullBracketIdx;
						if (idx !== -1) return val.substring(0, idx).trim();
						return val;
					};
					return u("div", {
						style: {
							padding: "4px 6px",
							borderBottom: "1px solid var(--media-inner-border, #eee)",
							backgroundColor: "#fff",
							display: "flex",
							alignItems: "center",
							gap: "4px",
							position: "relative",
							flexShrink: 0
						},
						children: [u("div", {
							style: {
								position: "relative",
								flex: 1,
								display: "flex",
								alignItems: "center"
							},
							children: [
								u("span", {
									style: {
										position: "absolute",
										left: "8px",
										top: "50%",
										transform: "translateY(-50%)",
										fontSize: "12px",
										color: "#888",
										pointerEvents: "none"
									},
									children: "🔍"
								}),
								u("input", {
									type: "text",
									placeholder: T.bookmark_search_placeholder || "Search bookmarks...",
									value: filterText,
									onInput: (e) => setFilterText(e.target.value),
									style: {
										width: "100%",
										padding: "4px 24px 4px 24px",
										fontSize: "11px",
										borderRadius: "14px",
										border: "1px solid #ccc",
										outline: "none",
										backgroundColor: "#F0F2F5",
										transition: "all 0.2s",
										boxSizing: "border-box",
										height: "24px"
									},
									onFocus: (e) => {
										e.currentTarget.style.backgroundColor = "#fff";
										e.currentTarget.style.borderColor = "#1877F2";
										e.currentTarget.style.boxShadow = "0 0 0 2px rgba(24, 119, 242, 0.2)";
									},
									onBlur: (e) => {
										e.currentTarget.style.backgroundColor = "#F0F2F5";
										e.currentTarget.style.borderColor = "#ccc";
										e.currentTarget.style.boxShadow = "none";
									}
								}),
								filterText && u("button", {
									onClick: () => setFilterText(""),
									style: {
										position: "absolute",
										right: "8px",
										top: "50%",
										transform: "translateY(-50%)",
										border: "none",
										background: "transparent",
										cursor: "pointer",
										fontSize: "11px",
										color: "#888",
										padding: "2px",
										display: "flex",
										alignItems: "center",
										justifyContent: "center"
									},
									children: "✖"
								})
							]
						}), u("div", {
							style: {
								display: "flex",
								alignItems: "center",
								flexShrink: 0
							},
							children: activeTab === "posts" ? u("select", {
								value: sortPostsBy,
								onChange: (e) => {
									const val = e.target.value;
									setSortPostsBy(val);
									GM_setValue("bookmark_sort_posts_by", val);
									window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
								},
								style: {
									padding: "2px 4px",
									borderRadius: "6px",
									border: "1px solid #ccc",
									backgroundColor: "#fff",
									fontSize: "11px",
									outline: "none",
									height: "24px",
									maxWidth: "95px",
									color: "#444"
								},
								children: [
									u("option", {
										value: "savedAt",
										children: getShortSortLabel("bookmark_sort_saved_at", "Saved")
									}),
									u("option", {
										value: "publishTime",
										children: getShortSortLabel("bookmark_sort_publish_time", "Published")
									}),
									u("option", {
										value: "name",
										children: getShortSortLabel("bookmark_sort_name", "Name")
									})
								]
							}) : u("select", {
								value: sortPagesBy,
								onChange: (e) => {
									const val = e.target.value;
									setSortPagesBy(val);
									GM_setValue("bookmark_sort_pages_by", val);
									window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
								},
								style: {
									padding: "2px 4px",
									borderRadius: "6px",
									border: "1px solid #ccc",
									backgroundColor: "#fff",
									fontSize: "11px",
									outline: "none",
									height: "24px",
									maxWidth: "95px",
									color: "#444"
								},
								children: [
									u("option", {
										value: "savedAt",
										children: getShortSortLabel("bookmark_sort_saved_at", "Saved")
									}),
									u("option", {
										value: "lastVisitedAt",
										children: getShortSortLabel("bookmark_sort_last_visited", "Visited")
									}),
									u("option", {
										value: "name",
										children: getShortSortLabel("bookmark_sort_name", "Name")
									})
								]
							})
						})]
					});
				})(),
				u("div", {
					style: {
						flex: 1,
						overflowY: "auto",
						padding: "4px",
						display: "flex",
						flexDirection: "column",
						gap: "3px"
					},
					children: activeTab === "posts" ? filteredPosts.length === 0 ? u("div", {
						style: {
							fontSize: "12px",
							color: "#888",
							textAlign: "center",
							padding: "16px 0"
						},
						children: T.bookmark_empty || "No bookmarks yet."
					}) : filteredPosts.map((post) => u("a", {
						href: post.url,
						target: "_blank",
						rel: "noopener",
						title: formatPostTooltip(post, T),
						style: {
							display: "flex",
							flexDirection: "column",
							padding: "4px 6px",
							borderRadius: "4px",
							textDecoration: "none",
							color: "var(--primary-text)",
							border: "1px solid #eee",
							backgroundColor: "#f9f9f9",
							fontSize: "12px",
							lineHeight: "1.2",
							position: "relative",
							transition: "background-color 0.15s ease"
						},
						onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#F0F2F5",
						onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#f9f9f9",
						children: [u("div", {
							className: "gm-bookmark-text-container",
							style: {
								flex: 1,
								minWidth: 0
							},
							children: [
								u("div", {
									style: {
										display: "flex",
										justifyContent: "space-between",
										alignItems: "baseline"
									},
									children: [u("span", {
										style: {
											fontWeight: "bold",
											color: "#1877F2",
											whiteSpace: "nowrap",
											overflow: "hidden",
											textOverflow: "ellipsis",
											maxWidth: "130px"
										},
										children: ["👤 ", post.authorName]
									}), u("span", {
										className: "gm-bookmark-timestamp",
										style: {
											fontSize: "9px",
											color: "#888",
											flexShrink: 0
										},
										children: post.timestamp
									})]
								}),
								u("div", {
									style: {
										color: "#555",
										fontSize: "11px",
										whiteSpace: "nowrap",
										overflow: "hidden",
										textOverflow: "ellipsis",
										marginTop: "1.5px"
									},
									children: post.excerpt
								}),
								post.tags && post.tags.length > 0 && u("div", {
									style: {
										display: "flex",
										flexWrap: "wrap",
										gap: "2px",
										marginTop: "3px"
									},
									children: post.tags.map((tag) => u("span", {
										style: {
											background: "#E4E6EB",
											color: "#050505",
											borderRadius: "8px",
											padding: "0px 5px",
											fontSize: "9px",
											display: "inline-flex",
											alignItems: "center",
											gap: "1px"
										},
										onClick: (e) => {
											e.preventDefault();
											e.stopPropagation();
											setFilterText(tag);
										},
										children: [
											"#",
											tag,
											u("span", {
												style: {
													cursor: "pointer",
													color: "#888",
													fontWeight: "bold",
													fontSize: "9px",
													paddingLeft: "2px"
												},
												onClick: (e) => {
													e.preventDefault();
													e.stopPropagation();
													removePostTag(post, tag);
												},
												children: "×"
											})
										]
									}, tag))
								}),
								editingTagsId === post.id && u("div", {
									onClick: (e) => {
										e.preventDefault();
										e.stopPropagation();
									},
									style: { marginTop: "4px" },
									children: u("input", {
										type: "text",
										placeholder: T.bookmark_add_tag_placeholder || "Type tag and Enter...",
										value: newTagInput,
										onInput: (e) => setNewTagInput(e.target.value),
										onKeyDown: (e) => {
											if (e.key === "Enter") {
												addPostTag(post, newTagInput);
												setNewTagInput("");
												setEditingTagsId(null);
											} else if (e.key === "Escape") setEditingTagsId(null);
										},
										onBlur: () => {
											setTimeout(() => setEditingTagsId(null), 200);
										},
										autoFocus: true,
										style: {
											fontSize: "10px",
											padding: "2px 4px",
											border: "1px solid #1877F2",
											borderRadius: "4px",
											width: "100%",
											boxSizing: "border-box",
											outline: "none"
										}
									})
								}),
								editingFolderId === post.id && u("div", {
									onClick: (e) => {
										e.preventDefault();
										e.stopPropagation();
									},
									style: { marginTop: "4px" },
									children: u("select", {
										value: post.folderId || "",
										onChange: (e) => {
											movePostToFolder(post, e.target.value || null);
											setEditingFolderId(null);
										},
										onBlur: () => setEditingFolderId(null),
										autoFocus: true,
										style: {
											fontSize: "10px",
											padding: "1px",
											border: "1px solid #1877F2",
											borderRadius: "4px",
											width: "100%",
											outline: "none"
										},
										children: [u("option", {
											value: "",
											children: T.bookmark_folder_root || "Uncategorized"
										}), folders.map((f) => u("option", {
											value: f.id,
											children: f.name
										}, f.id))]
									})
								})
							]
						}), u("div", {
							className: "gm-bookmark-action-buttons",
							style: {
								position: "absolute",
								right: "4px",
								top: "50%",
								transform: "translateY(-50%)",
								display: "flex",
								gap: "2px",
								alignItems: "center"
							},
							onClick: (e) => {
								e.preventDefault();
								e.stopPropagation();
							},
							children: [
								u("button", {
									className: "gm-card-action-btn",
									title: T.bookmark_add_tag_btn || "Add Tag",
									onClick: (e) => {
										e.preventDefault();
										e.stopPropagation();
										setNewTagInput("");
										setEditingTagsId(post.id);
									},
									style: {
										background: "transparent",
										border: "none",
										cursor: "pointer",
										padding: "2px",
										fontSize: "11px"
									},
									children: "🏷️"
								}),
								u("button", {
									className: "gm-card-action-btn",
									title: T.bookmark_move_to_folder || "Move to Folder",
									onClick: (e) => {
										e.preventDefault();
										e.stopPropagation();
										setEditingFolderId(post.id);
									},
									style: {
										background: "transparent",
										border: "none",
										cursor: "pointer",
										padding: "2px",
										fontSize: "11px"
									},
									children: "📂"
								}),
								u(CopyLinkButton, {
									url: post.url,
									app,
									T
								}),
								u(CopyContentButton, {
									post,
									app,
									T
								}),
								u(DeleteConfirmButton, {
									onDelete: () => {
										const updated = BookmarkStorage.getAll().filter((p) => p.id !== post.id);
										BookmarkStorage.save(updated);
										const PHT = app.modules.postHeaderTools;
										if (PHT) PHT.reEvaluateAllButtons();
									},
									title: T.bookmark_post_removed || "Remove bookmark",
									T,
									isCompact: true
								})
							]
						})]
					}, post.id)) : filteredPages.length === 0 ? u("div", {
						style: {
							fontSize: "12px",
							color: "#888",
							textAlign: "center",
							padding: "16px 0"
						},
						children: T.bookmark_empty || "No bookmarks yet."
					}) : filteredPages.map((page) => {
						const isCurrent = page.url === currentUrl;
						return u("a", {
							href: page.url,
							target: "_blank",
							rel: "noopener",
							title: `${page.title}${page.desc ? "\n" + page.desc : ""}`,
							style: {
								display: "flex",
								flexDirection: "column",
								padding: "4px 6px",
								borderRadius: "4px",
								textDecoration: "none",
								color: "var(--primary-text)",
								border: `1px solid ${isCurrent ? "#F5C33B" : "#eee"}`,
								backgroundColor: isCurrent ? "#FFFDF0" : "#f9f9f9",
								fontSize: "12px",
								lineHeight: "1.2",
								position: "relative",
								transition: "background-color 0.15s ease"
							},
							onMouseEnter: (e) => e.currentTarget.style.backgroundColor = isCurrent ? "#FFFBE0" : "#F0F2F5",
							onMouseLeave: (e) => e.currentTarget.style.backgroundColor = isCurrent ? "#FFFDF0" : "#f9f9f9",
							children: [u("div", {
								className: "gm-bookmark-text-container",
								style: {
									flex: 1,
									minWidth: 0
								},
								children: [
									u("div", {
										style: {
											fontWeight: "bold",
											color: "#1877F2",
											whiteSpace: "nowrap",
											overflow: "hidden",
											textOverflow: "ellipsis"
										},
										children: ["📁 ", page.title]
									}),
									page.desc && u("div", {
										style: {
											color: "#65676B",
											fontSize: "11px",
											marginTop: "1.5px",
											display: "-webkit-box",
											webkitLineClamp: 1,
											webkitBoxOrient: "vertical",
											overflow: "hidden",
											lineHeight: "1.2"
										},
										children: page.desc
									}),
									u("div", {
										style: {
											color: "#888",
											fontSize: "9px",
											marginTop: "1.5px"
										},
										children: ["🕒 ", formatLastVisited(page.lastVisitedAt || page.savedAt, T)]
									}),
									page.tags && page.tags.length > 0 && u("div", {
										style: {
											display: "flex",
											flexWrap: "wrap",
											gap: "2px",
											marginTop: "3px"
										},
										children: page.tags.map((tag) => u("span", {
											style: {
												background: "#E4E6EB",
												color: "#050505",
												borderRadius: "8px",
												padding: "0px 5px",
												fontSize: "9px",
												display: "inline-flex",
												alignItems: "center",
												gap: "1px"
											},
											onClick: (e) => {
												e.preventDefault();
												e.stopPropagation();
												setFilterText(tag);
											},
											children: [
												"#",
												tag,
												u("span", {
													style: {
														cursor: "pointer",
														color: "#888",
														fontWeight: "bold",
														fontSize: "9px",
														paddingLeft: "2px"
													},
													onClick: (e) => {
														e.preventDefault();
														e.stopPropagation();
														removePageTag(page, tag);
													},
													children: "×"
												})
											]
										}, tag))
									}),
									editingTagsId === page.url && u("div", {
										onClick: (e) => {
											e.preventDefault();
											e.stopPropagation();
										},
										style: { marginTop: "4px" },
										children: u("input", {
											type: "text",
											placeholder: T.bookmark_add_tag_placeholder || "Type tag and Enter...",
											value: newTagInput,
											onInput: (e) => setNewTagInput(e.target.value),
											onKeyDown: (e) => {
												if (e.key === "Enter") {
													addPageTag(page, newTagInput);
													setNewTagInput("");
													setEditingTagsId(null);
												} else if (e.key === "Escape") setEditingTagsId(null);
											},
											onBlur: () => {
												setTimeout(() => setEditingTagsId(null), 200);
											},
											autoFocus: true,
											style: {
												fontSize: "10px",
												padding: "2px 4px",
												border: "1px solid #1877F2",
												borderRadius: "4px",
												width: "100%",
												boxSizing: "border-box",
												outline: "none"
											}
										})
									}),
									editingFolderId === page.url && u("div", {
										onClick: (e) => {
											e.preventDefault();
											e.stopPropagation();
										},
										style: { marginTop: "4px" },
										children: u("select", {
											value: page.folderId || "",
											onChange: (e) => {
												movePageToFolder(page, e.target.value || null);
												setEditingFolderId(null);
											},
											onBlur: () => setEditingFolderId(null),
											autoFocus: true,
											style: {
												fontSize: "10px",
												padding: "1px",
												border: "1px solid #1877F2",
												borderRadius: "4px",
												width: "100%",
												outline: "none"
											},
											children: [u("option", {
												value: "",
												children: T.bookmark_folder_root || "Uncategorized"
											}), folders.map((f) => u("option", {
												value: f.id,
												children: f.name
											}, f.id))]
										})
									})
								]
							}), u("div", {
								className: "gm-bookmark-action-buttons",
								style: {
									position: "absolute",
									right: "4px",
									top: "50%",
									transform: "translateY(-50%)",
									display: "flex",
									gap: "2px",
									alignItems: "center"
								},
								onClick: (e) => {
									e.preventDefault();
									e.stopPropagation();
								},
								children: [
									u("button", {
										className: "gm-card-action-btn",
										title: T.bookmark_add_tag_btn || "Add Tag",
										onClick: (e) => {
											e.preventDefault();
											e.stopPropagation();
											setNewTagInput("");
											setEditingTagsId(page.url);
										},
										style: {
											background: "transparent",
											border: "none",
											cursor: "pointer",
											padding: "2px",
											fontSize: "11px"
										},
										children: "🏷️"
									}),
									u("button", {
										className: "gm-card-action-btn",
										title: T.bookmark_move_to_folder || "Move to Folder",
										onClick: (e) => {
											e.preventDefault();
											e.stopPropagation();
											setEditingFolderId(page.url);
										},
										style: {
											background: "transparent",
											border: "none",
											cursor: "pointer",
											padding: "2px",
											fontSize: "11px"
										},
										children: "📂"
									}),
									u(CopyLinkButton, {
										url: page.url,
										app,
										T
									}),
									u(DeleteConfirmButton, {
										onDelete: () => {
											const updated = GM_getValue("bookmarked_pages", []).filter((p) => p.url !== page.url);
											GM_setValue("bookmarked_pages", updated);
											window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
											const FN = app.modules.floatingNavigator;
											if (FN) FN.updateVisibility();
										},
										title: T.bookmark_page_action_remove_title || "Remove page bookmark",
										T,
										isCompact: true
									})
								]
							})]
						}, page.url);
					})
				})
			]
		});
	};
	var SearchBarComponent = ({ app, searchInstance, signals }) => {
		const T = app.state.T;
		const toolbarRef = A(null);
		const [bookmarkPos, setBookmarkPos] = d$2(app.state.settings.bookmarkPosition || "left");
		y$2(() => {
			const handler = (e) => {
				setBookmarkPos(e.detail);
			};
			window.addEventListener("gm-bookmark-position-changed", handler);
			return () => window.removeEventListener("gm-bookmark-position-changed", handler);
		}, []);
		A(null);
		const [isBookmarkMenuOpen, setIsBookmarkMenuOpen] = d$2(false);
		const { isPinned, keyword, selectedScope, isAtTop, isHovered, isFocused, isBarVisible, suppressShow, isPageBookmarked } = signals;
		const handleBookmarkPageClick = () => {
			const T = app.state.T;
			const currentUrl = window.location.origin + window.location.pathname;
			const bookmarks = GM_getValue("bookmarked_pages", []);
			const index = bookmarks.findIndex((b) => b.url === currentUrl);
			if (index === -1) {
				const pageTitle = document.title.replace(/ \| Facebook$/, "").replace(/^\(\d+\) /, "") || "Facebook Page";
				const getMetaContent = (selectors) => {
					for (const selector of selectors) {
						const el = document.querySelector(selector);
						if (el) {
							const content = el.getAttribute("content");
							if (content) return content.trim();
						}
					}
					return "";
				};
				const pageBookmark = {
					url: currentUrl,
					title: pageTitle,
					desc: getMetaContent([
						"meta[property=\"og:description\"]",
						"meta[name=\"description\"]",
						"meta[name=\"twitter:description\"]"
					]),
					savedAt: Date.now(),
					lastVisitedAt: Date.now()
				};
				bookmarks.push(pageBookmark);
				GM_setValue("bookmarked_pages", bookmarks);
				isPageBookmarked.value = true;
				app.modules.toastNotifier.show(T.bookmark_page_added || "Page added to bookmarks.", "success");
			} else {
				bookmarks.splice(index, 1);
				GM_setValue("bookmarked_pages", bookmarks);
				isPageBookmarked.value = false;
				app.modules.toastNotifier.show(T.bookmark_page_removed || "Page removed from bookmarks.", "success");
			}
			window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
		};
		y$2(() => {
			if (toolbarRef.current) searchInstance.toolbar = toolbarRef.current;
		});
		const handleScopeChange = (e) => {
			selectedScope.value = e.target.value;
		};
		const handleInputChange = (e) => {
			keyword.value = e.target.value;
		};
		const handleClearClick = () => {
			keyword.value = "";
			const input = toolbarRef.current?.querySelector(".gm-search-input-container > input");
			if (input) input.focus();
		};
		const handleSearchClick = (e) => {
			if (isSearchDisabled.value) return;
			e.preventDefault();
			performSearch(e.button === 1 ? "background" : "_blank");
		};
		const handleKeyDown = (e) => {
			if (e.key === "Enter" && !isSearchDisabled.value) performSearch("_blank");
		};
		const isSearchDisabled = g$1(() => {
			return !(selectedScope.value === "" || [
				"/photos/",
				"/videos/",
				"reel_search"
			].includes(selectedScope.value)) && !keyword.value.trim();
		});
		const performSearch = (target) => {
			const kw = keyword.value.trim();
			const scopeVal = selectedScope.value;
			if (!(scopeVal === "" || [
				"/photos/",
				"/videos/",
				"reel_search"
			].includes(scopeVal)) && !kw) return;
			const langExclusion = app.state.settings.excludeTranslation ? " -inurl:?locale= -inurl:?locale2=" : "";
			const openUrl = (url) => {
				if (target === "background") if (typeof GM_openInTab !== "undefined") GM_openInTab(url, {
					active: false,
					insert: true
				});
				else window.open(url, "_blank");
				else window.open(url, target);
			};
			const internalSearchMap = {
				"events_search": `https://www.facebook.com/events/search/?q=${encodeURIComponent(kw)}`,
				"marketplace_search": `https://www.facebook.com/marketplace/search/?query=${encodeURIComponent(kw)}`,
				"watch_search": `https://www.facebook.com/watch/search/?q=${encodeURIComponent(kw)}`
			};
			if (internalSearchMap[scopeVal]) {
				openUrl(internalSearchMap[scopeVal]);
				return;
			}
			if (scopeVal === "reel_search") {
				const pageName = searchInstance.getCurrentPageName();
				if (!pageName) {
					if (app.modules.toastNotifier) app.modules.toastNotifier.show(T.notificationReelSearchError, "failure");
					return;
				}
				const combinedKeywords = kw ? `${kw} "${pageName}"` : `"${pageName}"`;
				openUrl(`https://www.google.com/search?q=${encodeURIComponent(combinedKeywords + " site:www.facebook.com/reel/" + langExclusion)}`);
			} else if (scopeVal.startsWith("site:")) openUrl(`https://www.google.com/search?q=${encodeURIComponent(kw)}+${encodeURIComponent(scopeVal)}`);
			else {
				let basePath = "";
				const pathSegments = window.location.pathname.split("/").filter(Boolean);
				if (pathSegments.length > 0 && pathSegments[0] !== "groups") basePath = pathSegments[0] === "people" && pathSegments[2] && !isNaN(parseInt(pathSegments[2], 10)) ? `/${pathSegments[2]}` : `/${pathSegments[0]}`;
				else if (pathSegments.length > 1 && pathSegments[0] === "groups") basePath = `/${pathSegments[0]}/${pathSegments[1]}`;
				const fullSiteTarget = `site:www.facebook.com${basePath}${scopeVal}` + langExclusion;
				let searchUrl = `https://www.google.com/search?q=${kw ? `${encodeURIComponent(kw)}+${encodeURIComponent(fullSiteTarget)}` : encodeURIComponent(fullSiteTarget)}`;
				if (scopeVal === "/photos/") searchUrl += "&udm=2";
				openUrl(searchUrl);
			}
		};
		const handleShortcutClick = (e, url) => {
			if (e.button === 0) {
				e.preventDefault();
				window.location.href = `https://www.facebook.com${url}`;
			} else if (e.button === 1) {
				e.preventDefault();
				window.open(`https://www.facebook.com${url}`, "_blank");
			}
		};
		const togglePin = () => {
			isPinned.value = !isPinned.value;
			GM_setValue("isSearchBarPinned", isPinned.value);
		};
		const isGroupPage = window.location.pathname.startsWith("/groups/");
		const icons = searchInstance.icons;
		const isHidden = !isBarVisible.value;
		const transformStyle = !isPinned.value && !isAtTop.value && !isHovered.value && !isFocused.value || isHidden ? "translateY(-100%)" : "translateY(0)";
		const visibilityStyle = isHidden ? "hidden" : "visible";
		const isHintVisible = !isPinned.value && !isAtTop.value && !isHidden;
		const bookmarkMenuButton = app.state.settings.enableBookmarks && u("button", {
			className: isBookmarkMenuOpen ? "gm-pinned" : "",
			title: T.bookmark_menu_title || "My Bookmarks",
			onClick: () => setIsBookmarkMenuOpen(!isBookmarkMenuOpen),
			children: u("span", {
				className: "gm-icon-wrapper",
				dangerouslySetInnerHTML: { __html: isBookmarkMenuOpen ? icons.bookmarkFilled : icons.bookmark }
			})
		});
		return u(S$1, { children: [
			u("div", {
				ref: toolbarRef,
				className: "gm-toolbar",
				style: {
					transform: transformStyle,
					visibility: visibilityStyle
				},
				onMouseEnter: () => {
					isHovered.value = true;
				},
				onMouseLeave: () => {
					isHovered.value = false;
				},
				children: [
					u("div", {
						className: "gm-button-group",
						children: [
							bookmarkPos === "left" && bookmarkMenuButton,
							u("button", {
								title: T.shortcutWatch,
								onMouseDown: (e) => handleShortcutClick(e, "/watch/"),
								children: u("span", {
									className: "gm-icon-wrapper",
									dangerouslySetInnerHTML: { __html: icons.watch }
								})
							}),
							u("button", {
								title: T.shortcutEvents,
								onMouseDown: (e) => handleShortcutClick(e, "/events/"),
								children: u("span", {
									className: "gm-icon-wrapper",
									dangerouslySetInnerHTML: { __html: icons.events }
								})
							}),
							u("button", {
								title: T.shortcutMarketplace,
								onMouseDown: (e) => handleShortcutClick(e, "/marketplace/"),
								children: u("span", {
									className: "gm-icon-wrapper",
									dangerouslySetInnerHTML: { __html: icons.marketplace }
								})
							})
						]
					}),
					u("div", {
						className: "gm-search-core-wrapper",
						children: u("div", {
							className: `gm-search-component-wrapper ${isFocused.value ? "gm-focused" : ""}`,
							children: [u("select", {
								style: { cursor: "pointer" },
								value: selectedScope.value,
								onChange: handleScopeChange,
								children: [u("optgroup", {
									label: T.searchGroupContextual,
									children: [
										u("option", {
											value: "",
											title: T.searchTooltipPosts,
											children: T.searchScopePosts
										}),
										u("option", {
											value: "/photos/",
											disabled: isGroupPage,
											title: T.searchTooltipPhotos,
											children: T.searchScopePhotos
										}),
										u("option", {
											value: "/videos/",
											disabled: isGroupPage,
											title: T.searchTooltipVideos,
											children: T.searchScopeVideos
										}),
										u("option", {
											value: "reel_search",
											disabled: isGroupPage,
											title: T.searchTooltipReels,
											children: T.searchScopeReels
										})
									]
								}), u("optgroup", {
									label: T.searchGroupGlobal,
									children: [
										u("option", {
											value: "site:www.facebook.com -inurl:/people/ -inurl:/groups/ -inurl:/events/ -inurl:/marketplace/ -inurl:/gaming/ -inurl:/posts/ -inurl:/videos/ -inurl:/watch/ -inurl:/reels/ -inurl:/reel/ -inurl:/photos/ -inurl:/photo/ -inurl:/albums/ -inurl:/media/ -inurl:/about/ -inurl:/mentions/ -inurl:/permalink/ -inurl:/story.php -inurl:/photo.php -inurl:/permalink.php -inurl:/hashtag/ -inurl:comment_id=",
											title: T.searchTooltipPages,
											children: T.searchScopePages
										}),
										u("option", {
											value: "site:www.facebook.com/people/",
											title: T.searchTooltipPeople,
											children: T.searchScopePeople
										}),
										u("option", {
											value: "site:www.facebook.com/groups/ -inurl:/posts/ -inurl:/permalink/",
											title: T.searchTooltipGroups,
											children: T.searchScopeGroups
										}),
										u("option", {
											value: "site:www.facebook.com inurl:/posts/",
											title: T.searchTooltipGlobalPosts,
											children: T.searchScopeGlobalPosts
										}),
										u("option", {
											value: "watch_search",
											title: T.searchTooltipGlobalVideos,
											children: T.searchScopeGlobalVideos
										}),
										u("option", {
											value: "events_search",
											title: T.searchTooltipEvents,
											children: T.searchScopeEvents
										}),
										u("option", {
											value: "marketplace_search",
											title: T.searchTooltipMarketplace,
											children: T.searchScopeMarketplace
										})
									]
								})]
							}), u("div", {
								className: "gm-search-input-container",
								children: [
									u("input", {
										type: "text",
										placeholder: T.searchPlaceholder,
										value: keyword.value,
										onInput: handleInputChange,
										onKeyDown: handleKeyDown,
										onFocus: () => {
											isFocused.value = true;
										},
										onBlur: () => {
											isFocused.value = false;
										}
									}),
									u("button", {
										className: "gm-search-clear-button",
										style: { display: keyword.value ? "flex" : "none" },
										onMouseDown: (e) => e.preventDefault(),
										onClick: handleClearClick,
										children: "✖"
									}),
									u("button", {
										className: "gm-search-button-integrated",
										style: {
											opacity: isSearchDisabled.value ? .5 : 1,
											cursor: isSearchDisabled.value ? "not-allowed" : "pointer"
										},
										disabled: isSearchDisabled.value,
										title: !keyword.value && (selectedScope.value === "" || [
											"/photos/",
											"/videos/",
											"reel_search"
										].includes(selectedScope.value)) ? T.searchAllContextualTooltip.replace("{scope}", T.searchScopePosts) : T.searchButton,
										onMouseDown: handleSearchClick,
										children: u("span", {
											className: "gm-icon-wrapper",
											dangerouslySetInnerHTML: { __html: icons.search }
										})
									})
								]
							})]
						})
					}),
					u("div", {
						className: "gm-button-group",
						children: [
							u("button", {
								className: isPinned.value ? "gm-pinned" : "",
								title: isPinned.value ? T.unpinToolbar : T.pinToolbar,
								onClick: togglePin,
								children: u("span", {
									className: "gm-icon-wrapper",
									dangerouslySetInnerHTML: { __html: isPinned.value ? icons.pinned : icons.unpinned }
								})
							}),
							bookmarkPos === "right" && bookmarkMenuButton,
							u("button", {
								title: T.menuSettings,
								onClick: () => app.modules.settingsModal.open(),
								children: u("span", {
									className: "gm-icon-wrapper",
									dangerouslySetInnerHTML: { __html: icons.settings }
								})
							})
						]
					})
				]
			}),
			u("div", {
				className: "gm-hover-trigger",
				style: { visibility: visibilityStyle },
				onMouseEnter: () => {
					isHovered.value = true;
				},
				onMouseLeave: () => {
					isHovered.value = false;
				}
			}),
			u("div", {
				className: `gm-hover-hint ${isHintVisible ? "gm-visible" : ""}`,
				style: { visibility: visibilityStyle }
			}),
			app.state.settings.enableBookmarks && u(BookmarksSidebar, {
				app,
				isOpen: isBookmarkMenuOpen,
				onClose: () => setIsBookmarkMenuOpen(false),
				position: bookmarkPos,
				isPageBookmarked,
				onBookmarkPage: handleBookmarkPageClick
			})
		] });
	};
	var SearchBar = class {
		app;
		toolbar = null;
		rootEl = null;
		observer = null;
		scrollListener = null;
		historyListener = null;
		bookmarksUpdatedListener = null;
		showTimer = null;
		signals = {
			isPinned: y$1(true),
			keyword: y$1(""),
			selectedScope: y$1(""),
			isAtTop: y$1(true),
			isHovered: y$1(false),
			isFocused: y$1(false),
			isBarVisible: y$1(true),
			wasDialogVisible: y$1(false),
			suppressShow: y$1(false),
			isPageBookmarked: y$1(false)
		};
		icons = {
			pinned: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#1877F2" d="M16 11V5h1.5a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5v2a.5.5 0 0 0 .5.5H8v6l-2 3v2h5v6l1 1 1-1v-6h5v-2l-2-3z"></path></svg>`,
			unpinned: `<svg viewBox="0 0 24 24" width="20" height="20"><g transform="rotate(180 12 12)"><path d="M16 11V5h1.5a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5v2a.5.5 0 0 0 .5.5H8v6l-2 3v2h5v6l1 1 1-1v-6h5v-2l-2-3z" style="fill:none; stroke:#65676B; stroke-width:1.5px;"></path></g></svg>`,
			watch: `<svg viewBox="0 0 24 24" width="20" height="20" style="fill:none; stroke:#65676B; stroke-width:1.8px; stroke-linecap:round; stroke-linejoin:round;"><rect x="2.5" y="5.5" width="19" height="13" rx="3" ry="3"></rect><path d="M10 9l5 3-5 3V9z"></path></svg>`,
			events: `<svg viewBox="0 0 24 24" width="20" height="20"><path d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V10h14v10zm0-12H5V6h14v2zm-7 5h5v5h-5v-5z"></path></svg>`,
			marketplace: `<svg viewBox="2 2 28 28" width="20" height="20"><path fill="#65676B" d="M28.908,12.571a.952.952,0,0,0-.1-.166,3.146,3.146,0,0,0-.118-.423c-.006-.016-.012-.032-.02-.048L25.917,5.6A1,1,0,0,0,25,5H7a1,1,0,0,0-.917.6l-2.77,6.381a2.841,2.841,0,0,0,0,2.083A4.75,4.75,0,0,0,6,16.609V27a1,1,0,0,0,1,1H25a1,1,0,0,0,1-1V16.609a4.749,4.749,0,0,0,2.687-2.543,2.614,2.614,0,0,0,.163-.655A1.057,1.057,0,0,0,28.908,12.571ZM13,26V20h2v6Zm4,0V20h2v6Zm7,0H21V19a1,1,0,0,0-1-1H12a1,1,0,0,0-1,1v7H8V17a5.2,5.2,0,0,0,4-1.8,5.339,5.339,0,0,0,8,0A5.2,5.2,0,0,0,24,17Zm2.837-12.7A3.015,3.015,0,0,1,24,15a2.788,2.788,0,0,1-3-2.5,1,1,0,0,0-2,0A2.788,2.788,0,0,1,16,15a2.788,2.788,0,0,1-3-2.5,1,1,0,0,0-2,0A2.788,2.788,0,0,1,8,15a3.016,3.016,0,0,1-2.838-1.7.836.836,0,0,1,0-.571L7.656,7H24.344l2.477,5.7A.858.858,0,0,1,26.837,13.3Z"/></svg>`,
			search: `<svg viewBox="0 0 24 24" width="18" height="18"><path d="M20.71 19.29l-3.4-3.39A7.92 7.92 0 0 0 19 11a8 8 0 1 0-8 8 7.92 7.92 0 0 0 4.9-1.69l3.39 3.4a1.002 1.002 0 0 0 1.42 0 1 1 0 0 0 0-1.42zM5 11a6 6 0 1 1 6 6 6 6 0 0 1-6-6z"></path></svg>`,
			settings: `<svg viewBox="0 0 24 24" width="20" height="20"><g transform="scale(0.85) translate(2.1, 2.1)"><path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.488.488 0 0 0-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84a.484.484 0 0 0-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.488.488 0 0 0-.59.22L2.74 8.87c-.12.19-.06.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path></g></svg>`,
			bookmark: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#65676B" d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>`,
			bookmarkFilled: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#F5C33B" d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>`
		};
		constructor(app) {
			this.app = app;
		}
		getOccupiedHeight() {
			if (this.signals.isPinned.value && this.toolbar && this.toolbar.style.visibility !== "hidden") return this.toolbar.offsetHeight;
			return 0;
		}
		getCurrentPageName() {
			const h1 = document.querySelector("h1");
			if (!h1) return null;
			let pageName = "";
			for (let i = 0; i < h1.childNodes.length; i++) {
				const node = h1.childNodes[i];
				if (node.nodeType === Node.TEXT_NODE) pageName += node.nodeValue || "";
			}
			return pageName.trim();
		}
		init() {
			if (!this.app.state.settings.hideUselessElements) return;
			this.signals.isPinned.value = GM_getValue("isSearchBarPinned", true);
			const currentUrl = window.location.origin + window.location.pathname;
			const bookmarks = GM_getValue("bookmarked_pages", []);
			const idx = bookmarks.findIndex((b) => b.url === currentUrl);
			const isBookmarked = idx !== -1;
			this.signals.isPageBookmarked.value = isBookmarked;
			if (isBookmarked) {
				bookmarks[idx].lastVisitedAt = Date.now();
				GM_setValue("bookmarked_pages", bookmarks);
				setTimeout(() => {
					window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
				}, 100);
			}
			this.rootEl = document.createElement("div");
			this.rootEl.id = "gm-searchbar-root";
			document.body.appendChild(this.rootEl);
			R(u(SearchBarComponent, {
				app: this.app,
				searchInstance: this,
				signals: this.signals
			}), this.rootEl);
			this.bindEvents();
			setTimeout(() => {
				this.updateVisibility();
			}, this.app.config.TIMEOUTS.INITIAL_DELAY);
		}
		deinit() {
			if (this.rootEl) {
				R(null, this.rootEl);
				this.rootEl.remove();
				this.rootEl = null;
			}
			this.toolbar = null;
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			if (this.scrollListener) {
				window.removeEventListener("scroll", this.scrollListener);
				this.scrollListener = null;
			}
			if (this.historyListener) {
				window.removeEventListener("historyChange", this.historyListener);
				this.historyListener = null;
			}
			if (this.bookmarksUpdatedListener) {
				window.removeEventListener("gm-bookmarks-updated", this.bookmarksUpdatedListener);
				this.bookmarksUpdatedListener = null;
			}
			if (this.showTimer) {
				clearTimeout(this.showTimer);
				this.showTimer = null;
			}
		}
		bindEvents() {
			this.scrollListener = this.app.utils.throttle(() => this.handleScroll(), this.app.config.TIMEOUTS.THROTTLE_SCROLL);
			window.addEventListener("scroll", this.scrollListener, { passive: true });
			this.historyListener = () => this.updateVisibility();
			window.addEventListener("historyChange", this.historyListener);
			const handleBookmarksUpdated = () => {
				const currentUrl = window.location.origin + window.location.pathname;
				const bookmarks = GM_getValue("bookmarked_pages", []);
				this.signals.isPageBookmarked.value = bookmarks.some((b) => b.url === currentUrl);
			};
			this.bookmarksUpdatedListener = handleBookmarksUpdated;
			window.addEventListener("gm-bookmarks-updated", this.bookmarksUpdatedListener);
			this.observer = new MutationObserver(this.app.utils.throttle(() => this.updateVisibility(), this.app.config.TIMEOUTS.THROTTLE_UI));
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
		}
		handleScroll() {
			if (this.signals.isPinned.value) {
				this.signals.isAtTop.value = true;
				return;
			}
			if (this.signals.suppressShow.value) {
				if (this.showTimer) {
					clearTimeout(this.showTimer);
					this.showTimer = null;
				}
				return;
			}
			const isAtTopNow = window.scrollY < 10;
			if (!this.signals.isAtTop.value && isAtTopNow) {
				this.signals.isAtTop.value = true;
				if (this.showTimer) clearTimeout(this.showTimer);
				this.showTimer = setTimeout(() => {
					if (!this.signals.suppressShow.value) {}
					this.showTimer = null;
				}, 200);
			} else if (this.signals.isAtTop.value && !isAtTopNow) {
				this.signals.isAtTop.value = false;
				if (this.showTimer) {
					clearTimeout(this.showTimer);
					this.showTimer = null;
				}
			}
		}
		updateVisibility() {
			const C = this.app.config;
			const currentPath = window.location.pathname;
			const dialogExists = !!document.querySelector(C.SELECTORS.GLOBAL.DIALOG);
			if (this.signals.wasDialogVisible.value && !dialogExists) {
				if (!this.signals.isPinned.value) {
					this.signals.suppressShow.value = true;
					if (this.showTimer) {
						clearTimeout(this.showTimer);
						this.showTimer = null;
					}
					setTimeout(() => {
						this.signals.suppressShow.value = false;
						this.updateVisibility();
					}, 400);
				}
			}
			this.signals.wasDialogVisible.value = dialogExists;
			let isDisallowed = [
				"/photo/",
				"/videos/",
				"/reel/",
				"/posts/",
				"/watch/"
			].some((p) => currentPath.startsWith(p)) || dialogExists;
			if (this.signals.suppressShow.value) isDisallowed = true;
			this.signals.isBarVisible.value = !isDisallowed;
			if (!isDisallowed) {
				const currentUrl = window.location.origin + window.location.pathname;
				const bookmarks = GM_getValue("bookmarked_pages", []);
				const idx = bookmarks.findIndex((b) => b.url === currentUrl);
				const isBookmarked = idx !== -1;
				this.signals.isPageBookmarked.value = isBookmarked;
				if (isBookmarked) {
					bookmarks[idx].lastVisitedAt = Date.now();
					GM_setValue("bookmarked_pages", bookmarks);
					setTimeout(() => {
						window.dispatchEvent(new CustomEvent("gm-bookmarks-updated"));
					}, 100);
				}
			}
		}
	};
	var FloatingNavComponent = ({ app, floatingNavigatorInstance, signals }) => {
		const containerRef = A(null);
		const settings = app.state.settings;
		const { isAutoLoading, progressPercent, batchCopyMode, isBarVisible, floatingNavOpacity, autoLoadTooltip, batchCopyTooltip } = signals;
		const getCore = () => app.modules.postNavigatorCore;
		const getLoader = () => app.modules.contentAutoLoader;
		y$2(() => {
			if (containerRef.current) floatingNavigatorInstance.container = containerRef.current;
			return () => {
				floatingNavigatorInstance.container = null;
			};
		}, [floatingNavigatorInstance]);
		y$2(() => {
			const handleMouseUp = () => {
				const c = getCore();
				if (c) c.stopContinuousNavigation();
			};
			document.body.addEventListener("mouseup", handleMouseUp);
			return () => {
				document.body.removeEventListener("mouseup", handleMouseUp);
			};
		}, [app]);
		y$2(() => {
			const handleVisibilityUpdate = () => {
				floatingNavigatorInstance.updateVisibility();
			};
			window.addEventListener("historyChange", handleVisibilityUpdate);
			const observer = new MutationObserver(app.utils.throttle(handleVisibilityUpdate, 200));
			observer.observe(document.body, {
				childList: true,
				subtree: true
			});
			handleVisibilityUpdate();
			return () => {
				window.removeEventListener("historyChange", handleVisibilityUpdate);
				observer.disconnect();
			};
		}, [app, floatingNavigatorInstance]);
		const handlePrevMouseDown = (e) => {
			if (e.button !== 0) return;
			const c = getCore();
			if (c) c.startContinuousNavigation("prev");
		};
		const handlePrevMouseLeave = () => {
			const c = getCore();
			if (c) c.stopContinuousNavigation();
		};
		const handlePrevContextMenu = (e) => {
			e.preventDefault();
			e.stopPropagation();
			const c = getCore();
			if ((c ? c.getSortedPosts() : []).length > 0 && c) c.updateActivePost(0, "manual");
		};
		const handleNextMouseDown = (e) => {
			if (e.button !== 0) return;
			const c = getCore();
			if (c) c.startContinuousNavigation("next");
		};
		const handleNextMouseLeave = () => {
			const c = getCore();
			if (c) c.stopContinuousNavigation();
		};
		const handleNextContextMenu = (e) => {
			e.preventDefault();
			e.stopPropagation();
			const c = getCore();
			const posts = c ? c.getSortedPosts() : [];
			if (posts.length > 0 && c) c.updateActivePost(posts.length - 1, "manual");
		};
		const handleAutoLoadClick = () => {
			const loader = getLoader();
			if (loader) if (loader.state.isRunning) loader.stop("autoLoad_status_stopped");
			else loader.start();
		};
		const handleAutoLoadContextMenu = (e) => {
			e.preventDefault();
			e.stopPropagation();
			const loader = getLoader();
			if (loader) loader.toggleMode();
		};
		const handleBatchCopyClick = () => {
			const loader = getLoader();
			if (loader) loader.copyAllPosts();
		};
		const handleBatchCopyContextMenu = (e) => {
			e.preventDefault();
			e.stopPropagation();
			const loader = getLoader();
			if (loader) loader.toggleBatchCopyMode();
		};
		return u("div", {
			ref: containerRef,
			className: `gm-floating-nav ${isAutoLoading.value ? "gm-running" : ""}`,
			"data-opacity": floatingNavOpacity.value ? "true" : "false",
			style: { display: isBarVisible.value ? "flex" : "none" },
			children: [
				u("button", {
					title: app.state.T.floatingNavPrevTooltip,
					onMouseDown: handlePrevMouseDown,
					onMouseLeave: handlePrevMouseLeave,
					onContextMenu: handlePrevContextMenu,
					children: u("svg", {
						viewBox: "0 0 24 24",
						children: u("path", { d: "M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" })
					})
				}),
				u("button", {
					title: app.state.T.floatingNavNextTooltip,
					onMouseDown: handleNextMouseDown,
					onMouseLeave: handleNextMouseLeave,
					onContextMenu: handleNextContextMenu,
					children: u("svg", {
						viewBox: "0 0 24 24",
						children: u("path", { d: "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z" })
					})
				}),
				(settings.floatingNav_showAutoLoad || settings.floatingNav_showBatchCopy) && u("div", { style: { height: "4px" } }),
				settings.floatingNav_showAutoLoad && u("button", {
					className: "gm-auto-load-btn",
					title: autoLoadTooltip.value,
					onClick: handleAutoLoadClick,
					onContextMenu: handleAutoLoadContextMenu,
					style: {
						position: "relative",
						display: "flex",
						alignItems: "center",
						justifyContent: "center",
						borderColor: isAutoLoading.value ? "transparent" : "#ddd"
					},
					children: [u("svg", {
						className: "gm-progress-ring",
						viewBox: "0 0 44 44",
						style: {
							position: "absolute",
							top: 0,
							left: 0,
							width: "44px",
							height: "44px",
							transform: "rotate(-90deg)",
							pointerEvents: "none",
							opacity: isAutoLoading.value ? 1 : 0,
							transition: "opacity 0.3s"
						},
						children: [u("circle", {
							cx: "22",
							cy: "22",
							r: "20",
							fill: "none",
							stroke: "#ddd",
							"stroke-width": "2.5",
							style: { opacity: .3 }
						}), u("circle", {
							className: "gm-progress-circle",
							cx: "22",
							cy: "22",
							r: "20",
							fill: "none",
							stroke: "#1877F2",
							"stroke-width": "2.5",
							"stroke-dasharray": "125.66",
							"stroke-dashoffset": 125.66 - progressPercent.value * 125.66,
							"stroke-linecap": "round",
							style: { transition: "stroke-dashoffset 0.3s ease" }
						})]
					}), u("span", {
						className: "gm-icon-wrapper",
						style: {
							zIndex: 1,
							display: "flex"
						},
						children: isAutoLoading.value ? u("svg", {
							viewBox: "0 0 24 24",
							fill: "#e02424",
							children: u("path", { d: "M6 6h12v12H6z" })
						}) : u("svg", {
							viewBox: "0 0 24 24",
							children: u("path", { d: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" })
						})
					})]
				}),
				settings.floatingNav_showBatchCopy && u("button", {
					title: batchCopyTooltip.value,
					onClick: handleBatchCopyClick,
					onContextMenu: handleBatchCopyContextMenu,
					children: batchCopyMode.value === "file" ? u("svg", {
						viewBox: "0 0 24 24",
						children: u("path", { d: "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z" })
					}) : u("svg", {
						viewBox: "0 0 24 24",
						children: u("path", { d: "M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" })
					})
				})
			]
		});
	};
	var FloatingNavigator = class {
		app;
		rootEl = null;
		container = null;
		isInitialized = false;
		signals = {
			isAutoLoading: y$1(false),
			progressPercent: y$1(0),
			batchCopyMode: y$1("file"),
			isBarVisible: y$1(false),
			floatingNavOpacity: y$1(false),
			autoLoadTooltip: y$1(""),
			batchCopyTooltip: y$1("")
		};
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.isInitialized) return;
			if (!this.app.state.settings.floatingNavEnabled) return;
			const settings = this.app.state.settings;
			this.signals.floatingNavOpacity.value = !!settings.floatingNavOpacity;
			const TActions = this.app.modules.transparencyActions;
			if (TActions && TActions.container) TActions.container.dataset.opacity = settings.floatingNavOpacity ? "true" : "false";
			const loader = this.app.modules.contentAutoLoader;
			if (loader) this.signals.batchCopyMode.value = loader.state.batchCopyMode === "clipboard" ? "clipboard" : "file";
			this.updateButtonTooltip();
			this.updateBatchCopyTooltip();
			this.updateVisibility();
			if (!document.getElementById("gm-dynamic-styles-opacity")) {
				const style = document.createElement("style");
				style.id = "gm-dynamic-styles-opacity";
				style.innerHTML = `
        .gm-floating-nav[data-opacity="true"] { opacity: 0.1; transition: opacity 0.3s; }
        .gm-floating-nav[data-opacity="true"]:hover { opacity: 1 !important; }
        .gm-floating-nav.gm-running { opacity: 1 !important; }
        /* When running, make non-hovered sibling buttons semi-transparent */
        .gm-floating-nav.gm-running button:not(.gm-auto-load-btn):not(:hover) { opacity: 0.4; filter: grayscale(0.5); }
        /* Highlight state for bookmarked pages/groups */
        .gm-floating-nav button.gm-bookmarked { background-color: #FFFDF0 !important; border: 1px solid #F5C33B !important; box-shadow: 0 4px 12px rgba(245, 195, 59, 0.3) !important; }
        .gm-floating-nav button.gm-bookmarked:hover { background-color: #FFFBE0 !important; box-shadow: 0 6px 16px rgba(245, 195, 59, 0.4) !important; }
      `;
				document.head.appendChild(style);
			}
			this.rootEl = document.createElement("div");
			this.rootEl.id = "gm-floating-root";
			document.body.appendChild(this.rootEl);
			R(u(FloatingNavComponent, {
				app: this.app,
				floatingNavigatorInstance: this,
				signals: this.signals
			}), this.rootEl);
			this.isInitialized = true;
		}
		deinit() {
			if (!this.isInitialized) return;
			if (this.rootEl) {
				R(null, this.rootEl);
				this.rootEl.remove();
				this.rootEl = null;
			}
			const style = document.getElementById("gm-dynamic-styles-opacity");
			if (style) style.remove();
			this.container = null;
			this.isInitialized = false;
		}
		updateOpacityState(enabled) {
			this.signals.floatingNavOpacity.value = enabled;
			const TActions = this.app.modules.transparencyActions;
			if (TActions && TActions.container) TActions.container.dataset.opacity = enabled ? "true" : "false";
		}
		updateButtonState(state) {
			const isRunning = state === "start";
			this.signals.isAutoLoading.value = isRunning;
			this.updateButtonTooltip();
		}
		updateProgress(current, target) {
			if (target > 0) this.signals.progressPercent.value = Math.min(Math.max(current / target, 0), 1);
			else this.signals.progressPercent.value = 1;
		}
		updateButtonTooltip() {
			const T = this.app.state.T;
			if (this.signals.isAutoLoading.value) {
				this.signals.autoLoadTooltip.value = T.tooltipAutoLoadStop || "Stop auto load";
				return;
			}
			const loader = this.app.modules.contentAutoLoader;
			const mode = loader ? loader.state.mode : "incremental";
			const batchSize = this.app.state.settings.autoLoadBatchSize || 20;
			const tooltip = mode === "incremental" ? T.autoLoad_tooltip_incremental.replace("{n}", batchSize.toString()) : T.autoLoad_tooltip_target.replace("{n}", batchSize.toString());
			this.signals.autoLoadTooltip.value = tooltip;
		}
		updateBatchCopyTooltip() {
			const T = this.app.state.T;
			const loader = this.app.modules.contentAutoLoader;
			const mode = loader ? loader.state.batchCopyMode : "clipboard";
			this.signals.batchCopyMode.value = mode === "clipboard" ? "clipboard" : "file";
			const modeLabel = mode === "clipboard" ? T.batchCopyMode_clipboard || "Clipboard" : T.batchCopyMode_file || "Download as File";
			this.signals.batchCopyTooltip.value = `${T.tooltipBatchCopy || "Batch Export"}\n[${modeLabel}]`;
		}
		updateVisibility() {
			const isVisible = this.app.utils.isFeedPage() && !document.querySelector(this.app.config.SELECTORS.GLOBAL.DIALOG);
			this.signals.isBarVisible.value = isVisible;
		}
	};
	var WheelNavigator = class {
		app;
		isCoolingDown = false;
		wheelListener = null;
		isInitialized = false;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.isInitialized) return;
			if (!this.app.state.settings.wheelNavEnabled) return;
			this.isInitialized = true;
			this.wheelListener = this.handleWheel.bind(this);
			document.addEventListener("wheel", this.wheelListener, { passive: false });
		}
		deinit() {
			if (!this.isInitialized) return;
			if (this.wheelListener) {
				document.removeEventListener("wheel", this.wheelListener);
				this.wheelListener = null;
			}
			this.isInitialized = false;
		}
		handleWheel(event) {
			if (this.isCoolingDown) return;
			if (!this.app.utils.isFeedPage() || document.querySelector(this.app.config.SELECTORS.GLOBAL.DIALOG)) return;
			const modifierKey = this.app.state.settings.wheelNavModifier;
			if (modifierKey !== "none") {
				if (!event[modifierKey]) return;
			}
			event.preventDefault();
			event.stopPropagation();
			const direction = event.deltaY > 0 ? "next" : "prev";
			const core = this.app.modules.postNavigatorCore;
			if (core) core.navigateToPost(direction);
			this.isCoolingDown = true;
			setTimeout(() => {
				this.isCoolingDown = false;
			}, this.app.state.settings.continuousNavInterval);
		}
	};
	var ClickToFocusNavigator = class {
		app;
		clickListener = null;
		isInitialized = false;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.isInitialized) return;
			const settings = this.app.state.settings;
			if (!settings.keyboardNavEnabled && !settings.floatingNavEnabled && !settings.wheelNavEnabled) return;
			this.isInitialized = true;
			this.clickListener = this.handleClick.bind(this);
			document.body.addEventListener("click", this.clickListener);
		}
		deinit() {
			if (!this.isInitialized) return;
			if (this.clickListener) {
				document.body.removeEventListener("click", this.clickListener);
				this.clickListener = null;
			}
			this.isInitialized = false;
		}
		handleClick(event) {
			const target = event.target;
			if (!target) return;
			if (target.closest("a, button, [role=\"button\"], input, textarea") || window.getSelection()?.toString().length) return;
			const post = target.closest("[role=\"article\"][aria-posinset]");
			if (!post) return;
			if (post.closest(this.app.config.SELECTORS.GLOBAL.DIALOG)) return;
			const core = this.app.modules.postNavigatorCore;
			if (!core) return;
			const C = this.app.config;
			const currentHighlighted = document.querySelector(`.${C.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS}`);
			if (currentHighlighted && currentHighlighted !== post) currentHighlighted.classList.remove(C.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS);
			post.classList.add(C.SELECTORS.NAVIGATOR.HIGHLIGHT_CLASS);
			const newIndex = core.getSortedPosts().findIndex((p) => p === post);
			if (newIndex !== -1) core.updateActivePost(newIndex, "scroll");
		}
	};
	var FollowingExtractor = class {
		app;
		fab = null;
		observer = null;
		isInitialized = false;
		constructor(app) {
			this.app = app;
		}
		init() {
			if (this.isInitialized) return;
			window.addEventListener("historyChange", () => this.checkAndRenderFab());
			this.observer = new MutationObserver(this.app.utils.throttle(() => this.checkAndRenderFab(), 300));
			this.observer.observe(document.body, {
				childList: true,
				subtree: true
			});
			this.checkAndRenderFab();
			this.isInitialized = true;
		}
		deinit() {
			if (!this.isInitialized) return;
			if (this.observer) {
				this.observer.disconnect();
				this.observer = null;
			}
			this.removeFab();
			this.isInitialized = false;
		}
		checkAndRenderFab() {
			if (window.location.pathname.includes("/following")) this.renderFab();
			else this.removeFab();
		}
		renderFab() {
			if (this.fab) return;
			const buttonTitle = this.app.state.T.following_copy_button_title || "Copy Following List";
			const fabEl = this.app.utils.createStyledElement("div", {}, {
				className: "gm-following-fab",
				title: buttonTitle,
				innerHTML: `
        <span class="gm-following-fab-icon">
          <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
            <path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/>
          </svg>
        </span>
        <span class="gm-following-fab-text">${buttonTitle}</span>
      `,
				on: { click: () => this.extractAndCopy() }
			});
			this.fab = fabEl;
			document.body.appendChild(fabEl);
		}
		removeFab() {
			if (this.fab) {
				this.fab.remove();
				this.fab = null;
			}
		}
		async extractAndCopy() {
			if (!this.fab || this.fab.classList.contains("gm-success")) return;
			const T = this.app.state.T;
			const C = this.app.config.SELECTORS.EXTRACTOR;
			const originalContent = this.fab.innerHTML;
			try {
				const sectionSelector = C?.FOLLOWING_CONTAINER || "[data-pagelet=\"ProfileAppSection_0\"]";
				const itemSelector = C?.FOLLOWING_ITEM || "div.x1iyjqo2.xv54qhq";
				const section = document.querySelector(sectionSelector);
				if (!section) {
					this.app.modules.toastNotifier.show(T.following_copy_failed || "Failed to extract following list", "failure");
					return;
				}
				const nameContainers = section.querySelectorAll(itemSelector);
				const extracted = [];
				nameContainers.forEach((container) => {
					const a = container.querySelector("a");
					let name = "";
					let url = null;
					if (a) {
						url = a.getAttribute("href");
						if (url) try {
							const urlObj = new URL(url, window.location.origin);
							this.app.utils.cleanUrlParams(urlObj);
							const cleanedUrl = urlObj.toString();
							try {
								url = decodeURIComponent(cleanedUrl);
							} catch (decodeErr) {
								url = cleanedUrl;
							}
						} catch (e) {}
						name = cleanDomText(a);
					} else {
						const span = container.querySelector("span");
						if (span) name = span.textContent.trim();
					}
					if (name) extracted.push({
						name,
						url
					});
				});
				if (extracted.length === 0) {
					this.app.modules.toastNotifier.show(T.following_copy_failed || "Failed to extract following list", "failure");
					return;
				}
				const formattedText = extracted.map((item) => {
					if (item.url) return `${item.name} (${item.url})`;
					return item.name;
				}).join("\n");
				if (typeof GM_setClipboard === "function") GM_setClipboard(formattedText);
				const successMsg = (T.following_copy_success || "Copied {count} following items!").replace("{count}", extracted.length.toString());
				this.app.modules.toastNotifier.show(successMsg, "success");
				this.fab.classList.add("gm-success");
				const successText = this.fab.querySelector(".gm-following-fab-text");
				const successIcon = this.fab.querySelector(".gm-following-fab-icon");
				if (successText) successText.textContent = successMsg;
				if (successIcon) successIcon.innerHTML = `
          <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
            <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
          </svg>
        `;
				await this.app.utils.delay(3e3);
				if (this.fab) {
					this.fab.classList.remove("gm-success");
					this.fab.innerHTML = originalContent;
				}
			} catch (error) {
				console.error(`${this.app.config.LOG_PREFIX} [FollowingExtractor] Error:`, error);
				this.app.modules.toastNotifier.show(T.following_copy_failed || "Failed to extract following list", "failure");
			}
		}
	};
	var MainApp = class {
		config = config;
		styles = {};
		state = {
			settings: {},
			T: {},
			cachedPageID: null,
			currentPath: "",
			lastActivePost: null
		};
		utils = utils_exports;
		modules = {};
		init() {
			let lang = GM_getValue("appLanguage", "auto");
			if (lang === "auto") lang = navigator.language.toLowerCase();
			if (lang.startsWith("ja")) this.state.T = translations.ja;
			else if (lang.startsWith("zh")) this.state.T = translations["zh-TW"];
			else this.state.T = translations.en;
			console.log("[FB Login Wall Remover] Initializing in language:", lang);
			const toastNotifier = new ToastNotifier(this);
			this.modules.toastNotifier = toastNotifier;
			const settingsMdl = new SettingsModal(this);
			this.modules.settingsModal = settingsMdl;
			const settingsMgr = new SettingsManager(this);
			this.modules.settingsManager = settingsMgr;
			settingsMgr.init();
			const domCleaner = new DomCleaner(this);
			this.modules.domCleaner = domCleaner;
			const uiCleaner = new UiCleaner(this);
			this.modules.uiCleaner = uiCleaner;
			const contentExpander = new ContentExpander(this);
			this.modules.contentExpander = contentExpander;
			const linkIntervention = new LinkIntervention(this);
			this.modules.linkIntervention = linkIntervention;
			const styleInjector = new StyleInjector(this);
			this.modules.styleInjector = styleInjector;
			const errorRecovery = new ErrorRecovery(this);
			this.modules.errorRecovery = errorRecovery;
			const contentAutoLoader = new ContentAutoLoader(this);
			this.modules.contentAutoLoader = contentAutoLoader;
			const transparencyActions = new TransparencyActions(this);
			this.modules.transparencyActions = transparencyActions;
			const adsLibraryHandler = new AdsLibraryHandler(this);
			this.modules.adsLibraryHandler = adsLibraryHandler;
			const internalTransparencyHandler = new InternalTransparencyHandler(this);
			this.modules.internalTransparencyHandler = internalTransparencyHandler;
			const idRevealer = new IdRevealer(this);
			this.modules.idRevealer = idRevealer;
			const postNavigatorCore = new PostNavigatorCore(this);
			this.modules.postNavigatorCore = postNavigatorCore;
			const postHeaderTools = new PostHeaderTools(this);
			this.modules.postHeaderTools = postHeaderTools;
			const timelineNavigator = new TimelineNavigator(this);
			this.modules.timelineNavigator = timelineNavigator;
			const keyboardNavigator = new KeyboardNavigator(this);
			this.modules.keyboardNavigator = keyboardNavigator;
			const scrollRestorer = new ScrollRestorer(this);
			this.modules.scrollRestorer = scrollRestorer;
			const autoUnmuter = new AutoUnmuter(this);
			this.modules.autoUnmuter = autoUnmuter;
			const postNumbering = new PostNumbering(this);
			this.modules.postNumbering = postNumbering;
			const searchBar = new SearchBar(this);
			this.modules.searchBar = searchBar;
			const floatingNavigator = new FloatingNavigator(this);
			this.modules.floatingNavigator = floatingNavigator;
			const wheelNavigator = new WheelNavigator(this);
			this.modules.wheelNavigator = wheelNavigator;
			const clickToFocusNavigator = new ClickToFocusNavigator(this);
			this.modules.clickToFocusNavigator = clickToFocusNavigator;
			const followingExtractor = new FollowingExtractor(this);
			this.modules.followingExtractor = followingExtractor;
			const scrollInt = new ScrollInterceptor(this);
			const historyInt = new HistoryInterceptor(this);
			scrollInt.init();
			historyInt.init();
			window.addEventListener("DOMContentLoaded", () => {
				console.log("[FB Login Wall Remover] DOM Content Loaded. Initializing modules...");
				const LOG = "[FB Login Wall Remover]";
				let successCount = 0;
				let failCount = 0;
				const initModule = (name, moduleFn) => {
					try {
						moduleFn();
						successCount++;
						console.log(`${LOG} ✅ Module initialized: ${name}`);
					} catch (error) {
						failCount++;
						console.error(`${LOG} ❌ Failed to initialize module '${name}':`, error);
					}
				};
				initModule("domCleaner", () => this.modules.domCleaner.init());
				initModule("linkIntervention", () => this.modules.linkIntervention.init());
				initModule("styleInjector", () => this.modules.styleInjector.init());
				if (this.state.settings.hideUselessElements) initModule("uiCleaner", () => this.modules.uiCleaner.init());
				if (this.state.settings.expandContentEnabled) initModule("contentExpander", () => this.modules.contentExpander.init());
				if (this.state.settings.errorRecoveryEnabled) initModule("errorRecovery", () => this.modules.errorRecovery.init());
				initModule("contentAutoLoader", () => this.modules.contentAutoLoader.init());
				if (this.state.settings.transparencyButtonsEnabled) initModule("transparencyActions", () => this.modules.transparencyActions.init());
				initModule("adsLibraryHandler", () => this.modules.adsLibraryHandler.init());
				initModule("internalTransparencyHandler", () => this.modules.internalTransparencyHandler.init());
				if (this.state.settings.idRevealerEnabled) initModule("idRevealer", () => this.modules.idRevealer.init());
				initModule("postNavigatorCore", () => this.modules.postNavigatorCore.init());
				initModule("postHeaderTools", () => this.modules.postHeaderTools.init());
				if (this.state.settings.timelineNavEnabled) initModule("timelineNavigator", () => this.modules.timelineNavigator.init());
				if (this.state.settings.keyboardNavEnabled) initModule("keyboardNavigator", () => this.modules.keyboardNavigator.init());
				initModule("scrollRestorer", () => this.modules.scrollRestorer.init());
				initModule("autoUnmuter", () => this.modules.autoUnmuter.init());
				if (this.state.settings.postNumberingEnabled) initModule("postNumbering", () => this.modules.postNumbering.init());
				if (this.state.settings.hideUselessElements) initModule("searchBar", () => this.modules.searchBar.init());
				if (this.state.settings.floatingNavEnabled) initModule("floatingNavigator", () => this.modules.floatingNavigator.init());
				if (this.state.settings.wheelNavEnabled) initModule("wheelNavigator", () => this.modules.wheelNavigator.init());
				initModule("clickToFocusNavigator", () => this.modules.clickToFocusNavigator.init());
				initModule("followingExtractor", () => this.modules.followingExtractor.init());
				console.log(`${LOG} All modules processed. Success: ${successCount}, Failed: ${failCount}`);
				if (failCount > 0) console.warn(`${LOG} ⚠️ ${failCount} module(s) failed to initialize. Check errors above.`);
				setTimeout(() => this.cleanOldFpcTasks(), 3e3);
			});
		}
		cleanOldFpcTasks() {
			this.runGarbageCollection();
		}
		runGarbageCollection() {
			if (typeof GM_listValues !== "function" || typeof GM_deleteValue !== "function") return;
			try {
				const keys = GM_listValues();
				let cleanedCount = 0;
				const activeSettingKeys = new Set();
				if (this.modules.settingsManager?.definitions) this.modules.settingsManager.definitions.forEach((def) => {
					activeSettingKeys.add(def.key);
				});
				const persistentKeys = new Set([
					"appLanguage",
					"autoLoadMode",
					"batchCopyMode",
					"isSearchBarPinned",
					"bookmarked_posts",
					"bookmarked_pages",
					"bookmarked_folders"
				]);
				const transientKeys = ["fblwr_ads_target_id", "fblwr_int_action"];
				const isAdsPage = window.location.pathname.includes("/ads/library/");
				const isTransparencyPage = window.location.href.includes("about_profile_transparency");
				for (const key of keys) {
					if (typeof key !== "string") continue;
					if (key.startsWith("fpc_")) {
						GM_deleteValue(key);
						cleanedCount++;
						continue;
					}
					if (transientKeys.includes(key)) {
						if (!(key === "fblwr_ads_target_id" && isAdsPage || key === "fblwr_int_action" && isTransparencyPage)) {
							GM_deleteValue(key);
							cleanedCount++;
						}
						continue;
					}
					if (!(activeSettingKeys.has(key) || persistentKeys.has(key))) {
						GM_deleteValue(key);
						cleanedCount++;
					}
				}
				if (cleanedCount > 0) console.log(`[FB Login Wall Remover] Garbage collection: Cleaned up ${cleanedCount} orphaned or stale keys.`);
			} catch (e) {
				console.error("[FB Login Wall Remover] Error during garbage collection:", e);
			}
		}
		async handleWorkerTask() {
			await new WorkerHandler().run();
		}
	};
	if (new URLSearchParams(window.location.search).has("fpc_worker_task")) {
		const app = new MainApp();
		window.addEventListener("DOMContentLoaded", () => app.handleWorkerTask());
	} else if (isLoggedIn()) console.log("[FB Login Wall Remover] Logged-in state detected. Script terminated.");
	else {
		console.log("[FB Login Wall Remover] Logged-out state detected. Script active.");
		new MainApp().init();
	}
})();